vue3 笔记
watchEffect 的起源
stackoverflow - watchEffect vs. watch
- watch behavior in v3 is different to v2
- Change watch Options API to trigger immediately
vue3 最初只有 watch ,没有 watchEffect。这个时候的 watch 默认是 immediate = true
,可以 watch 具体对象,也可以 watch 一个函数自动收集依赖
但是 vue2 中的 watch 默认是 immediate = false
,导致 watch 的行为在 vue2 和 vue3 中不一致,给用户迁移项目带来麻烦。
vue作者在 github 讨论的解决方案:
- 保留这种不一致,把这列为 breaking changes,让用户自行修改代码解决
- 修改 vue3 的 watch 为默认 immediate = false。但这导致 watch(fn,handler) 的功能失效,所以必须把这个功能拆出来
最终采用了方案二,拆出来的变成了 watchEffect
另:用 watchEffect 时我总是忘记,只有取值才会watch,赋值不会
watchEffect(function(){// ...name.value = res; // 这里 name 不会被watch!
},handler)
getCurrentInstance
在 setup 中无法获取 this,绝大部分情况也不需要 this。但是如果真的想用 this 该怎么办呢?举个例子,在 vue2 项目中使用 composition api。但是 vue2 对应的 vuex 版本是 vuex3,而 vuex3 是不支持组合式写法的,只能傻傻的通过 this.$store 拿:(vuex你能不能给点力啊。。无语)
// vuex3
this.$store.xxxx
/// vuex4
import { useStore } from 'vuex'
const store = useStore()
网上说:在 setup 中想要获取 this 可以用 getCurrentInstance
const instance = getCurrentInstance();
console.log("proxy", instance.proxy);
console.log("ctx", instance.ctx);
但其实是不对的!因为 getCurrentInstance() 返回的 {ctx, proxy} 都是只给 dev 使用的,具体可以看我的回答。 但是项目中 prod 时又可以通过 proxy.$store 拿到数据。所以 $store 和组件内的数据还不一样吗?不管了,以后别用这个API 了。当他不存在。
并且,异步操作中(即当前组件初始化已经结束后)也不能用 getCurrentInstance,因为这时候 currentInstance 已经是 null 了。
曾经,这个 API 在 vue 官方文档中还有,在描述中写着“仅在高阶场景中使用,业务代码中不能用”。现在最新的文档中干脆直接去掉这个 API 了,我理解的官方的意思是:“当初就不该告诉你们有这个 API ,都瞎用。现在我藏起来,都别用了”。
setup 中的 props
解构 props
import { ref, toRef, toRefs, computed } from "vue";
export default {props: {obj: {type: Object,required: true,},},setup(props) {const data1 = props.obj; // 不可以const data2 = ref(props.obj); // 不可以const { obj: data3 } = toRefs(props); // okconst data4 = toRef(props, "obj"); // okconst data5 = computed(() => props.obj); // okreturn { data1, data2, data3, data4, data5 };},
};
前两种写法都不可以。当 props.obj 整体引用变化时,data1 和 data2 指向的还是旧地址。
watch prop
watch(() => props.obj, handler)
provide prop
provide('obj', props.obj) // 错误。当 props.obj 引用改变时,子组件中 inject 的还是旧引用
provide('obj', toRef(props, 'obj')) // ok. 但要注意子组件中 inject 后,使用时需要 .value