iis服务器助手广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >mini-vue渲染的简易实现
  • 125
分享到

mini-vue渲染的简易实现

2024-04-02 19:04:59 125人浏览 泡泡鱼
摘要

目录前言目标第一步: 第二步:第三步:第四步:总结前言 目前的主流框架Vue、React 都是通过 Virtual Dom(虚拟Dom)来实现的,通过Virtua

前言

目前的主流框架VueReact 都是通过 Virtual Dom(虚拟Dom)来实现的,通过Virtual Dom技术提高页面的渲染效率。Vue中我们通过在 template 模板中编写html代码,React中我们通过在内部的一个 render 函数里编写html代码,这个函数通过 jsx 编译后,实际会输出一个h函数,也就是我们的 Virtual Dom(虚拟Dom),下面简单来实现一个虚拟dom渲染真实dom,以及更新的方法。

目标

主要实现以下三个功能:

  • 通过h函数返回Vnodes;
  • 通过 mount 函数将 虚拟dom 挂载到真实节点上;
  • 通过 patch 函数通过 newVnodes 与 oldVnodes比较来实现dom的更新;

第一步:

在body标签内创建一个id为app的节点,后面会将虚拟节点挂载到这个节点上,而renderer.js用来实现上面三个功能。


<body>
  <div id="app"></div>
  <script src="./renderer.js"></script>
</body>

 第二步:

编写h函数,用来返回tag(标签元素)、props(属性对象)、children(子节点),简单来说虚拟Dom就是一个普通javascript对象。


// renderer.js
 
const h = (tag, props, children) => {
  return {
    tag,
    props,
    children
  }
}

那么通过这个h函数,我们简单来看看下面一段代码会输出什么?


const vdom = h("div", {class: "header"}, [
  h("h2", null, "Hello World"),
  h("h2", {id: 0}, h("span", null, "啦啦啦啦")) // 当props没有值,必须传一个null,不能不传
]);
console.log(vdom);

由下图可以看出,通过h函数,给我们返回了一个javaScript对象,这个便是 Virtual Dom(虚拟Dom),形成树状节点。

 那么我们拿到这个vnodes,如何挂载到真实节点上呢?下面我们来看看第三步

第三步:

我们先创建一个 mount 函数,需要传入两个参数,第一个是我们刚刚通过h函数返回的vnodes,第二个参数是我们需要将这些vnode挂载到哪个节点上,接下来看代码:


const mount = (vnodes, app) => {
  // 通过vnodes里面的tag值,比如("div", "h2"),创建一个节点
  // 同样在vnodes对象里保存一份真实dom,方便以后进行更新,新增等操作
  const el = vnodes.el = document.createElement(vnodes.tag); 
  // 拿到这个节点后,我们通过判断props值,进行添加属性
  if (vnodes.props) {
    for (let key in vnodes.props) {
      // 这儿通过拿到props中key值后,在做判断
      let value = vnodes.props[key];
      if (key.startsWith('on')) {
        // 比如用户写了一个onClick="changeData",处理为监听函数的事件
        el.addEventListener(key.slice(2).toLowerCase(), value)
      } else {
        el.setAttribute(key, value)
      }
      // 这下面还有些判断,比如指令啊v-if等等,进行边界化处理
    }
  }
  // 处理完props后,最后是Children节点
  if (vnodes.children) {
    if (typeof vnodes.children === 'string') {
      // 如果这儿是个字符串类型,那么就可以直接添加到节点中去
      el.textContent = vnodes.children
    } else {
      // 这种情况为数组类型,含有子节点,通过遍历,再生成子节点
      vnodes.children.forEach(vnode => {
        // 通过递归,再次将子节点挂载到当前节点上去
        mount(vnode, el)
      })
    }
  }
  // 最终将这个真实节点挂载到我们传入的app节点中去
  app.appendChild(el);
}
const app = document.querySelector("#app")
mount(vdom, app)

我们来看看通过mount函数挂载的实际效果:

 那么到这里,我们就已经实现了通过虚拟dom来创建真实dom了,那在vue当中是如何对这些dom进行更新操作呢,接下来我们再创建一个 patch函数(更新):

第四步:

