文章目录
- 1. Vue3 之 生命周期
- 2. Vue3 之 自定义hook函数
- 3. Vue3 之 toRef 和 toRefs的使用
- 4. Vue3 之 shallowReactive 和 shallowRef 函数API
- 5. Vue3 之 readonly函数 和 shallowReadonly函数
- 6. Vue3 之 toRaw 和 markRaw函数 使用
- 7. Vue3 之 customRef 函数 使用
- 8. Vue3 之 provide 和 inject函数使用
- 8. Vue3 之 响应式数据的判断 api函数
- 9. Vue3 之 Composition API(组合式API)的优势
- 10. Vue3 之 Fragment组件
- 11. Vue3 之 Teleport组件
- 12. Vue3 之 Suspense组件
- 13. Vue3 之 其他情况的转变
1. Vue3 之 生命周期
Vue3的声明周期流程:
vue3中没有了 beforeDestroy 和 destroyed 两个钩子函数,取而代之的是 beforeUnmount 和 unmounted ,卸载前和卸载后的两个钩子函数。
Vue3 配置项的钩子函数如下:
<template> <h2>当前求和为:{{sum}}</h2> <button @click="sum++">+1操作</button></template><script>import {ref,reactive,watch,watchEffect} from 'vue'export default { name:'Demo', setup(){ //数据 let sum = ref(0) return { sum } }, //通过配置项的形式使用生命周期钩子函数 beforeCreate() { console.log('beforeCreate') }, created() { console.log('created') }, beforeMount() { console.log('beforeMount') }, mounted() { console.log('mounted') }, beforeUpdate() { console.log('beforeUpdate') }, updated() { console.log('updated') }, beforeUnmount() { console.log('beforeUnmount') }, unmounted() { console.log('unmounted') }}</script>
Vue3也提供了Composition API 组合式API形式的生命周期钩子:
- vue3因为有了setup配置项,所以就没必要再去提供beforeCreate和created的组合API了。setup就可以替代他俩的作用!
同样开始要先引入对应钩子的api:
<template> <h2>当前求和为:{{sum}}</h2> <button @click="sum++">+1操作</button></template><script>import {ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted} from 'vue'export default { name:'Demo', setup(){ //数据 let sum = ref(0) onBeforeMount(()=>{ console.log('onBeforeMount') }) onMounted(()=>{ console.log('onMounted') }) onBeforeUpdate(()=>{ console.log('onBeforeUpdate') }) onUpdated(()=>{ console.log('onUpdated') }) onBeforeUnmount(()=>{ console.log('onBeforeUnmount') }) onUnmounted(()=>{ console.log('onUnmounted') }) return { sum } },}</script>
如果以上的两种都配置了,组合式的钩子比配置项的钩子优先级高,同一个钩子都是先执行组合式的钩子在执行配置项的钩子。
2. Vue3 之 自定义hook函数
什么是hook?
- 本质是一个函数,把setup函数中使用的Composition API进行了封装。
实现一个鼠标点击显示坐标的功能:
<template> <h2>当前点击时鼠标的坐标为:x:{{point.x}}, y:{{point.y}}</h2></template><script>import {ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, reactive} from 'vue'export default { name:'Demo', setup(){ //数据 let sum = ref(0) let point = reactive({ x:0, y:0 }) //获取鼠标点击的xy坐标 function savePoint(event){ point.x = event.pageX point.y = event.pageY console.log(event.pageX,event.pageY) } //给window添加一个点击事件,获取鼠标当前的位置! onMounted(()=>{ window.addEventListener('click',savePoint) }) //组件被卸载之前,将window的事件移除 onUnmounted(()=>{ window.removeEventListener('click',savePoint) }) return { point } },}</script>
一般我们再src下面创建一个hooks目录,在里面创建useXxx.js的文件,作为钩子函数。
这样我们就可以将上面的那些功能全部拿出去,单独写一个js文件暴露出来,谁要用,谁引用,这就和钩子组合式API一样。
import {onMounted, onUnmounted, reactive} from "vue";export default function (){ //实现鼠标打点相关的数据 let point = reactive({ x:0, y:0 }) //实现鼠标打点相关的方法 function savePoint(event){ point.x = event.pageX point.y = event.pageY console.log(event.pageX,event.pageY) } //实现鼠标打点相关的钩子声明周期 onMounted(()=>{ window.addEventListener('click',savePoint) }) //组件被卸载之前,将window的事件移除 onUnmounted(()=>{ window.removeEventListener('click',savePoint) }) return point}
其实hook就是为了复用代码。
3. Vue3 之 toRef 和 toRefs的使用
同样使用toRef和toRefs前也需要导入对应api:
import {reactive,toRef,toRefs} from 'vue'
如下图中的name1 和 name2 :
- name1只是单纯的拿到了person.name的值,并没有响应式!
- 而通过toRef获取到的name2是和person存在响应式的关系!!
ref函数的疑点:
toRef处理一个数据,而toRefs就能处理多个,写法如下:
- 巩固一个知识点:
let a = { //在一个对象里面,通过...展开另外一个对象的写法 ...toRefs(person),}//这种...写法让a对象扩展了toRefs(person)的属性
<template> <h2>姓名:{{name}}</h2> <h2>年龄:{{age}}</h2> <h2>薪资:{{job.j1.salary}}</h2> <button @click="name += '~'">修改姓名</button> <button @click="age++">增长年龄</button> <button @click="job.j1.salary++">涨薪</button></template><script>import {reactive,toRef,toRefs} from 'vue'export default { name:'Demo', setup(){ //数据 let person = reactive({ name:'张三', age:18, job:{ j1:{ salary: 20 } } }) //将person里面的所有属性全部代理! const x = toRefs(person) return { //在一个对象里面,通过...展开另外一个对象的写法 ...toRefs(person), } }}</script>
总结:
4. Vue3 之 shallowReactive 和 shallowRef 函数API
shallowReactive函数只是考虑第一层响应式:
//shallow是浅的的意思,就是仅第一层能够有响应式,而job下面的这些对象就没有响应式!//shallowReactive只考虑也就是只考虑第一层let person = shallowReactive({ name:'张三', age:18, job:{ j1:{ salary: 20 } }})
shallowRef函数,会去处理基本数据类型的响应式,不会去处理对象类型的响应式:
//shallowRef函数不会去处理对象类型的响应式!//ref函数会去处理对象的响应式!let x = shallowRef({ y:0})
原因如下:
- 打印x如下信息:
总结:
踩坑经历:
- 之前有的时候vue2项目赋予值,经常把整个响应式都给赋值过去,以至于一改赋予对象其他对象也就跟着改变。这样在vue3就可以直接通过shallowRef函数来赋予就没问题了。
5. Vue3 之 readonly函数 和 shallowReadonly函数
readonly函数就是让一个响应式数据变为只读(深只读)。
shallowReadonly函数让一个响应式数据变为只读的(浅只读)。
应用场景:就是不希望数据被修改时!
注意点 – 页面数据没有变化有两种情况:
- js数据没有响应式,数据变了,但是页面没变!
- js数据有响应式,但是数据自身没有变化,页面就更不会变化了。
而 readOnly 以及 shallowReadonly 函数是属于第二种情况,数据压根就不会变化的!
let person = reactive({ name:'张三', age:18, job:{ j1:{ salary: 20 } }})//person里面所有的person都不能修改!//person = readonly(person)//浅可读let person2 = shallowReadonly(person)//person2就是浅可读的,这样的喊出就是别人没办法修改person2,但是却可以修改person,达到这样的一个效果。
6. Vue3 之 toRaw 和 markRaw函数 使用
raw英文直译:生的,未加工的。
toRaw作用:将一个reactive生成的响应式对象转为普通对象。
markRaw作用:标记一个对象,使其永远不会再成为响应式对象。
toRaw函数的使用:
- 注意:toRaw只能使用到reactive函数。
markRaw函数 使用:
- 注意:markRaw虽然标记了一个对象,使其不会成为响应式,但是如果改变对象的数据,对象本身数据是会改变的!只不过没有了响应式,页面不会显示了。
总结:
- 着重记一下,应用场景。
7. Vue3 之 customRef 函数 使用
customRef 函数作用:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制。
使用customRef函数,必须熟练使用customRef函数的两个参数track和trigger:
- track作用:通知Vue追踪value的变化(相当于提前和get商量一下,让他任务这个value有用的!)
- trigger作用:通知Vue重新解析模板。
以下实现了一个定时器防抖效果的操作:
<template> <input type="text" v-model="keyWord"> <h3>{{keyWord}}</h3></template><script>import {ref,customRef} from 'vue'export default { name:'App', setup(){ //自定义一个ref--名为:myRef function myRef(value,delay){ let timer //customref函数有两个参数:track , trigger //trigger是个函数,一般再set中使用,通知vue重新解析模板 //track也是个函数,通知Vue追踪数据(return的值)的变化 return customRef((track, trigger)=>{ return { //读,走get get(){ console.log(`有人从myRef容器中读取了数据,${value}`) track()//通知Vue追踪value的变化(相当于提前和get商量一下,让他任务这个value有用的!) return value }, //改,走set set(newValue){ console.log(`有人改变了myRef容器中读取了数据,${newValue}`) //先清除定时器,在设置定时器,这样就做成了防抖效果。 clearTimeout(timer) timer = setTimeout(()=>{ //修改get用到的value value = newValue },delay) trigger()//通知Vue重新解析模板 } } }) } //使用自定义的ref let keyWord = myRef('hello',500) return { keyWord } },}</script>
8. Vue3 之 provide 和 inject函数使用
provide英文直译:提供。
inject英文直译:注入。
作用:实现祖孙组件间通信(祖和孙之间,隔了一个父)。
总结:
8. Vue3 之 响应式数据的判断 api函数
9. Vue3 之 Composition API(组合式API)的优势
传统的Options API(配置项API)的缺点:
而Vue3的组合式API更好的划分功能!也是最方便的!
10. Vue3 之 Fragment组件
11. Vue3 之 Teleport组件
teleport组件作用:teleport是一种能够将我们的组件html结构移动到指定位置的计数。
使用teleport组件实现一个弹框效果:
- 以下是点击组件,将teleport里面的元素放到其他标签里面。
<template> <div> <button @click="isShow=true">点我弹个窗</button> <!--定位到id为itholmes的标签里面,也可以定位元素。--> <teleport to="#itholmes"> <div v-if="isShow" class="mask"> <div class="dialog"> <h3>我是一个弹窗</h3> <h4>一些内容</h4> <h4>一些内容</h4> <h4>一些内容</h4> <button @click="isShow=false">关闭弹窗</button> </div> </div> </teleport> </div></template><script>import {ref} from 'vue'export default { name: 'Dialog', setup(){ let isShow = ref(false) return { isShow } }}</script><style> .dialog{ position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); text-align: center; width: 300px; height: 300px; background-color: green; } /*对话框后面的遮蔽框*/ .mask{ position: absolute; top: 0; bottom: 0; left: 0; right: 0; background-color: rgba(0,0,0,0.5); }</style>
相当于跨了多个组件来指定的位置:
12. Vue3 之 Suspense组件
Suspense英文直译:悬念,悬疑。
Suspense组件作用就是等待异步组件渲染一些额外的环境,增加用户体验。
静态引入:
- import Child from ‘@/components/Child’ 这种方式就是静态引用。
<template> <div class="app"> <h3>我是App(祖)</h3> <Child></Child> </div></template><script>//通过这种方式引入的Child组件,App会等child组件加载完成后,再加载import Child from '@/components/Child'export default { name:'App', components:{ Child },}</script><style>.app{ background-color: gray; padding: 10px;}</style>
异步引入:
- 通过defineAsyncComponent方式的引入,叫做异步引入。
<template> <div class="app"> <h3>我是App(祖)</h3> <Child></Child> </div></template><script>import {defineAsyncComponent} from 'vue'//这样const Child = defineAsyncComponent(()=>import('@/components/Child')) //异步引入export default { name:'App', components:{ Child },}</script><style>.app{ background-color: gray; padding: 10px;}</style>
通过异步引入 和 Suspense组件的使用达到如下的效果图:
- 注意:Suspense组件是一个内置组件,不需要引入。
<template> <div class="app"> <h3>我是App(祖)</h3> <!-- Suspense是一个内置组件。 --> <Suspense> <!-- Suspense使用的是插槽技术 --> <!-- default就是我们要放置的模块数据,因为是异步的所以app先加载。 --> <template v-slot:default> <Child></Child> </template> <!-- 在default定义的模块还没有加载出来之前,由fallback插槽模块进行替代。 --> <template v-slot:fallback> <h3>加载中...</h3> </template> </Suspense> </div></template><script>import {defineAsyncComponent} from 'vue'const Child = defineAsyncComponent(()=>import('@/components/Child')) //异步引入export default { name:'App', components:{ Child },}</script><style>.app{ background-color: gray; padding: 10px;}</style>
在异步加载下,俩种情况下能产生组件之间延迟的情况。
- 第一种:网速慢。
- 第二种:使用了promise对象。(这里是个特例!)
补充一点:setup不能是一个async函数,因为返回值不再是return的对象,而是promise,模板看不到return对象中的属性。(后期也可以,返回一个Promise实例,但需要Suspense和异步组件的配合!)
总结:
13. Vue3 之 其他情况的转变
Vue2 和 Vue3 全局API做出的一些调整:
Vue3的data配置项使用被声明为一个函数!(一般都用setup了。)
过度类名的修改:
Vue3移除了keyCode作为v-on的修饰符,同时不再支持config.keyCodes了。
keyCode就是像 keyup.13 等等,也就是没有了@keyup.13的形式。
在Vue2中,native的使用:
- 如果写了一个click的自定义事件,现在想要调用原生的click事件,就用到了native。
而Vue3移除了v-on.native修饰符。
Vue3移除过滤器(filter)。