IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 7.vue3渲染模块的domAapi实现 -> 正文阅读

[JavaScript知识库]7.vue3渲染模块的domAapi实现

vue3渲染模块的domapi实现原理

vue3中渲染模块有两个子模块,分别是runtime-dom和runtime-core,其中,runtime-dom模块提供了常用的节点操作api和属性操作的api,而runtime-core中则包含虚拟dom的创建,diff算法等。

通过vue3中的runtime-core可以实现自己的渲染逻辑

本节来完善runtime-dom中的domapi,以便后面供runtime-core模块使用

vue中runtime-core的渲染逻辑

 <script src="./runtime-dom.global.js"></script>
    <div id="app"></div>
    <script>
        const  {createRenderer,h } = VueRuntimeDOM
        const {render,createApp} = createRenderer({

        })
        console.log(h('h1','hello world'),app)
    </script>
  • 结果输出虚拟dom h1节点
  • h函数为runtime-core中创建虚拟dom的函数
  • createRenderer函数可以让用户自己创建一个渲染器,从而创建元素
    • createRenderer函数里面,需要用户传入如何操作节点的命令,即元素创建api和属性创建api

runtime-dom中相关api的实现

  • 在runtime-dom新建nodeOps模块和patchProp模块,分别处理dom操作和属性操作
  • dom 操作
    • nodeOps模块为一个类,包含各种元素操作方法,主要有:
      • 元素创建
      • 文本节点创建
      • 元素插入
      • 移除节点
      • 获取节点
      • 获取节点父节点
      • 获取兄弟节点
      • 给文本节点设置内容
      • 给元素节点设置内容
    export const nodeOps  = {
     createElement(tagName){
         return document.createElement(tagName)
     },
     createTextNode(text){
         return document.createTextNode(text)
     },
     insert(element,container,anchor = null){
         container.insertBefore(element,anchor); // ==appendChild 
     },
     remove(child){
         const parent = child.parentNode;
         if(parent){
             parent.removeChild(child);
         }
     },
     querySelector(selectors){
         return document.querySelector(selectors);
     },
     parentNode(child){ // 父节点
         return child.parentNode
     },
     nextSibling(child){ // 获取兄弟元素
         return child.nextSibling
     },
     setText(element,text){ // 给文本节点设置内容
         element.nodeValue = text;
     },
     setElementText(element,text){ // 给元素节点设置内容 innerHTML
         element.textContent = text;
     }
    }
    
    • 属性操作
      • 对节点的属性操作包含多种情况,取决于节点的属性是什么,总体来说可以分为四种:
        • 类名
        • 行内样式
        • 事件
        • 其它属性
      • patchProp方法需要接收四个参数,分别是el:元素,key:属性名,preValue:之前的属性值,nextValue:新的属性值
      • 通过key判断属于哪一种情况,分别进行相关的处理
      • key === class:
        • 当是对类名的操作时,只需要判断nextValue是否存在,若存在则直接替换,若不存在则删除改属性
          export function patchClass(el,nextValue){
              if(nextValue == null){
                  el.removeAttribute('class')
              }else{
                  el.className = nextValue
              }
          }
          
      • key === ‘style’:
        • 若key为style,直接用nextValue进行替换对效率不太好,最好的方法是将nextValue和preValue进行对比,若之后存在的则保留,不存在的则删除。
          export function patchStyle(el,preValue,nextValue){ // 我如何比较两个对象的差异?
              if(preValue == null) preValue = {};
              if(nextValue == null ) nextValue = {}
              // 比对两个对象 需要同时遍历 新的和老的 
              const style = el.style
              for(let key in nextValue){
                  style[key] = nextValue[key]
              }
              if(preValue){
                  for(let key in preValue){
                      if(nextValue[key] == null){
                          // 老的有 新的没有 需要删除老的
                          style[key] = null;
                      }
                  }
              }
          }
        
      • key为事件
        • 若为事件,则需要将之前的事件缓存起来,当有新事件时,则直接添加新事件并缓存,若事件名不变,事件函数繁盛改变,则需要从缓存中取出原事件,将事件的执行内容替换
        function createInvoker(preValue) {
              const invoker = (e) => { invoker.value(e) }; // 这个地方需要调用才会执行 invoker.value
        
              invoker.value = preValue; // 后续只需要修改value的引用就可以 达到调用不同的逻辑
              return invoker
          }
          export function patchEvent(el, eventName, nextValue) {
              const invokers = el._vei || (el._vei = {});
              const exitingInvoker = invokers[eventName];
        
              if (exitingInvoker && nextValue) { // 进行换绑
                  exitingInvoker.value = nextValue;
              } else {
                  // 不存在缓存的情况  addEventListener('click')
                  const eName = eventName.slice(2).toLowerCase()
                  if (nextValue) {
                      const invoker = createInvoker(nextValue); // 默认会将第一次的函数绑定到invoker.value上
                      // el._vei  = {onClick: invoker}
                      invokers[eventName] = invoker; // 缓存invoker
                      el.addEventListener(eName, invoker);
                  } else if (exitingInvoker) {    // 没有新的值,但是之前绑定过 我需要删除老
                      el.removeEventListener(eName, exitingInvoker);
                      invokers[eventName] = null; // 缓存invoker
                  }
              }
          }
        
      • 其它属性的处理和class处理类似
  • 渲染器的创建
    • 除去自己创建一个渲染器外,根据domapi和属性操作api,vue内部会给用户提供一个创建好的渲染器, 渲染器函数为createRenderer,传入要操作的domapi,即可返回一个渲染器函数render
    const renderOptions = {patchProp,...nodeOps}
      // vue内置的渲染器,我们也可以通过createRenderer 创建一个渲染器,自己决定渲染方式
      export function render(vnode,container){
          let {render} = createRenderer(renderOptions);
          return render(vnode,container)
      }
    
      export function render(vnode,container){
          let {render} = createRenderer(renderOptions);
          return render(vnode,container)
      }
    
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-21 21:27:19  更:2022-07-21 21:28:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/11 13:01:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码