博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
带你手写vnode到renderDom
阅读量:6892 次
发布时间:2019-06-27

本文共 2746 字,大约阅读时间需要 9 分钟。

前言

本文分为

  • vnode树的构建
  • render 的渲染
  • 数据变更后的diff
  • 拿到变更后的patch

项目搭建

npm i -g create-react-appcreate-react-app my-appcd my-appnpm start复制代码

并且把src中其他文件都删除,留下index.js就可以接下来了

vnode 的构建

首先要确定我们vnode对象的属性; type:标签名,attrs:属性名,children:子元素

实例:

那么根据上面我们需要的vnode结果,我们去写创建vnode的函数 createElement(type, attrs, children)

src/index.jsimport { createElement } from './element'let virtualDom = createElement('ui', { class: 'li-group' }, [  createElement('li', { class: 'item' }, ['a']),  createElement('li', { class: 'item' }, ['b'])])复制代码

接下来我们开始具体去写createElement函数,我们先在src下新建一个element.js文件

createElement - src/element.js

src/elment.jsclass Element {  constructor(type, attrs, children) {    this.type = type    this.attrs = attrs    this.children = children  }}function createElement(type, attrs, children) {  return new Element(type, attrs, children)}export { createElement }复制代码

现在我们已经可以从上面打印出virtualDom的数据结构了,那么接下来就是将virtualDom通过render函数去构建成真实的dom

render - src/elment.js

render(virtualDom, target) target:添加的目标节点

src/index.jsimport { render } from './element'let el = render(virtualDom)复制代码
src/element.jsfunction render(virtualDom){  const { type, attrs, children } = virtualDom  let el = document.createElement(type)  // 挂载属性  for(let key in attrs){    setAttr(el, key, attrs[key])  }  // 创建子节点  children.forEach(child=>{    if(child instanceof Element){      // 节点      el.appendChild(render(child))    }else{      // 文本      let textNode = document.createTextNode(child)      el.appendChild(textNode)    }  })  return el}function setAttr(node, key, value){  switch(key){    case 'value': // input textarea      if(node.tagName.toUpperCase() === 'INPUT' || node.tagName.toUpperCase() === 'TEXTAREA'){        node[key] = value      } else{        node.setAttribute(key, value)      }      break;    case 'style':      node.style.cssText = value      break;    default:      node.setAttribute(key, value)      break;  }}复制代码

那么现在我们终于可以将Dom渲染到页面中了

renderDom - src/element.js

src/index.jsimport { renderDom } from './element'renderDom(el, document.getElementById('root'))复制代码
src/element.jsfunction renderDom(el, target){  target.appendChild(el)}复制代码

上半部分已经好了,我们还是动手完成一下成果把

github:

先整理一下剩下的内容

vnode已经完成了,那么接下来就还有数据变更后的 diff 算法 和 diff 算法计算出的变更内容 patch。 数据变更后会产生新的vnode, diff会对比两份 vnode 查到其中的变更,再将这些变更通过patch函数去修改真实dom

再来打破一下大多数人对虚拟dom的理解

网上很多人说虚拟动效率高,性能好。

开始分析了:

1、什么虚拟dom经过diff算法实现了dom的最小变化,局部刷新(这句话每错),但是和性能没关系,你手动去操作dom,看看控制台是不是也只有你改变的dom元素刷新了,手工操作本身就是最小变化,框架还要经过diff,那么框架为什么要diff,因为不diff,那他就得把整个页面出现渲染了。

2、另一种说法就更唬人点了。什么js线程和渲染线程是两个部门,跨部门交流当然耗性能,js去更新 虚拟dom是js和js间的沟通,搞的好像更新了虚拟dom树后不用去操作真实dom一样了。比手工操作还多了一遍操作

那么虚拟dom到底为什么存在。

回到框架本身,现在前端是数据驱动视图,是为了让使用者只关注数据本身,对dom的增删改查就都被隐藏在了框架中,框架本身也需要这么一份vnode的描述,来说明现在的node结构是怎么的,不然他也不知道哪里被改变了,也就无法帮我们去修改真实dom了

这才是维护一份虚拟dom的作用

下文:

转载地址:http://ytebl.baihongyu.com/

你可能感兴趣的文章
Eclipse配置实现定制登录界面
查看>>
NO.1 进入IT世界
查看>>
Exceeded maximum number of retries. Exceeded max scheduling attempts 3 for instance
查看>>
Asp.net mvc 3.0新特性-浅析1
查看>>
Hadoop FSDataInputStream 流定位的例子
查看>>
在OWA页面中,增加忘记密码项
查看>>
Samba文件共享服务(共享脚本 让你工作更轻松)
查看>>
AJAX 学习笔记[三] get 与post 模式的区别
查看>>
MES技术
查看>>
GO语言练习:网络编程 ICMP 示例
查看>>
ios11--UIButton
查看>>
Jq-公告渐隐弹出
查看>>
Windows Forms中通过自定义组件实现统一的数据验证(二)
查看>>
阿里云海外征战记:跻身全球前三,只用了两年半
查看>>
解密回声消除技术之二(应用篇)
查看>>
Go语言的web程序写法
查看>>
IDF2011:基于SaaS模式的"教学云"案例
查看>>
《Linux From Scratch》第三部分:构建LFS系统 第七章:基本系统配置- 7.5. 配置系统时间...
查看>>
云计算你必须思考的8大问题
查看>>
Windows7 Debug Test
查看>>