①性能的提升 打包大小减少41%、初次渲染快55%,更新渲染快133%,内存减少54%…… ②源码的升级
…… ③拥抱TypeScript Vue3可以更好的支持TypeScript ④新的特性 (1)Composition API(组合API) setup配置、ref与reactive、watch与watchEffect、provide与inject (2)新的内置组件 Fragment、Teleport、Suspense (3)其他改变 新的生命周期钩子、data选项始终被声明为一个函数、移除keyCode支持作为v-on的修饰符
①引入的不再是Vue的构造函数,而是一个名为createApp的工厂函数。 ②创建应用实例对象——app(类似于之前的Vue2中的vm,但app比vm更轻) ③不兼容vue2的写法。
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App); app.mount('#app') console.log(app)
角度 | ref | reactive |
---|---|---|
定义数据角度 | 基本类型数据,(也可以用来定义对象类型数据,它内部会自动通过reactive转为代理对象) | 对象(或数组)类型数据 |
原理角度 | 通过Object.defineProperty() 的get与set来实现响应式(数据劫持) | 通过使用Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据。 |
使用角度 | 操作数据需要.value,读取数据时模板中直接读取不需要.value。 | 操作数据与读取数据,均不需要.value。 |
语法 | const xxx = ref(initValue);创建一个包含响应式数据的引用对象(reference 对象,简称ref对象) let dog = ref('汤姆'); const person = ref({ name:'月亮', age:20});console.log(dog);console.log(person); | const 代理对象 = reactive(源对象),接收一个对象(或数组),返回一个代理对象(proxy对象) const person = reactive({name:'月亮',age:20});console.log(person); |
图示 |
Object.defineProperty() | proxy() | |
---|---|---|
使用方式 | 多个属性需要循环。 | 添加get()、set()、deleteProperty()函数实现响应式,没有添加之前只是代理。能捕获到对属性的任何一种操作,不用循环遍历。 |
使用 | vue3的响应式不仅仅用了代理还用到了反射。 | |
图示 |
import { reactive,computed,watch} from 'vue' 能用vue2里的computed和watch配置项,但是混合不好,vue3将计算属性变为组合式的API,在setup()函数中使用。
computed | watch | |
---|---|---|
使用 | 可以调用多次watch函数: | |
问题 | 用reactive定义的对象,watch监视旧值监视不到了。即使是用ref定义,但是其实其value还是用了proxy代理,监视对象.value最后oldValue还是有问题。不是.value监视就需要开启深度监视,也能监视到value中的proxy对象。不管嵌套的数据有多深,都能监视到,默认强制开启深度监视,deep:false也关不掉。但是对于监视一个代理对象里的属性对象时,深度监视没有开启,oldValue也有问题。 |
watchEffect()监视回调中用到了什么数据就监视那个数据。
let sum = ref(7);
watchEffect(()=>{
const x1 = sum.value;
console.log(x1);
})
组合式API写的生命周期钩子比配置项的要快一些:
新建一个文件夹hooks,里面都是就是文件。 什么是hook?——本质上是一个函数,把setup函数中使用的Composition API继续宁了封装。 类似于vue2中的mixin。 自定义hook的优势:复用代码,让setup中的逻辑更清楚易懂。 使用export default function(){return 需要的数据}
作用:创建一个ref对象,其value值指向另一个对象中的某个属性。 语法:const name = toRef(person,'name'); 对于深层次的对象,如果setup中直接return {此对象},以后模板取属性值需要person.属性很麻烦。 如果直接return {属性名:对象.属性名},不得行!!!此时属性名是自己新定义的属性了,后面就是把值给这个属性名,不能响应式了。记住对象.属性名就是个值!!! return { age:toRef(sum,'age'),}此时age响应式。 ...toRefs(对象),拆出来第一层
shallowReactive:只处理对象最外层属性的响应式(浅响应式) shallowRef:只处理基本数据类型的响应式,不进行对象的响应式处理。 什么时候使用? 如果有一个对象数据,结构比较深,但变化时只是外层属性变化==>shallowReactive 如果有一个对象数据,后续功能不会修改对象中的属性,而是生成新的对象来替换==>shallowRef
readonly:让一个响应式数据变为只读的(深只读),let person = readonly(person),对象里的数据改不了。 shallowReadonly:让一个响应式数据变为只读的(浅只读),对于对象外层只读 应用:不希望被修改时。
toRaw:将一个由reactive生成的响应式对象转为普通对象。(只能处理reactive标记的对象) 使用场景:用于读取相应是对象对应的普通对象,对这个普通对象所有的操作,不会引起页面更新。 markRaw:标记一个对象,使其永远不会再成为响应式对象。 使用场景:1.有些值不应被设置为响应式的,例如复杂的第三方类库等。 2.当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
作用:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制。
let keyword = myref('hello',500);
function myref(value,delay){//自定义ref
let timer;
return customRef((track,trigger)=>{//自定义的逻辑
return {
get:function(){//读取该数据时
track();//提前说明要追踪数据
return value;
},
set:function(newvalue){
value=newvalue;
clearTimeout(timer);
timer = setTimeout(()=>{
trigger();//通知vue重新去解析模板
},delay)
}
} //必须返回一个对象
});
}
作用:实现祖孙组件间的通信。(父子组件一般不用这个,而用props) 应用:父组件有一个provide选项来提供数据,子组件有一个inject选项来开始使用这些数据。
父组件: let car = reactive({ name:'奔驰', price:'40w' }); provide('car',car);//给自己的后代提供数据 复制代码 子组件 let car = inject('car'); 复制代码
isRef: 检查一个值是否为一个ref对象。
isReactive:检查一个对象是否由reactive创建的响应式代理。
isReadonly:检查一个对象是否由readonly创建的只读代理。
isProxy:检查一个对象是否由reactive或者readonly方法创建的代理。
----Options API存在的问题 | ----Composition API的优势 |
---|---|
使用传统Options API中,新增或者修改一个需求,就需要分别在data,method,computed里修改。(功能的数据、方法、监视都拆散了,多个功能的数据等都混在了一起。) | 可以更加优雅的组织代码、函数,让相关功能的代码更加有序地组织在一起。 |
在Vue2中:组件必须有一个根标签。 在Vue3中:组件可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中。 好处:减少标签层级,减少内存占用。
Teleport是一种能够将我们的组件html结构移动到指定位置的技术。
等待异步组件时渲染一些额外内容,让应用有更好的用户体验。 理解:suspense标签里准备了两个插槽,一个用于防止真正展示的组件,一个展示loading正在加载提示。
<Suspense>
<template v-slot:default>
<Child/>
</template>
<template v-slot:fallback>
<h3>加载中</h3>
</template>
</Suspense>
import {defineAsyncComponent} from 'vue'
const Child = defineAsyncComponent(()=>import('./Child.vue'))
对于自定义事件,需要在子组件中声明:
export default{
emits:['close']
}
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。