第一章 Vue3
1.Vue3有哪些提升?
①性能的提升
打包大小减少41%、初次渲染快55%,更新渲染快133%,内存减少54%……
②源码的升级
- 使用Proxy代替defineProperty实现响应式。
- 重写虚拟DOM的实现和Tree-Shaking。
……
③拥抱TypeScript
Vue3可以更好的支持TypeScript
④新的特性
(1)Composition API(组合API) setup配置、ref与reactive、watch与watchEffect、provide与inject
(2)新的内置组件 Fragment、Teleport、Suspense
(3)其他改变 新的生命周期钩子、data选项始终被声明为一个函数、移除keyCode支持作为v-on的修饰符
2.Vue3的main.js变化
①引入的不再是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)
3.ref和reactive(对比)
| 角度 | 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); |
| 图示 |
4.Object.defineProperty()和proxy()
| Object.defineProperty() | proxy() | |
|---|---|---|
| 使用方式 | 多个属性需要循环。 | 添加get()、set()、deleteProperty()函数实现响应式, 没有添加之前只是代理。能捕获到对属性的任何一种操作,不用循环遍历。 |
| 使用 | vue3的响应式不仅仅用了代理还用到了反射。 | |
| 图示 |
5.vue3中的computed、watch
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也有问题。 |
6.vue3的watchEffect()函数
watchEffect()监视回调中用到了什么数据就监视那个数据。
let sum = ref(7);
watchEffect(()=>{
const x1 = sum.value;
console.log(x1);
})
7.生命周期
组合式API写的生命周期钩子比配置项的要快一些:
8.自定义hook函数
新建一个文件夹hooks,里面都是就是文件。
什么是hook?——本质上是一个函数,把setup函数中使用的Composition API继续宁了封装。
类似于vue2中的mixin。
自定义hook的优势:复用代码,让setup中的逻辑更清楚易懂。
使用export default function(){return 需要的数据}
9.toRef
作用:创建一个ref对象,其value值指向另一个对象中的某个属性。
语法:const name = toRef(person,'name');
对于深层次的对象,如果setup中直接return {此对象},以后模板取属性值需要person.属性很麻烦。
如果直接return {属性名:对象.属性名},不得行!!!此时属性名是自己新定义的属性了,后面就是把值给这个属性名,不能响应式了。记住对象.属性名就是个值!!!
return { age:toRef(sum,'age'),}此时age响应式。
...toRefs(对象),拆出来第一层
第二章 不太常用的API
1.shallowReactive与shallowRef
shallowReactive:只处理对象最外层属性的响应式(浅响应式)
shallowRef:只处理基本数据类型的响应式,不进行对象的响应式处理。
什么时候使用?
如果有一个对象数据,结构比较深,但变化时只是外层属性变化==>shallowReactive
如果有一个对象数据,后续功能不会修改对象中的属性,而是生成新的对象来替换==>shallowRef
2.readonly与shallowReadonly
readonly:让一个响应式数据变为只读的(深只读),let person = readonly(person),对象里的数据改不了。
shallowReadonly:让一个响应式数据变为只读的(浅只读),对于对象外层只读
应用:不希望被修改时。
3.toRaw与markRaw
toRaw:将一个由reactive生成的响应式对象转为普通对象。(只能处理reactive标记的对象)
使用场景:用于读取相应是对象对应的普通对象,对这个普通对象所有的操作,不会引起页面更新。
markRaw:标记一个对象,使其永远不会再成为响应式对象。
使用场景:1.有些值不应被设置为响应式的,例如复杂的第三方类库等。
2.当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
4.customRef
作用:创建一个自定义的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)
}
} //必须返回一个对象
});
}
5.provide与inject
作用:实现祖孙组件间的通信。(父子组件一般不用这个,而用props)
应用:父组件有一个provide选项来提供数据,子组件有一个inject选项来开始使用这些数据。
父组件:
let car = reactive({ name:'奔驰', price:'40w' }); provide('car',car);//给自己的后代提供数据子组件
let car = inject('car');
6.响应式数据判断API
isRef: 检查一个值是否为一个ref对象。
isReactive:检查一个对象是否由reactive创建的响应式代理。
isReadonly:检查一个对象是否由readonly创建的只读代理。
isProxy:检查一个对象是否由reactive或者readonly方法创建的代理。
第三章 其他
1.Options API存在的问题与Composition API的优势
| ----Options API存在的问题 | ----Composition API的优势 |
|---|---|
| 使用传统Options API中,新增或者修改一个需求,就需要分别在data,method,computed里修改。(功能的数据、方法、监视都拆散了,多个功能的数据等都混在了一起。) | 可以更加优雅的组织代码、函数,让相关功能的代码更加有序地组织在一起。 |
2.新的组件
(1)Fragment
在Vue2中:组件必须有一个根标签。
在Vue3中:组件可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中。
好处:减少标签层级,减少内存占用。
(2)Teleport组件
Teleport是一种能够将我们的组件html结构移动到指定位置的技术。
(3)Suspense组件
等待异步组件时渲染一些额外内容,让应用有更好的用户体验。 理解: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'))
3.Vue3中的其他改变
- 移除keyCode作为v-on的修饰符,同时也不再支持config.keyCodes
- 移除v-on:Click.native修饰符 对于自定义事件,需要在子组件中声明:
export default{
emits:['close']
}
- 移除过滤器filter:过滤器虽然看起来很方便,但它需要一个自定义语法,打破打括号内表达式是"只是javascript"的假设,这不仅有学习成本,而且有实现成本,建议用方法或者计算属性去替换过滤器。