当前位置: 首页 > article >正文

15_卸载操作

在之前我们就提到,首次渲染之后,后续如果再调用 render 函数时,传递的 vnode 为 null 则表示是卸载。

当时我们是直接通过执行 container.innerHTML = ‘’ 来实现的,但是这样做会有以下几个问题,如下:

  • 容器内可能是由某个或者多个组件渲染的,当卸载操作发生时,应该正确的调用这些组件的 beforUnmount、unmounted 等生命周期函数。
  • 即使内容不是由组件渲染的,有的元素存在自定义指令,我们应该再在卸载操作发生时正确的执行这些对应指令的钩子函数。
  • 使用 innerHTML 清空容器的还有一个缺陷是,它并不会移除绑定在 DOM 元素上的事件处理函数

正确的卸载方式应该是,根据 vnode 对象获取对应与其相关联的真实 DOM 元素,然后使用原生 DOM 操作方式将该元素移除。为此,我们需要再 vnode 与真实 DOM 元素之间建立联系,修改 mountElement 函数,如下:

function mountElement(vnode, container) {
  // 让 vnode.el 引用真实的 dom 元素
  const el = (vnode.el = hostCreateElement(vnode.type))
  // ... 省略其他代码
}

这样建立联系之后,当卸载的时候,只需要根据 vnode.el 属性即可获取真实的 dom 元素,然后在将其从父元素中移除,如下:

function render(vnode, container) {
  if (vnode) {
    patch(container._vnode, vnode, container)
  } else {
    // 卸载操作
    if (container._vnode) {
      // 获取 vnode 关联的真实 dom
      const { el } = container._vnode
      // 获取 el 的父元素
      const parent = el.parentNode
      // 调用父元素的 removeChild 方法
      if (parent) {
        parent.removeChild(el)
      }
    }

    container._vnode = vnode
  }
}

根据之前的设计方案,这个卸载子元素的操作,会经常用到,我们将其提取出来,封装到 unmount 函数中,如下:

function unmount(vnode) {
  const { el } = vnode
  const parent = el.parentNode
  if (parent) {
    parent.removeChild(el)
  }
}

http://www.kler.cn/news/364469.html

相关文章:

  • 关系型数据库(1)----MySQL(初阶)
  • Redis批量获取缓存的方法
  • 2023 ICPC 亚洲澳门赛区赛 D. Graph of Maximum Degree 3
  • Android——convertView
  • 后端C++
  • excel判断某一列(A列)中的数据是否在另一列(B列)中
  • pytorch 交叉熵损失函数 BCELoss
  • Java 代理模式详解
  • 003:无人机概述
  • 使用RabbitMQ实现延迟消息的完整指南
  • 瓜田推广:揭秘零撸项目里流量变现的技术与模式框架,新手必看!
  • EDA软件设计(1)----画板、侧边框和属性版的简易设计
  • 多模态技术串讲
  • CSDN介绍
  • Flink on yarn模式下,JobManager异常退出问题
  • 百度文心一言接入流程-java版
  • 前端全栈混合之路Deno篇:Deno2.0如何快速创建http一个 restfulapi/静态文件托管应用及oak框架介绍
  • 循环双链表,将L改造为L=(a1,a3,…,an,a4,a2)
  • 【Linux】实现一个简易的shell命令行
  • Vue3+ts+vite自动导入vue的依赖
  • 应用案例 | Panorama SCADA助力巴黎奥运会:保障赛事协调与安全
  • 【STM32 Blue Pill编程实例】-OLED显示BME280传感器数据
  • HTTP介绍及请求过程
  • 深度学习中的注意力机制:从基础到应用
  • Redis学习文档
  • BigFoot (Simplified Configuration)