您现在的位置是:首页 >学无止境 >【vue】生命周期,组件,插槽,依赖注入,实现分页器组件,异步组件,keep-alive网站首页学无止境
【vue】生命周期,组件,插槽,依赖注入,实现分页器组件,异步组件,keep-alive
简介【vue】生命周期,组件,插槽,依赖注入,实现分页器组件,异步组件,keep-alive
❤️ Author: 老九
☕️ 个人博客:老九的CSDN博客
? 个人名言:不可控之事 乐观面对
? 系列专栏:
生命周期
- 每个Vue组件实例在创建时候都需要经历一系列的初始化步骤
首先是运行一个setup函数,然后是beforeCreate,然后初始化Options api,也就是所谓vue中例如data中的数据,该初始化的初始化,该读的读,vue2中把数据转成getter和setter等等 ,把computed里面的函数都改成getter字段
- 然后调用created函数,之后会询问有没有预编译好的模板,也就是所谓的脚手架,如果有编译好的模板就不用编译了,如果没有预编译模板需要自己编译,耗时。vue2中最终生成outerHTML,vue3中是InnerHTML ,根据编译模板之后会得到一个模板函数,也就是所谓的render函数,返回vnodetree
- 之后会执行beforeMount函数,然后初始渲染,根据vnodetree,真正创建一个DOM树,并塞到浏览器中
- 然后mounted调用,挂载成功了,称为了Mounted状态,当数据发生变化的时候,先执行beforeUpdate函数,然后重新渲染,生成新的虚拟DOM树,然后根据虚拟DOM树,利用diff算法,在真实的DOM树上进行打补丁,让虚拟DOM和真的DOM树形态一样,之后运行updated
- 当组件也unmounted的时候,之后会调用beforeUnmount和unmounted函数
总结
- 什么是Vue的options?就是new Vue({})时传入的这个对象,用来配置该vue实例的各个方面,常见字段有data,methods,computed等,声明组件的时候也用到的是同样的options对象:Vue.component(‘foo-bar’,{}),export default{}
- vue能够检测数据变化的原理?vue2中是将数据及computed等字段都变成了getter和setter,业务代码修改数据相当于调用setter,setter里就会安排更新。它在我们提供的数据对象(data字段)上,递归的调用Object.defineProperty把那个对象的每个属性及深层次属性都变成getter/setter,这里没有对数据的下标进行getter,setter化,所以对下标的直接赋值是不能被检测到的,需要调用ary.splice等方法,或者Vue.$set(obj,key,value)也可以实现,同时,Vue还替换了数组的原型,以让从数组上访问到push,pop等变更方法的同时,也能检测到更新;vue3中是利用ES6 的Proxy对象来监控数据的变化,Proxy能够拦截对一个对象的几乎所有的操作,如读取,写入,判断属性的存在性,调用等等
- 何为响应式效果?即业务代码对数据做出更新/修改后,vue能自动检测到并去执行dom的更新
- 为什么为data字段中新增的属性没有响应式效果?通过obj.a = val这种方式自主添加的属性,不会成为getter/setter,自然也就检测不到了,Vue.set(obj,‘a’,value)写法会将a属性添加并设置为getter/setter
- computed字段一般用在什么场景下?由现有数据推算/派生出来的数据时,将这些数据的计算声明为计算属性,可以极大的方便在模板中的使用。
- 什么是vue的批量更新?业务代码中对数据做多次连续的变化,vue只做一次虚拟DOM的render,也只做一次真实DOM的更新。具体执行步骤:执行数据变更操作,并将变更操作推入微任务队列。当当前任务执行完毕后,浏览器会开始执行微任务队列中的任务。Vue会遍历微任务队列,并依次执行队列中的任务,进行批量更新。在更新过程中,Vue会根据实际的变更情况,对虚拟DOM进行比对(diff算法),找出需要更新的节点,并进行相应的DOM操作。使用微任务机制可以确保在同一事件循环中的多次数据变更都能被合并为一次更新,从而减少DOM操作的次数,提高性能和用户体验。
- vue选项中的methods字段中的函数能使用箭头函数吗?能是能,但是用了箭头函数this的绑定就失效了,因为vue会自动将methods里的函数的this绑定到当前组件实例,而箭头函数的this是静态的,不能被绑定而改变。
- 为什么data字段不能直接写对象而要写函数?在vue2中声明组件的时候,data字段必须为函数,不能为对象。因为组件最终有可能被创建多个实例,而每个实例之间不该有关联,所以data也不应该使用同一份。那为什么不能声明成对象,vue给复制出多份?声明成函数,函数不调用,一份也没有,节省内存;声明成对象,就算组件不实例化,数据也要占一份的空间,如果组件被多次实例化,则数据应该有多份,则vue需要复制它,但并不是所有的对象都能够被轻松复制,想要复制这个对象,得先认识这个对象,例如数组需要循环,对象需要forof等等,无法保证正确复制所有对象。所以提供一个函数,自己构建并返回数据。
- 什么是虚拟DOM?为什么有时候它不会更新?就是各现代框架中用来表示DOM树的一种更轻量的数据结构,其实就是递归的对象,其中记录了如标签名,属性集合,事件集合,样式集合,子节点等信息,框架通过虚拟DOM来表示真实DOM,以达到节省内存以及快速对比的目的。当框架运行时候,在两次虚拟DOM的对比中,没有变化的部分,框架是不会去更新对应真实DOM中的结点的,如果用户以其他方式修改了DOM,但是这件事情在虚拟DOM中没有体现,则可能出现不更新的情况
- proxy是什么?是ES6新增的一个class,利用它可以对一个对象的各种操作进行拦截,以实现对对象的监控,p = new Proxy(targetObject,{ get(){} set(){} has(){} apply(){} construct(){}})
- 什么叫生命周期函数?vue2和vue3分别由哪些生命周期函数?一个复杂的对象在创建,运行,到最后的销毁的整个过程中,有着各个比较关键的时间点,在这些时间点会为使用者提供调用特定函数的机会,这些在特定时间点被调用的函数,被称作生命周期函数。
- 组件化是什么意思?通过一些方案,可以使用更高层次的标签来画页面
- 模块化是什么意思?不同代码写进不同文件,可以随时引入。
- v-model本质是什么?text:value,input ; checked:checked,change
- 什么是双向绑定?即页面中的一个可交互元素(往往是表单元素)与代码中的一个字段相互绑定,修改该字段,该表单元素会发生变化,通过表单元素进行鼠标或键盘输入,代码中对应的字段的值也会同步发生变化
组件
- 子组件不能修改父组件的值,是单项数据流的
例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="container">
<counter></counter>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
Vue.component("counter", {
template: `
<span>
<button @click="current--">-</button>
<span>{{current}}</span>
<button @click="current++">+</button>
</span>
`,
data() {
return {
current: 0,
};
},
});
new Vue({
el: "#container",
});
</script>
</body>
</html>
轮播图组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="container">
<slider
:imgs="['https://travel.12306.cn/imgs/resources/uploadfiles/images/243945e6-c45d-4870-9cf5-77e488068646_product_W572_H370.jpg','https://travel.12306.cn/imgs/resources/uploadfiles/images/fcd7173f-7651-46e7-a126-bdc199e1f6f7_product_W572_H370.jpg','https://travel.12306.cn/imgs/resources/uploadfiles/images/b0c76b21-531b-4af4-a607-cf5672c72ded_product_W572_H370.jpg']"
:buttons="true"
:indicators="false"
></slider>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
Vue.component("slider", {
template: `
<div style="border:1px solid;width:400px;height:300px;position:relative;">
<img :src="imgs[currentIndex]" style="width:100%;height:100%">
<button v-if="buttons" @click="prev" style="position:absolute;top:50%;left:0;transform:translateX(-50%);"><</button>
<button v-if="buttons" @click="next" style="position:absolute;top:50%;right:0;transform:translateX(-50%);">></button>
<ul style="gap:5px;list-style:none;position:absolute;bottom:5px;display:flex;left:50%;transform:translate(-50%)">
<li v-if="indicators" @click="currentIndex = index" v-for="(img,index) of imgs" :style="{backgroundColor: index === currentIndex ? 'red' : 'white'}" style="width:5px;height:5px;border:1px solid;border-radius:9999px"></li>
</ul>
</div>
`,
data() {
return {
currentIndex: 0,
};
},
props: ["imgs", "buttons", "indicators"],
methods: {
prev() {
this.currentIndex--;
if (this.currentIndex === -1) {
this.currentIndex = this.imgs.length - 1;
}
},
next() {
this.currentIndex++;
if (this.currentIndex == this.imgs.length) {
this.currentIndex = 0;
}
},
},
});
new Vue({
el: "#container",
data: {},
});
</script>
</body>
</html>
插槽
-
组件标签之间的东西,会出现在组件模板的slot插槽中显示
-
vue3中在组件中使用v-model
-
因此我们这样写,,emit事件写成update:modelValue,然后修改modelValue的传回去,就实现了v-model、
-
在vue2中.sync就相当于vue3中的v-model,v-model传入的默认值是modelValue,如果向改变名字,就v-model:xxx=”title",改变xxx的值就可以了
具名插槽
- < slot name="title " >,用的时候就直接< template #title>就可以了
实现一个分页器
依赖注入
- 如果有一种情况,要套很多层组件,我们不能一层一层传递数据,这样会太麻烦了,出现了依赖注入
父级组件这么写
也可以写成一个函数
子组件这么写
异步组件
-
当应用包含大量组件时,一次性加载所有组件可能会导致初始加载时间变长,影响用户体验。异步组件通过将组件的加载延迟到需要时再进行加载,可以有效地减少初始加载时间,并且只在需要时才加载相应的组件。
-
使用异步组件可以将组件的加载与应用的其他部分解耦,只有在组件真正需要时才加载,而不是在应用初始化阶段加载所有组件。这样可以避免不必要的网络请求和资源加载,提高应用的性能。
-
vue3中提供了defineAsyncComponent
-
Vue2中
-
Suspense 组件
假如Dashboard组件没有加载完,就先加载下面那个loading具名插槽,当Dashboard加载完之后,下面的具名插槽就会消失,但是Suspense没有错误处理,外面包一个onErrorCaptured()钩子函数进行捕获和处理异步错误
keep-alive
- 作为keep-alive的子组件,实例是不会销毁的,会记录切换之前的状态
————————————————————————
♥♥♥码字不易,大家的支持就是我坚持下去的动力♥♥♥
版权声明:本文为CSDN博主「亚太地区百大最帅面孔第101名」的原创文章
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。