Vue3(2)
更多Vue.js知识请点击——Vue.js
🥔:有的山长满荆棘,有的山全是野兽,所以你应该是自己的那座山
文章目录
- Vue3(2)
- 一、Vue3生命周期
- 二、自定义hook函数
- 三、toRef与toRefs
- 四、其他Composition API
- 1、shallowRef与shallowReactive
- 2、readonly与shallowReadonly
- 3、toRaw 与 markRaw
- 4、customRef
- 5、provide和inject
- 6、响应式数据的判断
- 五、组合式API的优势
- 1、选项式API的问题
- 2、组合式API的优势
- 六、新的组件
- 1、Fragment
- 2、Teleport
- 3、Suspense
- 七、其他
- 1、全局API的转移
- 2、其他改变
一、Vue3生命周期
以上是Vue3的8个生命周期钩子(beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeUnmount、unmounted),可以倒回去看看和Vue2的生命周期的区别。点击此处复习Vue2生命周期
Vue3中可以继续使用Vue2中的生命周期钩子(写在setup
函数外面),但是有两个更改:
beforeDestroy 改名为 beforeUnmount
destroyed 改名为 unmounted
如果要写在setup
函数里面,那么要注意,这些钩子会换名字
beforeCreate ===> setup()
created =======> setup()
beforeMount ===> onBeforeMount
mounted =======> onMounted
beforeUpdate ===> onBeforeUpdate
updated =======> onUpdated
beforeUnmount ==> onBeforeUnmount
unmounted =====> onUnmounted
如果写到setup
函数里面,是没有beforeCreate
和created
这两个钩子的,因为setup
的执行时机就相当于这两个钩子(setup
会先于所有的钩子执行,把想在这两个钩子里写的代码写到steup
中最前面
就行了)
二、自定义hook函数
- hook本质是一个函数,用use开头,把setup函数中使用的Composition API进行了封装。
- 和vue2中的mixin类似。点击此处复习vue2-mixin
- 自定义hook的优势:复用代码,让setup中的逻辑更清楚易懂。
三、toRef与toRefs
作用:创建一个 ref 对象,其value值指向另一个对象中的某个属性。
应用: 要将响应式对象中的某个属性单独提供给外部使用时。
这样的话当我们去修改这些重新定义的属性时,会同步更改person中的对应属性。但是如果const name = ref(person,'name')
,这样可以改name
,但是person中的name不会同步修改
,这就是toRef和ref的区别
扩展:toRefs
与toRef
功能一致,但可以批量创建多个 ref 对象,语法:
const { name } = {...toRefs(person)}
四、其他Composition API
1、shallowRef与shallowReactive
shallow:浅层的、肤浅的。
shallowReactive
:只处理对象最外层属性的响应式(浅响应式)。
shallowRef
:只处理基本数据类型的响应式, 不进行对象的响应式处理。
使用场景:
- 如果有一个对象数据,结构比较深, 但变化时只是外层属性变化 ===> shallowReactive。
- 如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换 ===> shallowRef。
2、readonly与shallowReadonly
readonly
: 让一响应式数据变为只读的(深只读,每一层都不能改,都是readonly)。
shallowReadonly
:让一个响应式数据变为只读的(浅只读,只有第一层readonly,深层次仍然可以改)。
使用场景: 不希望数据(尤其是这个数据是来自与其他组件时)被修改时。
3、toRaw 与 markRaw
raw:原始的、未加工的。
toRaw:把什么变为原始。
markRaw:把什么标记为原始。
toRaw
:将一个由reactive生成的响应式对象转为普通对象。
使用场景:用于读取响应式对象对应的普通对象,对这个对象的所有操作,不会引起页面更新。
markRaw
:标记一个对象,使其永远不会再成为响应式对象。
使用场景:
- 有些值不应别设置为响应式,例如复杂的第三方类库等。
- 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
4、customRef
custom:自定义、定制。
track:追踪。
trigger:触发。
customRef
:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显示控制。
通过customRef实现防抖效果:
<template>
<input type="text" v-model="keyword" />
<h3>{{ keyword }}</h3>
</template>
<script>
import { customRef, ref } from "vue";
export default {
name: "App",
setup() {
// 根据Vue提供的ref
// let keyword = ref("hello");
// 自定义的ref
function myRef(value, delay) {
let timer;
console.log("---myRef---");
const x = customRef((track, trigger) => {
return {
get() {
console.log(`有人从myRef容器中读取数据,我把${value}给他了`);
track(); //通知Vue追踪数据value的变化
return value;
},
set(newValue) {
console.log(`有人把myRef容器数据改了,改为了:${newValue}`);
// 通过一直开启关闭定时器实现防抖效果,停止delay毫秒后才读取到结果
clearTimeout(timer);
timer = setTimeout(() => {
value = newValue;
trigger(); //通过Vue去重新解析模板
}, delay);
},
};
});
return x;
}
let keyword = myRef("hello", 500);
return {
keyword,
};
},
};
</script>
5、provide和inject
provide:提供。
inject:注入。
作用:实现祖与后代组件间通信
套路:父组件有一个 provide
选项来提供数据,后代组件有一个 inject
选项来开始使用这些数据
具体写法:
注:可以给任何后代传递数据(子、孙、曾孙。。。),但是父子间一般不用这个,因为父子间通信有世界上最简单的方式,就是props
6、响应式数据的判断
isRef: 检查一个值是否为一个 ref 对象
isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理
五、组合式API的优势
1、选项式API的问题
使用传统的OptionsAPI,新增或者修改一个需求,需要分别在data、methods、computed中修改,这样不太好维护。
2、组合式API的优势
组合式API可以把相关功能的代码更有序地组织在一起,这样不仅更好维护,而且更优雅~
六、新的组件
1、Fragment
fragment:片段、碎片
- 在Vue2中,组件必须有一个根标签
- 在Vue3中,组件可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中
- 好处:减少标签层级,减小内存占用
2、Teleport
teleport:传送、瞬间移动。
Teleport
:一种能够将我们的组件html结构移动到指定位置的技术。
to='xxx'
:指移动位置,值可以是body等html结构。如上例把teleport里面的内容移动到了body标签内。
3、Suspense
suspense:悬念
等待异步组件时渲染一些额外内容,提升用户体验,类似于路由懒加载吧
用defineAsyncComponent
可以实现异步加载
使用Suspense
包裹组件,并配置好default
与 fallback
:当default插槽里面的内容还没出来时,先展示fallback里面的内容。
这个路由懒加载的效果会在网速慢或者setup返回promise时较为明显。
前面讲setup的时候说到:setup里面不能用async,返回值不能为promise,现在可以进行补充,setup可以返回promise,但是要和suspense还有异步组件配合使用。
七、其他
1、全局API的转移
Vue2中有许多全局API和配置
- 例如:注册全局组件、注册全局指令等。
// 注册全局组件
Vue.component('MyButton',{
data:()=>({
count:0
}),
template:`<button @click="count++">Clicked {{count}} times.</button>`
})
// 注册全局指令
Vue.directive('focus',{
inserted:el => el.focus()
})
Vue3对这些API做出了调整:
- 将全局的API,即:
Vue.xxx
调整到应用实例app
上
2.x 全局API(Vue) | 3.x 实例API(app) |
---|---|
Vue.config.xxx | app.config.xxx |
Vue.config.prodution.Tip | 移除 |
Vue.component | app.component |
Vue.directive | app.directive |
Vue.mixin | app.mixin |
Vue.use | app.use |
Vue.prototype | app.config.glocalProperties |
2、其他改变
-
Vue3里的data选项应始终被声明为一个函数。
我们之前在Vue2里提到data有两种写法,一种是对象式
data:{}
,一种是函数式data(){}
,当使用组件时必须用函数式,这是因为Object是引用数据类型,里面保存的是内存地址,单纯写成对象形式,就会使得所有组件实例共用一份data,造成一个变全都变得结果。如果data是一个函数的话,每复用一次组件,就会返回一份新的data(类似于给每个组件实例创建了一个私有的数据空间,让各个组件实例维护各自的数据)。而Vue3严格规定data只能写成函数式。
-
过渡类名的更改
Vue2写法:
.v-enter, .v-leave-to { opacity: 0; } .v-leave, .v-enter-to { opacity: 1; }
Vue3写法:更清晰更语义化
.v-enter-from, .v-leave-to { opacity: 0; } .v-leave-from, .v-enter-to { opacity: 1; }
-
移除了keyCode作为v-on的修饰符,同时也不再支持
config.keyCodes
-
移除
v-on.native
修饰符父组件中绑定事件:
<my-component v-on:close="handlerComponentEvent" v-on:click="handlerNativeClickEvent" />
子组件中声明自定义事件:
<script> export default{ // 声明为自定义事件,不声明就一直看成原生事件 emits:['close'] } </script>
-
移除过滤器(filter)