Composition API
作用:将零散分布的逻辑组合起来一起维护,并且可以将大单独的功能逻辑查分成单独的文件
setup
是Vue3.x新增的一个选项,他是组件内使用Composition API的入口。
setup执行时机是在beforeCreate之前
setup参数
需要两个参数,1 props:组件传入的属性 2 context
setup中接收的props是响应式的,当传入新的props时候,会被更新;犹豫是响应式的,所以不能使用ES6的解构接收。
reactive、ref、toRefs
使用reactive和热发来进行数据绑定
1、reactive 用于为对象添加响应式状态。接收一个js对象作为参数,返回一个具有响应式状态的副本。
a、获取数据值的时候直接获取,不需要加.value
b、参数只能传入对象类型
2、ref 用于为数据添加响应式状态。由于reactive只能传入对象类型的参数,而对于基本数据类型要添加响应式状态就只能用ref了,同样返回一个具有响应式状态的副本。
a、获取数据值的时候需要加.value。(对于基本数据类型,ref是自己的实现方式且性能优于reactive,而对于对象类型,ref仍然是通过reactive包装实现的)
b、参数可以传递任意数据类型,传递对象类型时也能保持深度响应式,所以适用性更广。
c、vue 3.0 setup里定义数据时推荐优先使用ref,方便逻辑拆分和业务解耦。
3、toRef 用于为源响应式对象上的属性新建一个ref,从而保持对其源对象属性的响应式连接。接收两个参数:源响应式对象和属性名,返回一个ref数据。例如使用父组件传递的props数据时,要引用props的某个属性且要保持响应式连接时就很有用。
a、获取数据值的时候需要加.value
b、toRef后的ref数据不是原始数据的拷贝,而是引用,改变结果数据的值也会同时改变原始数据
4、toRefs 用于将响应式对象转换为结果对象,其中结果对象的每个属性都是指向原始对象相应属性的ref。常用于es6的解构赋值操作,因为在对一个响应式对象直接解构时解构后的数据将不再有响应式,而使用toRefs可以方便解决这一问题。
a、获取数据值的时候需要加.value
b、toRefs后的ref数据不是原始数据的拷贝,而是引用,改变结果数据的值也会同时改变原始数据
作用其实和 toRef 类似,只不过 toRef 是一个个手动赋值,而 toRefs 是自动赋值。
<template>
<div class="homePage">
<p>第 {{ year }} 年</p>
<p>姓名: {{ nickname }}</p>
<p>年龄: {{ age }}</p>
</div>
</template>
<script>
import { defineComponent, reactive, ref, toRefs } from "vue";
export default defineComponent({
setup() {
const year = ref(0);
const user = reactive({ nickname: "cc", age: 26, gender: "女" });
setInterval(() => {
year.value++;
user.age++;
}, 1000);
return {
year,
// 使用reRefs
...toRefs(user),
};
},
});
</script>
watch 用法
watch 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。
watch(source, callback, [options])
source: 可以支持 string,Object,Function,Array; 用于指定要侦听的响应式变量
callback: 执行的回调函数
options:支持 deep、immediate 和 flush 选项。
监听reactive
import { defineComponent, ref, reactive, toRefs, watch } from "vue";
export default defineComponent({
setup() {
const state = reactive({ nickname: "c", age: 20 });
setTimeout(() => {
state.age++;
}, 1000);
// 修改age值时会触发 watch的回调
watch(
() => state.age,
(curAge, preAge) => {
console.log("新值:", curAge, "老值:", preAge);
}
);
return {
...toRefs(state),
};
},
});
// 监听复杂对象
const state = reactive({
room: {
id: 100,
attrs: {
size: "140平方米",
type: "三室两厅",
},
},
});
watch(
() => state.room,
(newType, oldType) => {
console.log("新值:", newType, "老值:", oldType);
},
{ deep: true }
);
侦听 ref 定义的数据
const year = ref(0);
setTimeout(() => {
year.value++;
}, 1000);
watch(year, (newVal, oldVal) => {
console.log("新值:", newVal, "老值:", oldVal);
});
监听多个数据
watch([() => state.age, year], ([curAge, newVal], [preAge, oldVal]) => {
console.log("新值:", curAge, "老值:", preAge); console.log("新值:", newVal,
"老值:", oldVal); });
stop 停止监听
我们在组件中创建的
watch
监听,会在组件被销毁时自动停止。如果在组件销毁之前我们想要停止掉某个监听, 可以调用watch()
函数的返回值。
const stopWatchRoom = watch(() => state.room, (newType, oldType) => {
console.log("新值:", newType, "老值:", oldType);
}, {deep:true});
setTimeout(()=>{
// 停止监听
stopWatchRoom()
}, 3000)
watchEffect的用法
import { defineComponent, ref, reactive, toRefs, watchEffect } from "vue";
export default defineComponent({
setup() {
const state = reactive({ nickname: "xiaofan", age: 20 });
let year = ref(0)
setInterval(() =>{
state.age++
year.value++
},1000)
watchEffect(() => {
console.log(state);
console.log(year);
}
);
return {
...toRefs(state)
}
},
});
watchEffect 不需要手动传入依赖
watchEffect 会先执行一次用来自动收集依赖
watchEffect 无法获取到变化前的值, 只能获取变化后的值
自定义 Hooks
Teleport:
传送
Suspense
它提供两个
template
slot, 刚开始会渲染一个 fallback 状态下的内容, 直到到达某个条件后才会渲染 default 状态的正式内容, 通过使用Suspense
组件进行展示异步渲染就更加的简单。:::warning 如果使用Suspense
, 要返回一个 promise
片段(Fragment)
<template>
<span></span>
<span></span>
</template>
更好的 Tree-Shaking
Vue3.x 在考虑到
tree-shaking
的基础上重构了全局和内部 API, 表现结果就是现在的全局 API 需要通过ES Module
的引用方式进行具名引用
变更
slot 具名插槽语法
自定义指令
v-model 升级
在 Vue3 中, 在自定义组件上使用
v-model
, 相当于传递一个modelValue
属性, 同时触发一个update:modelValue
事件如果要绑定属性名, 只需要给<modal v-model="isVisible"></modal> <!-- 相当于 --> <modal :modelValue="isVisible" @update:modelValue="isVisible = $event"></modal>
v-model
传递一个参数就行, 同时可以绑定多个v-model
<modal v-model:visible="isVisible" v-model:content="content"></modal> <!-- 相当于 --> <modal :visible="isVisible" :content="content" @update:visible="isVisible" @update:content="content" />
异步组件
Vue3 中 使用
defineAsyncComponent
定义异步组件,配置选项component
替换为loader
,Loader 函数本身不再接收 resolve 和 reject 参数,且必须返回一个 Promise