通过patch函数,我们需要传入两个参数(vnodes1、vnodes2),分别是新的虚拟dom和旧的虚拟dom,通过比较新旧虚拟dom,来指定更新哪些节点。(这儿不考虑key值,需要参考key值可以查看链接:https://www.jb51.net/article/219078.htm)


// patch函数 n1: 旧节点、 n2:新节点
// 在vue源码中,旧vnode,新vnode分别用n1, n2表示
const patch = (n1, n2) => {
  // 在上面我们通过mount函数给n2添加了节点属性el,绑定到n2上
  const el = n2.el = n1.el
  // 首先,还是从两个中的tag入手
  if (n1.tag == n2.tag) {
    // n1、n2的tag相同,再对比props
    const n1Props = n1.props || {};
    const n2Props = n2.props || {};
    // 分别取到n1,n2中的props,进行比较
    for (let key in n2Props) {
      // 取出n2中所有key,判断n2的key值和n1key值是否相同
      const n1Value = n1Props[key] || '';
      const n2Value = n2Props[key] || '';
      if (n1Value !== n2Value) {
        if (key.startsWith('on')) {
          // 比如用户写了一个onClick="changeData",处理为监听函数的事件
          el.addEventListener(key.slice(2).toLowerCase(), n2Value)
        } else {
          el.setAttribute(key, n2Value)
        }
      }
      // 相同则不作处理
    }
    for (let key in n1Props) {
      const oldValue = n1Props[key];
      if (!(key in n2Props)) {
        if (key.startsWith('on')) {
          el.removeEventListener(key.slice(2).toLowerCase(), oldValue)
        } else {
          el.removeAttribute(key)
        }
      }
    }
  } else {
    // tag不同,拿到n1的父节点
    const n1Parent = n1.el.parentElement;
    // 通过removeChild将旧节点从父节点中移除,然后将n2挂载到父节点中
    n1Parent.removeChild(n1.el); //n1.el是通过mount函数往对象里添加的真实dom节点
    mount(n2, n1Parent)
  }
  // 最后处理children,相对于来说复杂些
  // children可以为字符串也可以为数组,那么先看字符串时怎么处理
  const n1Children = n1.children || [];
  const n2Children = n2.children || [];
  if (typeof n2Children === "string") {
    // 如果新节点内容为字符串,直接使用innerhtml进行替换
    el.innerHtml = n2Children;
  } else {
    // 下面情况是n2.children为数组情况时
    if (typeof n1.children === "string") {
      // n1.children为字符串,n2.children为数组
      el.innerHtml = ''; // 先将节点内容情况,再讲新的内容添加进去
      mount(n2.children, el)
    } else {
      // 两种都为数组类型时,这儿不考虑key值
      const minLength = Math.min(n1Children.length, n2Children.length);
      for (let i = 0 ; i < minLength ; i++) {
        patch(n1Children[i], n2Children[i]);
      }
      if(n2Children.length > n1Children.length) {
        n2Children.slice(minLength).forEach(item => {
          mount(item, el)
        })
      }
      if(n2Children.length < n1Children.length) {
        n1Children.slice(minLength).forEach(item => {
          el.removeChild(item.el)
        })
      }
    }
  }
}

上面简单的实现了patch的作用,其实就是我们说的diff算法(当然这儿没有考虑key值的情况,只能两个依次比较),同一层级进行比较。现在模拟演示一下,看看是否能更新成功:


const vdom = h("div", {class: "header"}, [
  h("h2", null, "Hello World"),
  h("h2", {id: 0}, [h("span", null, "啦啦啦啦")]) // 当props没有值,必须传一个null,不能不传
]);
const app = document.querySelector("#app")
mount(vdom, app)
setTimeout(()=> { // 3秒后向patch传入新旧Vnodes
  const vdom1 = h("div", {class: "header"}, [
    h("h3", null, "Hello World"),
    h("span", null, "哈哈哈")
  ])
  patch(vdom, vdom1)
},3000)

 通过下图,我们可以看到已经简单的实现了虚拟dom更新节点。

总结

简单的实现了下虚拟Dom生成真实节点,然后通过patch进行更新。再去看看源码,就能更好的理解vue的渲染器是如何实现的了。

到此这篇关于mini-vue渲染的简易实现的文章就介绍到这了,更多相关mini-vue渲染内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: mini-vue渲染的简易实现

本文链接: https://www.lsjlt.com/news/132055.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • mini-vue渲染的简易实现
    目录前言目标第一步: 第二步:第三步:第四步:总结前言 目前的主流框架Vue、React 都是通过 Virtual Dom(虚拟Dom)来实现的,通过Virtua...
    99+
    2024-04-02
  • mini-vue渲染的实现方法
    本篇内容介绍了“mini-vue渲染的实现方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录前言目标 第二步:总结前言目前的主...
    99+
    2023-06-20
  • Vue怎么实现条件渲染与列表渲染
    本文小编为大家详细介绍“Vue怎么实现条件渲染与列表渲染”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue怎么实现条件渲染与列表渲染”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、Vue条件渲染v-show...
    99+
    2023-06-30
  • Java怎么实现简单的模板渲染
    这篇文章将为大家详细讲解有关Java怎么实现简单的模板渲染,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。java基本数据类型有哪些Java的基本数据类型分为:1、整数类型,用来表示整数的数据类型。2、浮点...
    99+
    2023-05-30
    java
  • Vue中怎么实现列表渲染
    这期内容当中小编将会给大家带来有关Vue中怎么实现列表渲染,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。<!DOCTYPE html> <ht...
    99+
    2024-04-02
  • vue中怎么实现服务端渲染
    本篇文章为大家展示了vue中怎么实现服务端渲染,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、什么是服务端渲染客户端请求服务器,服务器根据请求地址获得匹配的组件,...
    99+
    2024-04-02
  • Vue中的动态组件怎么实现渲染
    本篇内容介绍了“Vue中的动态组件怎么实现渲染”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、什么是动态组件动态组件指的是动态切换组件的显...
    99+
    2023-06-30
  • Vue组件渲染与更新怎么实现
    这篇“Vue组件渲染与更新怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue组件渲染与更新怎么实现”文章吧。1. ...
    99+
    2023-07-05
  • 如何用Vue实现一个渲染引擎
    这篇文章主要介绍“如何用Vue实现一个渲染引擎”,在日常操作中,相信很多人在如何用Vue实现一个渲染引擎问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何用Vue实现一个渲染...
    99+
    2024-04-02
  • vue中如何实现SSR服务端渲染
    本篇内容主要讲解“vue中如何实现SSR服务端渲染”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“vue中如何实现SSR服务端渲染”吧!一、SSR是什么Server-Side Rendering ...
    99+
    2023-06-29
  • Vue中条件渲染和列表渲染的示例分析
    这篇文章将为大家详细讲解有关Vue中条件渲染和列表渲染的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言什么是条件渲染?在我们的页面中会有很多这样的应用场景,比如说我们今天要上架一个活动,这个活...
    99+
    2023-06-25
  • Vue实现简易记事本
    本文实例为大家分享了Vue实现简易记事本的具体代码,供大家参考,具体内容如下 预览图: 功能如下: (1)输入任务并按下回车键,可将任务添加至任务列表(不可输入重复任务) (2)...
    99+
    2024-04-02
  • Vue渲染的示例分析
    小编给大家分享一下Vue渲染的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Vue 推荐在绝大多数情况下使用 templ...
    99+
    2024-04-02
  • 详解Vue的列表渲染
    目录1. v-for:遍历数组内容(常用)2. v-for:遍历对象属性(常用)3.遍历字符串(不常用)4.遍历指定次数(不常用)5.key 的作用和原理1.虚拟DOM中key的作用...
    99+
    2024-04-02
  • Vue Three.js:Vue 的 3D 渲染利器
    引言 Three.js 是一个流行且功能强大的 JavaScript 库,用于在 Web 浏览器中创建 3D 场景和视觉效果。借助 Vue Three.js,开发人员可以在 Vue 应用程序中轻松集成 Three.js 的功能,从而为用户...
    99+
    2024-03-09
    Vue Three.js、3D 渲染、Three.js、Vue
  • React中的重新渲染实现
    目录缘起类组件React 合成事件定时器回调后触发 setState异步函数后调触发 setState原生事件触发setState 修改不参与渲染的属性只是调用 setState,页...
    99+
    2023-01-31
    React 重新渲染
  • Vue跨端渲染实现多端无缝衔接
    Vue 内部的组件是以虚拟 dom 形式存在的。下面的代码就是一个很常见的虚拟 Dom,用对象的方式去描述一个项目。相比 dom 标签相比,这种形式可以让整个 Vue 项目脱离浏览器...
    99+
    2023-05-19
    Vue跨端渲染 Vue渲染机制
  • Vue如何实现动态渲染input输入框
    本文小编为大家详细介绍“Vue如何实现动态渲染input输入框”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue如何实现动态渲染input输入框”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。问题描述就比如现在...
    99+
    2023-07-04
  • Vue实现插槽下渲染dom字符串的使用
    目录前言需求v-htmlv-outerHTML前言 Vue插槽想必大家都不陌生了,它可以在使用组件的时候决定组件的一部分内容如何渲染。但我最近遇到个需求需要将 dom 字符串插入到插...
    99+
    2023-05-16
    Vue 渲染dom字符串 Vue 渲染dom
  • Vue中render如何实现渲染时间戳转时间以及渲染进度条效果
    这篇文章给大家分享的是有关Vue中render如何实现渲染时间戳转时间以及渲染进度条效果的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一.格式化时间效果图:实现上述界面代码如下:...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作