参考文章:mp.weixin.qq.com/s/B7n_dLC9r…
1、自定义指令
vue2用法
vue2中使用的钩子如下:
- bind - 指令绑定到元素后发生。只发生一次。
- inserted - 元素插入父 DOM 后发生。
- update - 当元素更新,但子元素尚未更新时,将调用此钩子。
- componentUpdated - 一旦组件和子级被更新,就会调用这个钩子。
- unbind - 一旦指令被移除,就会调用这个钩子。也只调用一次。
<p v-highlight="'yellow'">高亮显示此文本亮黄色</p>
Vue.directive('highlight', {
bind(el, binding, vnode) {
el.style.background = binding.value
}
})
vue3用法
vue3中使用的钩子如下:
created
- 新的!在元素的 attribute 或事件侦听器应用之前调用。- bind →
beforeMount
- inserted →
mounted
beforeUpdate
:新的!这是在元素本身更新之前调用的,很像组件生命周期钩子。- update → 移除!有太多的相似之处要更新,所以这是多余的,请改用 updated。
- componentUpdated →
updated
beforeUnmount
:新的!与组件生命周期钩子类似,它将在卸载元素之前调用。- unbind ->
unmounted
<p v-highlight="'yellow'">高亮显示此文本亮黄色</p>
const app = Vue.createApp({})
app.directive('highlight', {
beforeMount(el, binding, vnode) {
el.style.background = binding.value
}
})
2、过滤器
vue2用法
<template>
<h1>Bank Account Balance</h1>
<p>{{ accountBalance | currencyUSD }}</p>
</template>
<script>
export default {
props: {
accountBalance: {
type: Number,
required: true
}
},
filters: {
currencyUSD(value) {
return '$' + value
}
}
}
</script>
vue3用法
在vue3中过滤器已经废弃,建议使用方法调用或计算属性computed
<template>
<h1>Bank Account Balance</h1>
<p>{{ accountInUSD }}</p>
</template>
<script>
export default {
props: {
accountBalance: {
type: Number,
required: true
}
},
computed: {
accountInUSD() {
return '$' + this.accountBalance
}
}
}
</script>
全局属性定义
// main.js
const app = createApp(App)
//定义
app.config.globalProperties.$filters = {
currencyUSD(value) {
return '$' + value
}
}
//使用
<template>
<h1>Bank Account Balance</h1>
<p>{{ $filters.currencyUSD(accountBalance) }}</p>
</template>
注意:
这种方式只能用于方法中,不可以在计算属性中使用,因为后者只有在单个组件的上下文中定义时才有意义。
3、片段
vue2用法
vue2中不支持多根节点组件
<template>
<div>
<header>...</header>
<main>...</main>
<footer>...</footer>
</div>
</template>
vue3用法
vue3中支持多根节点组件:
<template>
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
</template>
4、v-if 与 v-for 的优先级
vue2中
在一个元素上同时使用 v-if 和 v-for 时,v-for 会优先作用
vue3中
v-if 总是优先于 v-for 生效
5、插槽
子组件
<slot name="content" :data="data"></slot>
export default {
data(){
return{
data:["走过来人来人往","不喜欢也得欣赏","陪伴是最长情的告白"]
}
}
}
vue2中
<!-- 父组件中使用 -->
<template slot="content" slot-scope="scoped">
<div v-for="item in scoped.data">{{item}}</div>
</template>
vue3中
<!-- 父组件中使用 -->
<template v-slot:content="scoped">
<div v-for="item in scoped.data">{{item}}</div>
</template>
<!-- 也可以简写成: -->
<template #content="{data}">
<div v-for="item in data">{{item}}</div>
</template>
6、v-model
vue2中
组件上使用 v-model其实就相当于传递了value属性, 并触发了input事件
<search-input v-model="searchValue"><search-input>
<!-- 相当于 -->
<search-input :value="searchValue" @input="searchValue=$event"><search-input>
vue3中
组件上使用 v-model其实就相当于传递一个modelValue 属性, 同时触发一个update:modelValue事件,而且同一个组件可以同时使用多个
v-model
<modal v-model:visible="isVisible" v-model:content="content"></modal>
<!-- 相当于 -->
<modal :visible="isVisible" :content="content" @update:visible="isVisible" @update:content="content"/>
7、watch
vue2中
watch:{
person: {
handler(newVal,oldVal) {
// ...
},
deep: true,
immediate: true
}
}
vue3中
用法:watch(source, callback, [options])
参数说明:
- source: 可以支持 string,Object,Function,Array; 用于指定要侦听的响应式变量
- callback: 执行的回调函数
- options:支持 deep、immediate 和 flush 选项。
watch(
() => state.person,
(newVal, oldVal) => {
console.log("新值:", newVal, "老值:", oldVal);
},
{ deep: true }
);
8、生命周期
9、数据建立 data
vue2中
export default {
props: {
strProp: String
},
data () {
return {
value1: '',
value2: ''
}
}
}
vue3中
import { reactive } from 'vue'
export default {
props: {
strProp: String
},
setup (props,{emit,attrs,slot}) {
const state = reactive({
value1: '',
value2: ''
})
return { state }
}
}
使用setup时,它接受两个参数:
props: 组件传入的属性
context:包含三个属性attrs、slot 和emit
setup 中接受的props是响应式的, 当传入新的 props 时,会及时被更新。由于是响应式的, 所以
不可以使用 ES6 解构,解决办法就是使用toRefs
。toRefs 用于将一个 reactive 对象转化为属性全部为 ref 对象的普通对象(reactive用于处理对象的双向绑定,ref则既可以处理对象也可以处理基础类型的双向绑定)。setup中不能访问 Vue2 中最常用的this对象,解构会消除它的响应式,所以context中就提供了this中最常用的三个属性:attrs、slot 和emit
。
ref、toRef、toRefs的区别:
ref 就当作简单的响应式变量 toRef 就是把不是响应式的对象转化成响应式 toRefs 就是把响应式的reactive对象,分解成无数的响应式 ref
setup() {
const obj = ref({count:1, name:"张三"});//ref处理对象
setTimeout(() =>{
obj.value.count = obj.value.count + 1;
obj.value.name = "李四";
}, 1000)
return{obj}
}
setup() {
const year = ref(0);//ref处理基础类型
const user = reactive({ nickname: "xiaofan", age: 26, gender: "女" });//reactive处理对象
return {year,user};
},
// 使用toRefs
setup() {
const year = ref(0);
const user = reactive({ nickname: "xiaofan", age: 26, gender: "女" });
return {year,...toRefs(user)};//使用toRefs处理reactive对象为 ref 对象
},