首页 > 其他分享 >《Vue.js 设计与实现》读书笔记 - 第14章、内建组件和模块

《Vue.js 设计与实现》读书笔记 - 第14章、内建组件和模块

时间:2023-02-09 13:12:48浏览次数:39  
标签:Vue const 14 读书笔记 rawVNode vnode 卸载 组件 挂载

第14章、内建组件和模块

14.1 KeepAlive 组件的实现原理

KeepAlive 一词借鉴了 HTTP 协议。

KeepAlive 组件可以避免组件被频繁的销毁/重建。本质是缓存管理,再加上特殊的挂载卸载逻辑。

卸载时将组件放入另一个容器中,再次挂载时再拿出来。对应生命周期为 activateddeactivated

我们创建内置组件 KeepAlive 后,需要在卸载和挂载时对它进行特殊处理。

const KeepAlive = {
  __isKeepAlive: true,
  setup(props, { slots }) {
    // 用于缓存组件实例
    const cache = new Map()
    // currentInstance 前几章为了生命周期存的全局变量
    // 记录组件的实例
    const instance = currentInstance
    // 从实例的属性中获取一些渲染器的内部方法
    const { move, createElement } = instance.keepAliveCtx
    // 创建隐藏容器
    const storageContainer = createElement('div')
    instance._deActivate = (vnode) => {
      move(vnode, storageContainer)
    }
    instance._activate = (vnode) => {
      move(vnode, container, anchor)
    }

    return () => {
      // 默认插槽
      let rawVNode = slots.default()
      // 不是组件直接渲染 因为非组件不能缓存
      if (typeof rawVNode.type !== 'object') {
        return rawVNode
      }

      const cachedVNode = cache.get(rawVNode.type)
      if (cachedVNode) {
        rawVNode.component = cachedVNode.component
        // 如果是缓存组件 后面就不需要再挂载初始化了
        rawVNode.keptAlive = true
      } else {
        cache.set(rawVNode.type, rawVNode)
      }

      rawVNode.shouldKeepAlive = true
      rawVNode.keepAliveInstance = instance

      return rawVNode
    }
  },
}

patch 的组件挂载逻辑部分新加判断:

if (!n1) {
  if (n2.keptAlive) {
    n2.keepAliveInstance._activate(n2, container, anchor)
  }
  // 挂载
  mountComponent(n2, container, anchor)
}

卸载也一样

function unmount(vnode) {
  if (vnode.type === Fragment) {
    // ...
  } else if (typeof vnode.type === 'object') {
    if (vnode.shouldKeepAlive) {
      // 如果是keepalive组件 卸载时调用组件的deactive方法
      vnode.keepAliveInstance._deActivate(vnode)
    } else {
      unmount(vnode.component.subTree)
    }
    return
  }
  // ...
}

同时在组件实例新增 keepAliveCtx,传入 movecreateElement 让组件在 activateddeactivated 时使用。

const instance = {
  state,
  props: shallowReactive(props),
  isMounted: false,
  subTree: null,
  slots,
  // 在组件实例中添加 mounted 数组,用来存储通过 onMounted 函数注册的生命周期函数
  mounted: [],
  // keepAlive组件实例下保存
  keepAliveCtx: null,
}
const isKeepAlive = vnode.type.__isKeepAlive
if (isKeepAlive) {
  instance.keepAliveCtx = {
    move(vnode, container, anchor) {
      insert(vnode.component, subTree.el, container, anchor)
    },
    createElement,
  }
}

KeepAlive 组件还支持 includeexclude 功能,实现原理就是在判断是否缓存时加一个正则匹配。

缓存管理,需要限定缓存数量,在 Vue 中采取最近一次访问优先策略。

以及考虑如何在 KeepAlive 中支持自定义策略。

14.2 Teleport 组件的实现原理

通常情况下,组件渲染成真实 DOM 的层级结构与虚拟 DOM 相同,但是如果我们想要渲染到其他位置就无法实现。比如我们想要渲染一个蒙层,需要挂载到 body 下面。

实现方式,给组件增加标识,patch 挂载时挂载到指定的位置即可。为了方便 TreeShaking 把渲染逻辑封装到组件内部,这样如果用户没有使用到 Teleport 组件就不会加载相关代码。

14.3 Transition 组件的实现原理

原理:

  • 组件被挂载时,将动效附加到该 DOM 上
  • 组件被卸载时,不要立即卸载 DOM 元素,等到 DOM 上动效执行完再卸载

在挂载时我们有 enter-fromenter-to 两种,我们需要在开始时添加 enter-from 类名,然后在下一帧再添加 enter-to 触发动画。由于浏览器限制,我们要通过嵌套的 requestAnimationFrame 执行。

等到过渡完成,通过 transitionend 事件判断,并删除类。卸载同理。

标签:Vue,const,14,读书笔记,rawVNode,vnode,卸载,组件,挂载
From: https://www.cnblogs.com/wenruo/p/17104913.html

相关文章

  • 【Vue】父子组件传值、方法引用
    父子组件值、方法引用1、值1.1父组件获取子组件值父组件<template><div><button@click="getChildValue">click</button><childref="child"></child>......
  • Educational Codeforces Round 141 (Rated for Div. 2) D. Different Arrays(动态规划,
    题目链接:https://codeforces.com/contest/1783/problem/D  大致题意:  给你一个长度为n的数组a,你必须要进行n-2次操作,对于下标i(在2-(n-1)之间),在每次操作......
  • Edu Codeforces Round 142 (Rated for Div. 2)-D. Fixed Prefix Permutations-置换、
    题目:https://codeforces.com/problemset/problem/1792/D非常套路地,\(q_{p_j}\)看成映射就是\((p*q)(j)\),双射自然可逆,所以改成\(q(j)=p^{-1}(j)\)。题目里的每个置换长......
  • Vue 常用
    阅读目录​​Vue3中八个生命周期函数​​​​js动态添加对象属性​​​​js遍历对象​​​​第一种:for......in​​​​第二种​​​​第三种:使用Object.getOwnPropertyNa......
  • Vue 的优化技巧
    演示代码使用Vue3+ts+Vite编写,但是也会列出适用于Vue2的优化技巧,如果某个优化只适用于Vue3或者Vue2,我会在标题中标出来。代码优化v-for中使用key使用v......
  • Vue2.9.6安装element-ui
    阅读目录安装element-ui源码路由文件:E:\node\vue296\src\router\index.js入口:E:\node\vue296\src\main.js组件:E:\node\vue296\src\components\Count.vue......
  • Vue 中遇到的错误
    阅读目录解决VUE启动问题(Youmayusespecialcommentstodisablesomewarnings)两种方法解决方法一方法二安装vuex启动报错“export‘watch‘wasn......
  • [email protected]选项卡
    阅读目录<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><style>body{font-family:"Micr......
  • Vue 命令行工具 Vue-CLI 详解
    阅读目录阐述vue全家桶vue-cliVueCLI的安装①默认安装vue/cli脚手架3②默认安装失败,解决mode版本问题③nvm下载太慢问题解决④安装Node^12.0.0......
  • Vue界面渲染函数互相条用导致渲染失败的总结
    先说问题:界面上有一块区域是这样的  数据是取自一个map集合,后面的符号和过滤条件是按照对应的顺序去拿,没有直接关联,请求是按照顺序发的,但是渲染的界面有可能乱序像......