Vue 3 学习笔记 Vue 3 的文档已经有中文版 ,内容很详细,也有 Vue 2 迁移 Vue 3 的指南 。因此这里只记录下自己用到的部分新特性和自己的一些理解。
Vue 3 数据响应式 Vue 2 的数据响应式底层实现是 Object.defineProperty()
,对于数组则是拦截了数组的七个方法。这种方式存在的问题是对于对象没有办法检测到属性的添加或删除。对于基于数组索引的变化也不能检测到。
Vue 3 的数据响应式基于 ES6 的 Proxy 实现的,和 Mobx 6 相同。解决了上面提到的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 const hero = { name: "赵云" , hp: 100 , sp: 100 , equipment: ['马' , '长枪' ] } const handler1 = { get (target, name, receiver ) { return Reflect .get(target, name, receiver) }, set (target, key, value, receiver ) { console .log(`hero's ${key} change to ${value} ` ) return Reflect .set(target, key, value, receiver) } } const handler2 = { set (target, key, value, receiver ) { console .log(`equipment's ${key} change to ${value} ` ) return Reflect .set(target, key, value, receiver) } } const heroProxy = new Proxy (hero, handler1)const equipmentProxy = new Proxy (heroProxy.equipment, handler2)heroProxy.equipment = equipmentProxy heroProxy.name = "张飞" heroProxy.equipment[2 ] = "盔甲" heroProxy.level = 100
Composition API 主要目的是为了更方便的拆分,重用代码,Vue 2 如果要复用代码的话需要使用 mixin。官方有示例 ,我感觉 Composition API 有点类似 React 的 自定义 Hooks。
setup 在 setup 中没有 this,只能使用 props 和 context
1 2 3 4 5 6 7 import {toRefs} from 'vue' setup (props ) { const {title} = toRefs(props) console .log(title.value) }
context 具有以下属性
生命周期钩子 setup 的生命周期钩子基本就是在选项式 API 的基础上加上 on
1 2 3 4 5 6 7 8 export default { setup ( ) { onMounted(()=> { ... }) } }
ref 和 reactive ref 和 reactive 都用于为数据添加响应式状态,但是 reactive 只接受对象类型的参数。一般数据为对象的话使用 reactive,基本类型使用 ref。 在 JS 中使用 ref 对象的值要加上 .value
,在 Template 中使用则不需要。
1 2 const count = ref(0 )console .log(count.value)
Provide / Inject 跟 Vue 2 中的 Provide 和Inject 功能类似,可以用于组件间通信。可以将 provide 提供的数据变为 inject 的组件只读的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <template> <MyMarker /> </template> <script> import { provide, reactive, readonly, ref } from 'vue' import MyMarker from './MyMarker.vue export default { components: { MyMarker }, setup() { const location = ref('North Pole') const geolocation = reactive({ longitude: 90, latitude: 135 }) const updateLocation = () => { location.value = 'South Pole' } provide('location', readonly(location)) provide('geolocation', readonly(geolocation)) provide('updateLocation', updateLocation) } } </script>
Teleport 可以把元素移动到我们想要的位置
1 2 3 4 5 <teleport to ="body" > <div > ... </div > </teleport >
v-model 用法的变更 Vue 2 中的 v-model 相当于绑定 value prop 和 input 事件:
1 2 3 <ChildComponent v-model ="pageTitle" > <ChildComponent :value ="pageTitle" @input ="pageTitle = $event" />
而 Vue 3 中的 v-model 更像是.sync
1 2 3 4 <ChildComponent :title.sync ="pageTitle" /> <ChildComponent v-model:title ="pageTitle" />
组件事件需要在 emits 选项中声明 组件需要在 emits 中声明触发的事件
1 2 3 export default { emits:['accept' ,'cancel' ] }
否则控制台会有警告
watchEffect 这个跟 MobX 的 autorun 非常像,它会立即执行传入的函数并响应式追踪其依赖,依赖变更久重新执行
1 2 3 4 5 6 7 const count = ref(0 )watchEffect(() => console .log(count.value)) setTimeout (() => { count.value++ }, 100 )
与 watch 的区别
watch 可以访问到侦听状态变化前后的值
watch 只有在侦听的源发生变化时才会执行回调
可以更具体的说明什么情况下回调函数执行
v-for 中的 Ref ref 可以绑定一个函数,来确定要绑定的 Dom 元素
1 2 3 <div class ="color-tabs-nav-item" v-for ="(t,index) in titles" :ref ="el => { if (index === selectedIndex) this.selectedItem = el }" :key ="index" > {{ t }} </div >
参考
深入实践 ES6 Proxy & Reflect
Vue 3 文档 - 深入响应式原理
ECMAScript 6 入门
Vue 3.0 学习笔记