一、计算属性 - computed
computed
(计算属性)在 Vue 2 和 Vue 3 中都能使用,主要用于处理依赖响应式数据的计算逻辑,它的值会根据依赖的变化自动更新,同时有缓存,比 methods
更高效。
1. 基本使用
示例:把 message
转换为大写
<div id="app"><p>原始文本: {{ message }}</p><p>大写文本: {{ upperMessage }}</p>
</div><script>
new Vue({el: '#app',data: {message: 'hello vue'},computed: {upperMessage() {return this.message.toUpperCase()}}
})
</script>
upperMessage
依赖 message
,当 message
变化时,它会自动更新。
computed
有缓存,只有依赖的数据变化时才会重新计算,比 methods
更高效。
2. 计算属性 vs 方法 (methods
)
<div id="app"><p>{{ upperMessage() }}</p>
</div><script>
new Vue({el: '#app',data: {message: 'hello vue'},methods: {upperMessage() {return this.message.toUpperCase()}}
})
</script>
区别:
computed
有缓存,只在message
变化时重新计算。methods
每次调用都会重新执行,即使message
没变,仍然会运行函数。
✅ 结论:
- 用
computed
处理依赖数据的计算,它只会在需要时计算,性能更好。 - 用
methods
处理事件或不需要缓存的逻辑。
3. 计算属性的 getter 和 setter
computed
默认只有 getter
(读取),但也可以加 setter
(写入):
<div id="app"><input v-model="fullName">
</div><script>
new Vue({el: '#app',data: {fullName: '张 三'},computed: {fullName: {get() {return this.firstName + ' ' + this.lastName},set(newValue) {const names = newValue.split(' ')this.lastName = names[0]this.firstName = names[1] || ''}}}
})
</script>
4. 依赖多个属性
computed
可以依赖多个 data
变量:
<div id="app"><p>{{ userInfo }}</p>
</div><script>
new Vue({el: '#app',data: {firstName: '三',lastName: '张',age: '18'},computed: {userInfo() {return `${this.lastName} ${this.firstName} - ${this.age}岁`}}
})
</script>
任何 firstName
、lastName
、age
变化,userInfo
都会自动更新。
5. 计算属性在 Vue 3 中的写法
Vue 3 组合式 API 中,computed
需要 import
:
import { ref, computed } from 'vue'export default {setup() {const message = ref('hello vue3')const upperMessage = computed(() => message.value.toUpperCase())return { message, upperMessage }}
}
Vue 3 computed
需要 .value
访问 ref
的数据。
总结
✅ computed
计算属性的特点:
- 有缓存,只有依赖数据变化时才会重新计算,比
methods
更高效。 - 适用于依赖多个
data
属性的计算逻辑。 - 可以有
getter
和setter
,适用于双向绑定。 - 在 Vue 3 组合式 API 里,需要
computed(() => {})
使用。
🔹 适用场景:
- 格式化数据(大写、日期、货币格式化等)
- 合并多个
data
变量 - 计算总价、折扣、平均值等
🚀 如果数据要频繁计算,优先用 computed
,避免 methods
造成不必要的计算!
二、监听器 - watch
watch
主要用于监听数据的变化并执行特定逻辑,适用于数据变化后需要进行异步操作、复杂逻辑或性能优化的场景。
1. 基本用法
watch
用于监听 data
或 computed
里的数据变化,并在变化时执行函数。
<div id="app"><p>姓名: {{ name }}</p><input v-model="name">
</div><script>
new Vue({el: '#app',data: {name: '张三'},watch: {name(newVal, oldVal) {console.log(`姓名从 ${oldVal} 变成了 ${newVal}`)}}
})
</script>
name
发生变化时,watch
里的函数会被调用。newVal
是新值,oldVal
是旧值。- 每次
input
修改name
,都会触发watch
。
2. 监听多个数据
可以监听多个数据:
watch: {firstName(newVal) {console.log(`firstName 变了: ${newVal}`)},lastName(newVal) {console.log(`lastName 变了: ${newVal}`)}
}
3. 监听对象或数组
(1)监听对象的某个属性
data() {return {user: { name: '张三', age: 25 }}
},
watch: {'user.age'(newVal, oldVal) {console.log(`年龄从 ${oldVal} 变成了 ${newVal}`)}
}
(2)深度监听 (deep: true
)
如果监听整个对象,需要deep: true
data() {return {user: { name: '张三', age: 25 }}
},
watch: {user: {handler(newVal) {console.log('user 变了:', newVal)},deep: true}
}
任何 user
内部属性变化,watch
都会触发。
(3)监听数组
data() {return {items: [1, 2, 3]}
},
watch: {items: {handler(newVal) {console.log('数组变了:', newVal)},deep: true}
}
修改 items
数组(如 push/pop/splice
),都会触发 watch
。
4. 监听 computed
计算属性
computed: {fullName() {return this.firstName + ' ' + this.lastName}
},
watch: {fullName(newVal) {console.log(`fullName 变了: ${newVal}`)}
}
监听 computed
的值变化,适用于计算后的数据需要额外处理的情况
5. immediate
立即执行
默认情况下,watch
不会在组件创建时立即执行,但可以加 immediate: true
让它立即执行一次:
watch: {name: {handler(newVal) {console.log(`初始化时就执行: ${newVal}`)},immediate: true}
}
适用于组件初始化时就要执行的逻辑(如请求接口)。
6. 监听数据变化后执行异步操作
可以在 watch
里调用 API:
watch: {searchQuery(newVal) {clearTimeout(this.timer)this.timer = setTimeout(() => {this.fetchResults(newVal)}, 500) // 防抖,500ms 后执行}
}
适用于搜索输入时防止频繁请求 API。
7. Vue 3 watch
用法
在 Vue 3 组合式 API 中,使用 watch
需要 import
:
import { ref, watch } from 'vue'export default {setup() {const name = ref('张三')watch(name, (newVal, oldVal) => {console.log(`姓名从 ${oldVal} 变成了 ${newVal}`)})return { name }}
}
Vue 3 的 watch
监听 ref
数据时,需要 .value
访问数据。
总结
✅ watch
监听数据变化,并执行指定逻辑:
- 适用于异步操作、API 请求、防抖、复杂计算。
- 监听对象/数组时,需加
deep: true
。 - 监听
computed
计算属性,可处理衍生数据。 - 用
immediate: true
让watch
立即执行一次。 - Vue 3 需要
import { watch }
,且监听ref
需要.value
。
🚀 如果数据需要动态监听并执行操作,watch
是最佳选择!
三、过滤器 - filters
在数据被渲染之前,可以对其进行进一步处理,比如将字符截取或者将小写统一转换为大写等等,过滤器本身就是一个方法。过滤器可以定义全局或局部。
在 Vue 2 中,过滤器(filters
) 主要用于格式化文本,可以在 { { 插值表达式 }}
和 v-bind
绑定中使用。它本质上是一个函数,接收输入值,返回格式化后的值。
1. 全局 & 局部过滤器
Vue 2 提供全局过滤器和局部过滤器两种方式。
(1)全局过滤器
在 Vue.filter()
中定义,全局可用。
Vue.filter('uppercase', function(value) {if (!value) return ''return value.toString().toUpperCase()
})
然后在模板中使用:
<p>{{ 'hello' | uppercase }}</p>
<!-- 输出: HELLO -->
(2)局部过滤器
在组件的 filters
选项里定义,只在当前组件可用:
<div id="app"><!-- 输出: Hello world --><p>{{ message | capitalize }}</p>
<script>const vm = new Vue({el: '#app',data: {message: 'hello world'},filters: {capitalize(value) {if (!value) return ''return value.charAt(0).toUpperCase() + value.slice(1)}}})
2. 过滤器的多重使用
可以多个过滤器链式调用:
<p>{{ message | capitalize | uppercase }}</p>
3. 过滤器用于 v-bind
在 v-bind
中使用时,需要用方法调用的形式:
<input :value="message | capitalize">
Vue 3 认为 filters
在模板中容易混乱,移除了 filters
,建议改用计算属性(computed
)或方法:
<div id="app"><input :value="formattedMessage">
<script>const vm = new Vue({el: '#app',data: {message: 'hello'},computed: {formattedMessage() {return this.message.charAt(0).toUpperCase() + this.message.slice(1)}
} })
4. 过滤器的应用场景
- 格式化文本(如大小写转换)
- 货币格式化
- 时间格式化
- 数字千分位分隔
四、混入 - Mixins
mixins
(混入)是 Vue 里的一种代码复用机制,可以在多个组件之间共享逻辑,避免代码重复,提高可维护性。
1. 基本使用
创建一个 mixins
,然后在组件中使用它。
// 定义一个 mixin
const myMixin = {data() {return {message: 'Hello from mixin'}},created() {console.log('Mixin 的 created 钩子被调用')},methods: {greet() {console.log(this.message)}}
}
在组件中使用 mixins
new Vue({el: '#app',mixins: [myMixin], // 这里使用 mixincreated() {console.log('组件的 created 钩子被调用')}
})
组件会继承 mixins
里的 data
、methods
、生命周期钩子。
2. mixins
逻辑合并规则
Vue 组件和 mixins
可能有相同的 data
、methods
、生命周期钩子,Vue 按以下规则合并:
项 | 合并规则 |
data | 合并,但组件数据优先(mixin 里的数据不会覆盖组件) |
methods | 合并,但组件方法优先(mixin 方法被组件覆盖) |
生命周期钩子 | 都会执行,先 mixin ,后组件 |
3. data
合并
const myMixin = {data() {return {message: 'Hello from mixin'}}
}new Vue({mixins: [myMixin],data() {return {message: 'Hello from component'}},created() {console.log(this.message) // 输出:Hello from component}
})
data
以组件的为准,不会被 mixins
覆盖。
4. methods
合并
const myMixin = {methods: {sayHello() {console.log('Hello from mixin')}}
}new Vue({mixins: [myMixin],methods: {sayHello() {console.log('Hello from component')}},created() {this.sayHello() // 输出:Hello from component}
})
如果 methods
重名,组件的 methods
会覆盖 mixins
的方法。
5. 生命周期钩子合并
如果 mixins
和组件都有相同的生命周期钩子,它们都会执行,但 mixins
里的先执行。
const myMixin = {created() {console.log('Mixin created')}
}new Vue({mixins: [myMixin],created() {console.log('Component created')}
})
输出顺序:
Mixin created
Component created
6. 监听器 (watch
) 合并
mixins
和组件里的 watch
会合并执行:
const myMixin = {watch: {message(newVal) {console.log('Mixin watch:', newVal)}}
}new Vue({mixins: [myMixin],data() {return { message: 'Hello' }},watch: {message(newVal) {console.log('Component watch:', newVal)}}
})
message
变化时,两个 watch
都会执行。
7. 作用场景
- 封装 API 请求(如
axios
请求) - 封装全局
methods
(如格式化时间、数据处理等) - 监听路由变化
- 公共的
watch
监听逻辑 - 封装生命周期钩子逻辑
封装 API 请求
const fetchDataMixin = {data() {return { dataList: [] }},methods: {async fetchData(url) {const res = await fetch(url)this.dataList = await res.json()}}
}
在多个组件中复用
new Vue({mixins: [fetchDataMixin],created() {this.fetchData('https://api.example.com/data')}
})
8. Vue 3 替代方案
Vue 3 使用 Composition API
(setup()
+ composables
)来取代 mixins
:
import { ref, onMounted } from 'vue'export function useFetchData(url) {const dataList = ref([])const fetchData = async () => {const res = await fetch(url)dataList.value = await res.json()}onMounted(fetchData)return { dataList }
}
在组件中使用
import { useFetchData } from './useFetchData'export default {setup() {const { dataList } = useFetchData('https://api.example.com/data')return { dataList }}
}
总结
✅ mixins
主要用于代码复用,避免多个组件重复写相同逻辑:
data
、methods
、watch
、生命周期钩子都可以混入methods
、data
遇到重名,组件优先生命周期钩子
遇到重名,mixins
先执行- 适用于封装 API 请求、监听逻辑、全局方法等
🚀 Vue 3 推荐使用 Composition API
代替 mixins
,提高可读性和灵活性!
五、插件 - Plugin
Vue 的插件 (Plugins
) 是一种全局增强 Vue 功能的方式,适用于全局方法、指令、组件、混入、状态管理等,例如 Vue Router
、Vuex
、Element UI
等都是 Vue 插件。
1. Vue 插件的基本结构
Vue 插件本质上是一个包含 install
方法的对象或函数:
const MyPlugin = {install(Vue, options) {// 1. 添加全局方法Vue.prototype.$myMethod = function () {console.log('Hello from MyPlugin')}// 2. 添加全局指令Vue.directive('focus', {inserted(el) {el.focus()}})// 3. 添加全局混入Vue.mixin({created() {console.log('Mixin from MyPlugin')}})// 4. 注册全局组件Vue.component('MyComponent', {template: '<div>我是插件注册的全局组件</div>'})}
}export default MyPlugin
📌 插件可以:
- 扩展 Vue 实例(如
Vue.prototype.$xxx
) - 添加全局指令
- 注册全局组件
- 混入全局
mixin
- 提供全局配置
2. 在 Vue 2 中使用插件
在 Vue 组件或 main.js
中引入并安装插件:
import Vue from 'vue'
import MyPlugin from './MyPlugin.js'Vue.use(MyPlugin) // 安装插件new Vue({el: '#app'
})
Vue.use(MyPlugin)
让所有 Vue 组件都能使用插件提供的功能。
3. Vue 2 插件的使用示例
(1)全局方法
Vue.prototype.$alertMessage = function (msg) {alert(msg)
}
组件中使用
<template><button @click="$alertMessage('Hello from Plugin!')">点击我</button>
</template>
(2)全局指令
Vue.directive('focus', {inserted(el) {el.focus()}
})
组件中使用
<template><input v-focus />
</template>
输入框会在页面加载时自动获得焦点。
(3)注册全局组件
Vue.component('MyButton', {template: '<button>我是插件的按钮</button>'
})
组件中使用
<template><MyButton />
</template>
(4)全局混入 (mixin
)
Vue.mixin({created() {console.log('每个组件都会执行这个 mixin')}
})
所有组件 created
时都会执行这个逻辑。
4. Vue 3 中的插件
Vue 3 的插件仍然需要 install
方法,但 Vue.prototype
替换为 app.config.globalProperties
。
(1)创建 Vue 3 插件
const MyPlugin = {install(app, options) {// 1. 添加全局方法app.config.globalProperties.$sayHello = function () {console.log('Hello from MyPlugin')}// 2. 添加全局指令app.directive('focus', {mounted(el) {el.focus()}})// 3. 注册全局组件app.component('MyComponent', {template: '<div>我是 Vue 3 插件的组件</div>'})}
}export default MyPlugin
(2)在 Vue 3 中使用插件
import { createApp } from 'vue'
import App from './App.vue'
import MyPlugin from './MyPlugin.js'const app = createApp(App)
app.use(MyPlugin) // 安装插件
app.mount('#app')
5. 插件的应用场景
✅ 适用于全局功能扩展,如:
- 封装全局方法(如
axios
请求) - 封装全局指令(如
v-focus
自动聚焦) - 注册全局组件(如
MessageBox
组件) - 提供全局 mixin(如
beforeRouteEnter
逻辑) - 集成第三方库(如
Vue Router
、Vuex
、Element UI
)
6. 插件 vs 组件 vs mixins
对比项 | 插件 (Plugins ) | 组件 (Components ) | 混入 (Mixins ) |
---|---|---|---|
用途 | 扩展 Vue 全局功能 | 复用 UI 结构和逻辑 | 复用数据逻辑 |
注册方式 | Vue.use(MyPlugin) | Vue.component('MyComp', Comp) | mixins: [MyMixin] |
作用范围 | 影响所有组件 | 只在使用组件的地方生效 | 影响 mixins 使用的组件 |
适用场景 | 全局工具、API、指令 | 复用 UI 结构 | 复用方法、数据 |