前言:vue框架作为当下使用最多的两大框架之一,在国内几乎大部分的互联网公司前端都离不开vue,虽然它在2022年升级了最新版本Vue3.0,但是直至现在主流的还是Vue2.0。因此,每个学习Vue框架的前端工程师都得对Vue2.0有足够深入的了解与使用方法。这里就给大家介绍一些Vue2中比较深入的知识点。
一.<keep-alive>标签的使用
1.介绍
<keep-alive>标签并没有实际的意义,就像<template>标签一样,没有实际的意义,只不过它会有一些特殊的作用。
2.作用
我们知道,组件的生命周期大体上可分为四个阶段:创建阶段、挂载阶段、更新阶段、销毁阶段。
单页面应用每次在切换路由的时候组件都会完整的经历这四个阶段,因此每次切换路由的时候,组件都要重新经历这四个阶段,对于一些比较数据比较多或者请求比较多、页面比较复杂的组件,如果每次都这样经历一次,无疑对浏览器的性能造成了很大的浪费,因此我们就寻求一种能够将那些比较复杂的组件给缓存起来的方法,让组件在第一次跳转它的时候就将它创建并渲染,然后将它缓存起来,不用的时候就不显示它,需要使用的时候就直接用缓存的组件,而不需要重新创建组件,重新去发请求,这样能节省浏览器的性能。
因此,<keep-alive>标签就是解决办法,它的作用就是让组件有缓存效果。
3.使用方法
使用方法非常简单,就是像使用标签一样,将需要缓存的那些组件的路由出口被它包裹起来。例如:
<keep-alive>
<router-view />
</keep-alive>
这样,这个路由出口的组件就都有了缓存的效果。
4.常用属性
上面的这种方法虽然可以让我们的路由有缓存的效果,但是它会让该路由出口的每个组件都实现缓存,但是我们有些页面比较简单,完全不需要做缓存,因此就可以使用它的两个常用属性来控制哪些组件需要缓存,哪些组件不需要缓存。
include
它决定哪些组件要被缓存,它的属性值就是需要被缓存的组件的name属性值。
exclude
它决定哪些组件不需要被缓存,它的属性值是不需要被缓存的组件的name属性值。
5.注意点
当使用了<keep-alive>之后组件的生命周期钩子函数就会多两个,一个是activated,这个钩子函数是在该组件被激活时触发,另一个是deactivated,该钩子函数是该组件失活时触发。因此,加了<keep-alive>的组件生命周期钩子函数执行顺序是:
graph TD
beforecreated--> created--> beforemounted--> mounted--> activeted
并且由于组件被缓存了,当组件切换时,它只会在组件第一次渲染时执行创建和挂载阶段,后续切换该组件时不会执行创建和挂载阶段,只会执行activeted组件激活的钩子函数。并且由于组件被缓存,因此切换组件不会将组件销毁,因此也不会执行销毁阶段的钩子函数,只会执行deactivated失活钩子函数。
二.组件的name选项的作用
作用1
- 项目中有用到keep-alive时,name可以用作include和exclude的值
作用2
- vue-tools 调试时,可以在vue-tools上直接看到我们定义的name名称,而不是看到vue-tools 给我们的默认组件名称,默认组件名称完全没有语义,使用我们自定义的name名称可以让我们查找组件更加方便,也更规范。
作用3
- 递归组件 我们可以在组件的html结构里面使用name属性定义的名称,来使用自身这个组件,这样能实现组件的递归,可以帮助我们实现一些特定的html结构。 1
三.组件通信的一些特殊方式
1.$attrs和$listeners
当我们想要实现隔组件传值的时候,例如A组件->B组件->C组件,我们想要将数据从A传到C,并且C也能修改A的数据的时候,如果依旧使用传统父子组件传值的话,那么就需要先将A组件的数据传给B,然后B组件再把数据传给C组件,修改数据也是同样如此,先在C组件设置$emit然后在B组件设置$emit通信父组件修改数据,这样的话虽然可以实现要求,但是代码难免太过冗余,因此我们有更方便的方法,那就是使用$attrs和$listeners
$attrs
它能获取到父组件所有的自定义属性,但是它获取的属性必须是没有在自己的Props中定义过的,并且可以通过v-bind传递给子组件
$listeners
它能获取到父组件上所有监听的自定义事件,除native修饰的事件外
其实总的来看,这两个属性其实本质上来说依旧针对的是父子之间传值,只不过我们可以利用它来做跨级通信
因此,如果需要隔组件传值的时候,我们就可以利用这两个属性,在中间的组件那里利用这两个属性给需要传值的两个组件作桥梁,以实现效果。例如:
使用场景 A -> B -> C 现在想将A组件的数据 传递给C. 并且C通知A组件去修改A的数据
父组件 A
<A :title="title" @upTitle="upTitle" />
子组件 B
<B v-bind="$attrs" v-on="$listeners" />
孙组件 C
定义props this.$emits('upTitle', 'xxx')
核心代码
<BCom v-bind="$attrs" v-on="$listeners" />
2. provide inject --- 依赖注入
当我们组件的层级嵌套可能不止两级,有更多层级的时候,我们可以使用provide inject来实现跨级通信
用法:
在要传值的组件里面设置provide选项,比如:
data(){
return {
count:10
}
}
provide() {
return {
mycount: this.count,
}
}
在接收数据的组件里面设置inject选项,例如:
inject: ['mycount']
这样的话,就成功的将count数据传递到了别的组件,但是这样传递的数据会有问题,那就是它失去了响应式,因此我们可以传递一个函数或者传递一个对象,这样就能保持响应式,例如
传递数据的组件
provide() {
return {
mycount: this.count,
thCount: this.provideUpdateCount
}
},
provideUpdateCount() {
return this.count
}
接收数据的组件
<div>inject: {{ mycount }} --- {{ thCount() }}</div>
inject: ['mycount', 'thCount'],
3. EventBus
eventBus适用于兄弟组件之间传值。因为是小型项目,不需要使用上vuex。但是也不用过度使用eventBus,否则会造成一些数据流向混乱,不利于后期代码维护
使用方法:
在Vue原型对象上挂载一个bus属性,这个属性的属性值是一个空的Vue对象实例,它是个没有DOM的组件,使用on方法监听事件,使用emit方法递交事件,在不同的组件里面,它们都能通过这种方式触发事件,因此就能实现跨组件通信。例如在A组件监听事件,在B组件递交事件,这样的话B组件每次递交事件,A组件都能监听到该事件从而执行事件处理函数,来操作数据。 例如: