Oct1a

Vue3 知识点总结

一、爷孙组件通信 provide>inject

这边以爷孙组件来命名,provide是无法在父子组件、兄弟组件通信,只有在爷孙组件才行

Provide/Inject用于非父子组件之间共享数据∶

比如有一些深度嵌套的组件,孙组件想要获取爷组件的部分内容;
在这种情况下,如果我们仍然将props沿着组件链逐级传递下去,就会非常的麻烦。

对于这种情况下,我们可以使用Provide和 Inject :

无论层级结构有多深,爷组件都可以作为其所有孙组件的依赖提供者;
爷组件有一个provide选项来提供数据;
孙组件有一个inject选项来开始使用这些数据;
实际上,你可以将依赖注入看作是“long range props”,除了∶爷组件不需要知道哪些孙组件使用它provide的 property子组件不需要知道inject的property来自哪里

举个栗子

爷组件代码

export default ({
    provide{
        name:"abc"
    }
})

孙组件

在孙子组件内拿到定义的值,界面上就可以直接使用了

export default {
  inject: ["name"],
}

这边会有个问题,如果爷爷组件想传入当前data数据长度,使用this获取是会报错

export default ({
    provide(){
            return{
          name:"why",
          length:this.list.length
        }
      },
})

需要使用函数返回,this才会指向正常

处理响应式数据

我们先来验证一个结果∶如果我们修改了this.names的内容,那么使用length的子组件会不会是响应式的?我们会发现对应的子组件中是没有反应的:
这是因为当我们修改了names之后,之前在provide中引入的this.names.length本身并不是响应式的;那么怎么样可以让我们的数据变成响应式的呢?
非常的简单,我们可以使用响应式的一些API来完成这些功能,比如说computed函数;当然,这个computed是vue3的新特性,在后面我会专门讲解,这里大家可以先直接使用一下注意:我们在使用length的时候需要获取其中的value
这是因为computed返回的是一个ref对象,需要取出其中的value来使用;

二、事件传递

vu3在事件总线中不再使用vuex,Vue3从实例中移除了**$on$off$once方法,所以我们如果希望继续使用全局事件总线,要通过第三方的库∶Vue3官方有推荐一些库,例如mitt** 或tiny-emitter ;
这里我们主要讲解一下mitt库的使用;

mitt库的使用

安装yarn add mitt

封装为eventbus.js

import mitt from 'mitt'

const emitter = mitt()

//export const emitter1 = mitt() //可以引入多个事件
//export const emitter2 = mitt()
//export const emitter3 = mitt()

export default emitter

发送事件

import emmiter from './utils/eventbus';

export default {
    methods:{
        click(){
            emmiter.emit("clickElement",{name:"kobe"}) //可以传递对象参数
        }
    }
}

监听事件

import emmiter from './utils/eventbus';

export default {
    created(){
        emmiter.on("clickElement",(info)=>{
            console.log(info)
        })
        //监听方式二:监听所有事件对象
        emmiter.on("*",(type,info)=>{
            console.log("* listener:",type,info) //“* listener:clicklement {name:"kobe"}”
        })
    }
}

取消事件

在默写情况下我们可能希望取消掉之前注册的函数监听:

emitter.all.clear() //取消所有监听

//单独取消某个监听事件需要先创建一个函数
function onFoo(){}
emitter.on("foo",onFoo) //监听
emitter.off("foo",onFoo) //取消监听

插槽Slot

在开发中,我们会经常封装一个个可复用的组件:
前面我们会通过props传递给组件一些数据,让组件来进行展示;
但是为了让这个组件具备更强的通用性,我们不能将组件中的内容限制为固定的div、span等等这些元素
比如某种情况下我们使用组件,希望组件显示的是一个按钮,某种情况下我们使用组件希望显示的是一张图片;我们应该让使用者可以决定某一块区域到底存放什么内容和原生;

默认插槽

当没有指定插槽名时,其实vue是有给插槽默认名称

<slot name="defalut"></slot>

动态插槽

目前我们使用的插槽名称都是固定的;比如v-slot:leftv-slot:center等等;
我们可以通过v-slot:[dynamicSlotName]方式动态绑定一个名称;

具名插槽

v-slot可以使用缩写#表示

<template #center>
    <button>点我</button>
</template>

作用域插槽

在Vue中有渲染作用域的概念

父级模板里的所有内容都是在父级作用域中编译的;

子模板里的所有内容都是在子作用域中编译的;

动态组件使用

 <component
    is="about"
    name="page"
    :age="18"
 ></component>

component Is 所匹配的是components导入的名称

<script lang="ts">
import my from './my.vue'
import about from './about.vue'
export default({
  components:{
    my,
    about,
  },
})
</script>

keep-alive

keep-alive有一些属性:
include - string | RegExp | Array。只有名称匹配的组件会被缓存;
exclude - string | RegExp \ Array。任何名称匹配的组件都不会被缓存;
max - number | string。最多可以缓存多少组件实例,一旦达到这个数字,那么缓存组件中最近没有被访问的实例会被销毁;

include和exclude prop 允许组件有条件地缓存∶

  1. 二者都可以用逗号分隔字符串、正则表达式或一个数组来表示;

  2. 匹配首先检查组件自身的name选项;

image-20210629183543586

如果出现设置完include没反应的情况,大部分原因是因为组件没有设置name属性

针对keep-alive的生命周期问题

对于缓存组件来说,再次进入时,我们是不会执行created或者mounted等生命周期函数的,但是有时候我们确实希望监听到何时重新进入到了组件,何时离开了组件;这个时候我们可以使用activateddeactivated这两个生命周期钩子函数来监听;

activated() {
    console.log ("about activated") ;
},
deactivated(),{
    console.log ("about deactivated") ;
}

Webpack的代码分包

在默认情况下,在构建整个组件树的过程中,因为组件和组件之间是通过模块化直接依赖的,那么webpack在打包时就会将组件模块打包到一起(比如一个app.js文件中) ;这个时候随着项目的不断庞大, app.js文件的内容过大,会造成首屏的渲染速度变慢;

所以,对于-些不需要立即使用的组件 ,我们可以单独对它们进行拆分,拆分成一些小的代码块chunk.js,这些chunk.js会在需要时从服务器加载下来,并且运行代码,显示对应的内容;

webpack如何可以对代码进行分包呢?

使用import函数引用,打包时就会自动分包

import(“./utils/math”).then((res)=>{
    console.log(res.sum(20,30))
})

Vue实现异步组件

如果我们的项目过大了,对于某些组件我们希望通过异步的方式来进行加载(目的是可以对其进行分包处理) , 那
么Vue中给我们提供了一个函数: defineAsyncComponent.

defineAsyncComponent接受两种类型的参数:
类型一:工厂函数,该工厂函数需要返回一个Promise对象;
类型二:接受一个对象类型,对异步函数进行配置;

两种方式


2.工厂模式

import Loading from './loading.vue'

const AsyncCategory = defineA


/**



异步组件和Suspense

Suspense是-个内置的全局组件,该组件有两个插槽:
0 default :如果default可以显示,那么显示default的内容;
0 fallback :如果default无法显示,那么会显示fallback插槽的内容;

Transition动画组件原理

当插入或删除包含在transition组件中的元素时, Vue将会做以下处理:

  1. 自动嗅探目标元素是否应用了CSS过渡或者动画,如果有,那么在恰当的时机添加/删除CSS类名;
  2. 如果transition组件提供了JavaScript钩子函数,这些钩子函数将在恰当的时机被调用;
  3. 如果没有找到JavaScript钩子并且也没有检测到CSS过渡/动画, DOM插入、删除操作将会立即执行;
  • v-enter-from :定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一-帧移除。
  • v-enter-active :定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动
    画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
  • v-enter-to :定义进入过渡的结束状态。在元素被插入之后下一帧生效(与此同时v-enter-from被移除) ,在过渡/
    动画完成之后移除。
  • v-leave-from :定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
  • v-leave-active :定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在
    过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
  • v-leave-to :离开过渡的结束状态。在离开过渡被触发之后下一-帧生效(与此同时v-leave-from被删除) ,在过渡/
    动画完成之后移除。

image-20210701155348107

class的name命名规则如下:

如果我们使用的是一个没有name的transition ,那么所有的class是以V-作为默认前缀;
如果我们添加了一个name属性,比如 , 那么所有的class会以why-开头;

我们也可以显示的来指定过渡的时间,通过duration属性。
duration可以设置两种类型的值:
number类型:同时设置进入和离开的过渡时间;
object类型:分别设置进入和离开的过渡时间;

过度的模式mode

in-out

<transition name="ani" mode="out-in">
    <component :is="isShow ? 'home' : 'about'"></component>
</transition>

out-in

<transition name="ani" mode="in-out">
    <component :is="isShow ? 'home' : 'about'"></component>
</transition>

appear初次渲染

默认情况下,首次渲染的时候是没有动画的,如果我们希望给他添加_上去动画,那么就可以增加另外一 个属性appear属性

<transition name="ani" mode="in-out" appear>
    <h2 v-if=“isShow”>你好,李银河</h2>
    <h2 v-else>hello Word</h2>
</transition>

第三方动画库animate.css的使用

如果我们手动一一个个来编写这些动画,那么效率是比较低的,所以在开发中我们可能会引用一-些第三方库的动画库,
比如animate.css.

Animate.css是一个已经准备好的、 跨平台的动画库为我们的web项目,对于强调、主页、滑动、注意力引导
非常有用;

安装animate.css :

npm install animate.css

在main.js中导入animate.css :

import”"animate.css" ;

接下来在使用的时候我们有两种
用法一 :直接使用animate库中定义的keyframes动画;
用法二:直接使用animate库提供给我们的类;

Gsap库

某些情况下我们希望通过JavaScript来实现一 些动画的效果,这个时候我们可以选择使用gsap库来完成。

什么是gsap呢?
GSAP是The GreenSock Animation Platform ( GreenSock动画平台)的缩写;
它可以通过JavaScript为CSS属性、SVG、 Canvas等设置动画,并且是浏览器兼容的;

这个库应该如何使用呢?

第一步:需要安装gsap库;
第二步:导入gsap库;
第三步:使用对应的api即可;

在使用动画之前,我们先来看-下transition组件给我们提供的JavaScript钩子 ,这些钩子可以帮助我们监听动画执行到
什么阶段了。

添加:css=”false” ,会让Vue会跳过CSS的检测,除了性能略高之外,这可以避免过渡过程中CSS规则的影响。

image-20210701182148240

当我们使用JavaScript来执行过渡动画时,需要进行done回调,否则它们将会被同步调用,过渡会立即完成。

image-20210701182050024

Options API的弊端

在Vue2中,我们编写组件的方式是Options API :
Options API的一大特点就是在对应的属性中编写对应的功能模块;
比如data定义数据、methods中定义方法、computed中定义计算属性、watch中监听属性改变,也包括生命周期钩子;
但是这种代码有一个很大的弊端∶
当我们实现某一个功能时,这个功能对应的代码逻辑会被拆分到各个属性中
当我们组件变得更大、更复杂时,逻辑关注点的列表就会增长,那么同一个功能的逻辑就会被拆分的很分散;尤其对于那些一开始没有编写这些组件的人来说,这个组件的代码是难以阅读和理解的(阅读组件的其他人);

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。