前言
vue3新增setup的初衷就是分散的逻辑块组合起来,使得开发者(特别是后续接替工作的开发人员)能够更好的理解代码逻辑,为此vue3新增了一系列的api方法来配合setup使用,其目的是我们原来写在声明周期(created,mounted等),以及监听函数、计算属性等中的逻辑,能够统一放在setup中,在上一篇vue3 --相对于vue2的改变T1档次,已经讲了setup、响应式api、生命周期,本文的讲解主要是computed、watch、provide、inject,在阅读之前希望能够对这些概念有初步的了解。
computed
定义computed
ref定义
import {computed} from "vue //引入方法
const base = ref("plus one val"); //定义一个ref //定义一个computed,依赖base const plusOne = computed(() => { return base.value + " process"; }); plusOne.value = "new val"; //报错,plusOne 是只读的, setTimeout(() => { base.value = "9999"; //改变(ref) base同样会触发(computed) plusOne的副作用,也就是视图更新等响应式变化 }, 2000);
普通对象定义
//也可以直接返回普通对象来定义conputed
const plusTwo = computed(() => {
return "测试值";
});
reactive定义
const reactiveBase = reactive({ prop: "reactive prop" }); //定义一个active
const plusFour = computed(() => {
return reactiveBase;
});
plusFour.value.prop = "new plus four val"; //因为plusFour.value是一个对象,所以我们改变对象下的prop属性,value的引用没有发生改变,所以不受computed只读限制。并且也会触发响应式副作用
setTimeout(() => {
reactiveBase.prop = "new plus four val2"; //改变(reactive) reactiveBase同样会触发(computed) plusFour的副作用
}, 2000);
通过传入{},定义get、set定义computed:值得一提的是,vue3任然保留了vue2在组件内部computed项,如果在组件的computed项中和setup返回的computed存在重名的项,组件内的computed会覆盖setup返回的computed
//通过传入对象,定义get、set方法来创建computed
const refTwo = ref("ref two raw");
const plusThree = computed({
get() {
return refTwo.value + " plus tree process";
},
set(val) {
console.log(val); //只有改变plusThree.value 时,才会触发
refTwo.value = val;
},
});
setTimeout(() => {
plusThree.value = "plusThree new val"; //定义set之后,computed是非只读的
refTwo.value = "change ref two generate"; //同样会引起computed的副作用,但是不会引发set()
}, 2000);
watchEffect
普通使用
const state = ref(0);
const state2 = ref(0);
watchEffect(() => {
console.log(state.value); //定义之后立即执行一次打印0,2000秒后state发生改变,又执行一次打印:1
console.log(state2.value); //如果在watchEffect内使用的多个响应式(ref||reactive)对象,那么只要有一个state发生改变,watchEffect就会执行
});
setTimeout(() => {
state.value++;
state2.value++;
}, 2000);
多个字段分别监听
export default {
setup(props) {
const state = ref(0);
const state2 = ref(0);
//监听state
watchEffect(() => {
console.log("监听state", state.value);
});
//监听state2
watchEffect(() => {
console.log("监听state2", state2.value);
});
setTimeout(() => {
state.value++;
}, 2000);
setTimeout(() => {
state2.value++;
}, 3000);
//setup中无需返回watchEffect
return {
state,
state2,
};
},
//如果在项中也定义了state的监听,那么watchEffect和watch都会执行,watch执行在watchEffect之后
watch: {
state(val) {
console.log("项监听", val);
},
},
};
watch
const state = ref(0);
const state2 = ref(0);
//监听state
watch(state, (newState, prevState) => {
console.log("监听state", state.value, state2.value); //定义时不会执行方法,只会在state改变后执行。即便内部使用了state2也不会对其进行监听
});
//监听多个字段
watch([state, state2], (newStatesArray, prevStateArray) => {
console.log(newStatesArray[0], newStatesArray[1]); //第一个参数为state,state2的最新数据数组
console.log(prevStateArray[0], prevStateArray[1]); //第二个参数为state,state2的上一个状态数据数组
});
provide和inject
//父组件
setup(props) {
let refProvide = ref("refProvide");
provide("key", "value"); //注入provide
provide("key2", refProvide); //注入响应式provide
return {
refProvide,
};
},
...
//子组件
setup(props) {
let value1 = inject("key"); //value
let value2 = inject("key2"); //ref value
return {
value1,
value2,
};
},