vue3正式版本刚刚发布,虽然之前就看过预览文档, 但是这次是发布的正式版本值得好好总结一番
在阅读vue3文档之前应当先了解proxy以便更好的理解 Composition Api(组合api)
vue3文档地址
vue3对比vue2的改变
对比
-
import { createApp } from 'vue' // 创建App const app = createApp({}) // 挂载路由, 全局组件, 全局指令等操作 // 按道理来说vue2的挂载组件库的操作也是在这个中间执行的 app.use(VueRouter) // 将app链接到#app元素中 app.mount('#app')
-
删除了filters 官方建议使用计算属性或者方法代替过滤器
-
template中可以写多个标签
<template> <header>...</header> <main v-bind="$attrs">...</main> <footer>...</footer> </template>
-
<child-component :ref="(el) => child = el"></child-component>
-
- 对于
v-if
/v-else
/v-else-if
的各分支项key
将不再是必须的,因为现在 Vue 会自动生成唯一的key
。 <template v-for>
的key
应该设置在<template>
标签上 (而不是设置在它的子结点上)
- 对于
-
transition 内置组件过度类名更改
leave-class
已经被重命名为leave-from-class
enter-class
已经被重命名为enter-from-class
-
teleport 内置组件
拥有to属性, 参数为css选择器, 将组件移动到对应选择器中, 会保持vue的特性,仅仅是迁移节点
<teleport to=".some-class" /> // 该dom插入到 *.some-class 元素中
-
v-model用法拓展
在vue2中修改父组件传入的props是一件很麻烦的事情
大部分情况我们会使用 .sync 修饰符以及 $emit(“update:xx”,xx)来修改
在vue3中如果子元素需要修改父元素传入的props的值, 父元素在传入该值的时候应该使用v-model传入
传入v-model相当于
<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" /> <!-- 上方代码等价于 --> <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" :content="pageContent" @update:content="pageContent = $event" />
-
Composition Api
建议阅读响应式原理, Composition API , 响应性基础 API, Refs, Computed 与 watch, setup 这几篇文章
总结以下常用的api
-
reactive 创建对象类型的响应式对象 , 注意该api创建的响应式对象解构时会失去响应, 可以使用toRef或者toRefs进行响应式绑定
声明类型
function reactive<T extends object>(target: T): UnwrapNestedRefs<T>
-
readonly 创建只读类型的响应式对象
-
shallowReactive 创建一层浅响应式对象 (不会对对象内部的对象进行响应式绑定)
-
shallowReadonly 创建一层只读的浅响应式对象(不会对对象内部的对象进行响应式以及只读绑定)
-
ref 创建一个响应式且可变ref对象
类型声明
interface Ref<T> { value: T } function ref<T>(value: T): Ref<T>
-
toRef 可以用来为源响应式对象上的 property 性创建一个
ref
。然后可以将 ref 传递出去,从而保持对其源 property 的响应式连接。const state = reactive({ foo: 1, bar: 2 }) const fooRef = toRef(state, 'foo') fooRef.value++ console.log(state.foo) // 2 state.foo++ console.log(fooRef.value) // 3
当您要将 prop 的 ref 传递给复合函数时,
toRef
很有用:export default { setup(props) { useSomeFeature(toRef(props, 'foo')) } }
-
toRefs 将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的
ref
const state = reactive({ foo: 1, bar: 2 }) /* // 相当于执行操作 stateAsRefs = { foo: ref(state.foo), bar: ref(state.bar) } // 所以解构也不会丢失响应性 */ const stateAsRefs = toRefs(state) /* Type of stateAsRefs: { foo: Ref<number>, bar: Ref<number> } */ // ref 和 原始property “链接” state.foo++ console.log(stateAsRefs.foo.value) // 2 stateAsRefs.foo.value++ console.log(state.foo) // 3
当从合成函数返回响应式对象时,
toRefs
非常有用,这样组件就可以在不丢失响应式的情况下对返回的对象进行分解/扩散:function useFeatureX() { const state = reactive({ foo: 1, bar: 2 }) // 逻辑运行状态 // 返回时转换为ref return toRefs(state) } export default { setup() { // 可以在不失去响应式的情况下破坏结构 const { foo, bar } = useFeatureX() return { foo, bar } } }
-
Computed , watchEffect 与 watch 计算属性与观察属性, 具体查看文档,本文不做过多的复制
watchEffect与watch的区别在于
- watchEffect会自动根据函数内的依赖而重新运行, 不需要明确的指明监听那个数据
- watch与vue2并无太大区别
-
setup中新的生命周期钩子
beforeCreate
-> usesetup()
created
-> usesetup()
beforeMount
->onBeforeMount
mounted
->onMounted
beforeUpdate
->onBeforeUpdate
updated
->onUpdated
beforeUnmount
->onBeforeUnmount
unmounted
->onUnmounted
errorCaptured
->onErrorCaptured
renderTracked
->onRenderTracked
renderTriggered
->onRenderTriggered
-
说一下ref与reactive的区别
网上有人说ref只能包裹基本数据类型(字符串,数字,布尔,undefined,null),我翻遍了官网也没找到对应的说明, 相反,我在官网中发现了如下示例代码
而在API文档中有如下说明如果将对象分配为 ref 值,则可以通过 reactive 方法使该对象具有高度的响应式。
从侧面印证出ref是可以包裹对象和数组的。
以及我在网上找到了一篇和我看法相同的文章: 来自 太_2_真_人 的vue3的ref和reactive分别何时使用?
并且查看了文章中去gethub上提的issues进一步印证了我的想法
引用文章中的原话
所以,ref和reactive并不是用来区分基本数据类型和引用数据类型的,反而他们的功能是一样的,只不过适用场景不太一样,了解这点之前先看下下面的代码:
// 风格1 let age = 10 let name = 'zhangsan' function updatePerson() { age = 20 } // 风格2 let person = { age: 10, name: 'zhangsan', sex: 'male' } function updatePerson() { person.age = 20 }
以上两种写法其实都对,只不过适用的写代码的风格不太一样,ref和reactive的区别就分别类似上面的风格1和风格2:
// ref let age = ref(10) let name = 'zhangsan'
// reactive let person = reactive({ age: 10, name: 'zhangsan' })
粗略总结, 如有错误以及未写入的新特性请各位评论区指出