javascript --- [虚拟DOM] 初始化 实现

说明

  • 本篇主要说明为什么要使用虚拟DOM技术,以及如何实现简单的虚拟dom
  • 您将会学到:
    1.原生JS对DOM的操作
    2.虚拟DOM的相关概念
    3.DIFF算法的基础概念

为什么提出 -> DOM操作慢

  • 我们使用createElement属性来创建一个最常见的div,看看一个最常见的DOM有多少个属性
<script>const div = document.createElement('div');let str = '';for(let key in div){str += key + ' ';}console.log(str);
</script>

在这里插入图片描述

  • 可以看出,每个DOM其实是由很多内置的属性.因此,当DOM元素的操作过多的时候,其性能可想而知.
  • 这就迫使我们去想一个办法去减少DOM操作

为什么提出 -> 对比Ajax技术的出现

  • 早期的网页交互,是整个页面进行更新的.
  • 但是大多数时候,用户对页面的操作,只是一小部分,这就导致了大多数更新是多余的.
  • 于是产生了Ajax技术(网页的部分更新)
  • 可以模仿Ajax技术,去部分渲染DOM

为什么提出 -> DOM树的概念

  • 你可以会反驳,减少DOM的操作,不一定非要用到虚拟DOM,而可以直接对DOM进行操作.
  • 这就得先理解DOM树.
  • 先看一个浏览器得请求过程:
    1.用户输入网址后,浏览器像服务器发送HTTP请求获得HTML页面
    2.得到页面后,HTML解释器、词法分析器、语法分析器就会把HTML从字节流解释成DOM树的结构(过程比较复杂,也许会开一篇新文章具体说明)
    3.得到DOM树后,WebKit会分批次的将结果词语返回给渲染线程进行渲染
  • 上面对DOM的产生和渲染说的比较细了,这样说的主要原因是: 说明没有一个类或者方法,可以得到内存中待渲染的DOM树(有可能要,但是我不知道QAQ).
  • 下面开始逐步实现虚拟DOM

createElement

  • 我们想实现以下结构
    在这里插入图片描述
  • 语法如下:
let vertualDom = createElement('ul', { class: 'list'}, [createElement('ul', { class: 'list'}, ['a']),createElement('ul', { class: 'list'}, ['b']),createElement('ul', { class: 'list'}, ['c'])
])
  • 我们想通过createElement之后,变为对象,结构如下:
    在这里插入图片描述
  • 很显然,可以在创建虚拟节点时,返回一个VNode类,其中包含3个属性(type、props、children)
class VNode {constructor(type, props, children) {this.type = type;this.props = props;this.children = children;}
}const createElement = (type, props, children) {return new VNode(type, props, children);
}
  • 上面之后,就可以返回一个虚拟DOM对象了.
  • 下面需要一个render方法,根据 虚拟DOM对象 来生成真实的DOM,并渲染.

render

  • render方法接收一个虚拟dom对象,根据对象创建真实的DOM
  • 1.首先我们根据传入的对象,创建ul
const render = (vnode) {let el = document.createElement(vnode.type);return el;
}
  • 打印一下:
let vertualDom = createElement('ul', { class: 'list' }, [createElement('ul', { class: 'list' }, ['a']),createElement('ul', { class: 'list' }, ['b']),createElement('ul', { class: 'list' }, ['c']),
])let el = render(vertualDom);console.log(el);

在这里插入图片描述

  • 2.有了DOM之后,我们给dom设置属性.由于属性可能比较多,
  • 因此我们使用for ... in 拿到键和值
  • 使用setAttribute来设置属性
const render = (vnode)  => {let el = document.createElement(vnode.type);let props = vnode.type;for(let key in props) {el.setAttribute(key, props[key]);}
}

在这里插入图片描述

  • 检测一下,改写vertualDom
let vertualDom = createElement('ul', { class: 'list', style:'border:1px solid black' }, [createElement('ul', { class: 'list' }, ['a']),createElement('ul', { class: 'list' }, ['b']),createElement('ul', { class: 'list' }, ['c']),
])
let el = render(vertualDom);
document.body.appendChild(el);

在这里插入图片描述

  • 现在有了节点和节点上面的属性,下面需要渲染其子元素…
  • 很自然的想到了递归.
  • 遍历其子元素,如果是VNode类型,就在调用render,否则认为其是一个文本节点.使用document.createTextNode创之
const render = (vnode) => {let el = document.createElement(vnode.type);let props = vnode.props;for (let key in props) {el.setAttribute(key, props[key]);}vnode.children.forEach(child => {child = child instanceof VNode ? render(child) : document.createTextNode(child);el.appendChild(child);})return el;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/250409.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

模块单元学习笔记(日志记录模块os模块sys)

一、日志记录模块 Logging 默认情况下&#xff0c;logging将日志打印到屏幕&#xff0c;日志级别大小关系为&#xff1a;CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET&#xff0c;当然也可以自己定义日志级别。 DEBUG&#xff1a;详细的信息,通常只出现…

webpack --- [4.x]你能看懂的webpack项目初始化

说明: 本篇文章主要做如下事情: 创建一个基本的webpack4.x 项目[报错]: The mode option has not been set, webpack will fallback to production for this value[报错]: ERROR in Entry module not found: Error: Can not resolve ./src in D:\L-react\HeiMa\01.webpack-ba…

tomcat8 进入不了Manager App 界面 403 Access Denied

准备 1.注释掉context.xml中的value属性 使用下面的命令&#xff1a; vim /usr/local/tomcats/tomcat-daily/webapps/manager/META-INF/context.xml 注释掉其中value节点 2.修改tomcat-users.xml文件 加入下面的配置 <role rolename"manager-gui" /><role …

SCRIPT70: 没有权限

主要原因&#xff1a;iframe安全而引发的问题&#xff0c;浏览器中js是没有垮域访问的权限的。如果用到iframe首先确保不垮域&#xff0c;或者不用iframe以绕开这个问题。 另外在jquery的早期版本中如&#xff1a;jquery-1.9.1.js $(#iframeWeb).attr(src, url);出现这样的问题…

webpack --- 在项目中使用React

说明: 分为2步: 首先导入react 和 react-dom:保证了虚拟DOM的创建和使用使用babel转码器: 由于DOM结构太多,每次使用React.createElement创建虚拟DOM会给开发带来很大压力,因此采用html的写法,通过babel转码器转换成React语法,可以很大程度上提高开发效率 项目源代码 在项目…

js改变select下拉框默认选择的option

比较简单&#xff0c;记录一下 var obj document.getElementById("fun"); obj.options[0].selected true; 转载于:https://www.cnblogs.com/vicF/p/9844028.html

vue拦截器实现统一token,并兼容IE9验证

项目中使用vue搭建前端页面&#xff0c;并通过axios请求后台api接口&#xff0c;完成数据交互。如果验证口令token写在在每次的接口中&#xff0c;也是个不小的体力活&#xff0c;而且也不灵活。这里分享使用vue自带拦截器&#xff0c;给每次请求的头部添加token&#xff0c;而…

Android Studio --- [学习笔记]Button、TextView、EditText

说明 源代码为了更全面的了解RN,先熟悉一下Android开发 第1章 Android 初体验 1.1 Android开发概述 Android是Google开发的操作系统Android开发是移动应用开发的表现形式之一(Android、IOS、H5 App、Native H5、 RN、ionic、MUI…) 1.2 Android开发工具 Android Studio为…

BZOJ2154: Crash的数字表格 BZOJ2693: jzptab

【传送门&#xff1a;BZOJ2154&BZOJ2693】 简要题意&#xff1a; 给出n,m&#xff0c;求$\sum_{i1}^{n}\sum_{j1}^{m}LCM(i,j)$ 题解&#xff1a; 莫比乌斯反演&#xff08;因为BZOJ2693是多组数据&#xff0c;数据强一点&#xff0c;所以代码用BZOJ2693的&#xff09; 设n…

对于数据库表排他更新的理解

1. 首先任何应用程序都只能有一个服务端&#xff0c;服务端共享数据给多个客户端访问。 (ア) 客户端从服务端取得相应的数据。 (イ) 或者更新、删除服务端的内容。 2. 当客户端A进入服务端方法更新数据库&#xff0c;服务端方法将被锁定。其它客户端在访问该方法时&#xff0c…

Angular 路由守卫

1. 路由 Angular路由: 可以控制页面跳转&#xff1b;可以在多视图间切换&#xff1b; 2. 路由守卫 Angular路由守卫&#xff1a; 在进入或离开某路由时&#xff0c;用于判断是否可以离开、进入某路由&#xff1b;&#xff1b;&#xff1b; return true 代表可以进入当前路由&am…

Vue页面手动刷新,导航栏激活项还原到初始状态问题解决方案

场景描述&#xff1a;在页面中存在顶部导航和左侧导航&#xff0c;左侧导航和右侧内容区使用了命名视图实现&#xff0c;点击左侧导航的链接时&#xff0c;右侧内容区相应显示不同组件内容。问题&#xff1a;在当前链接手动刷新浏览器&#xff08;例如&#xff1a;浏览器地址为…

Android Studio --- [学习笔记]RadioButton、CheckBox、ImageView、ListView、TCP的三次握手

说明 源代码在2.x里有TCP的三次挥手与四次握手,先对它进行简单的回答(百度).预计在下一篇里,会继续说明TCP接上一篇: Android Studio — > [学习笔记]Button、TextView、EditText 2.5 RadioButton 常用属性自定义样式监听事件 2.5.1 新建按钮,并跳转到相应的活动页面 1.…

洛谷3171 网络吞吐量(网络流)

t开成n结果cur赋值的时候也只赋值到t令人智熄 【题目分析】 好吧我承认这个错误真的呵呵。。。。。。。。 题目有那~~~~~么长&#xff0c;然后画画图这道题就基本看出正解了&#xff0c;再一看数据范围&#xff0c;n<500简直良心&#xff0c;好了&#xff0c;网络流没得跑了…

DIV+CSS布局的优势和弊端

DIVCSS的优势1、符合W3C标准。这保证您的网站不会因为将来网络应用的升级而被淘汰。2、对浏览者和浏览器更具亲和力。由于CSS富含丰富的样式&#xff0c;使页面更加灵活性&#xff0c;它可以根据不同的浏览器&#xff0c;而达到显示效果的统一和不变形。这样就支持浏览器的向后…

Android Studio --- [学习笔记]TCP(第2弹)、GridView、ScrollView

说明 这篇主要接上一篇Android Studio — > [学习笔记]RadioButton、CheckBox、ImageView、ListView、TCP的三次握手对上面回答的细解,并用JS伪代码,对TCP三次握手和四次挥手的简单实现.Android的基本了解到此篇结束,后续会根据具体情况深度学习. 2.y TCP的三次握手和四次挥…

MySQL中varchar最大长度是多少

一. varchar存储规则&#xff1a; 4.0版本以下&#xff0c;varchar(20)&#xff0c;指的是20字节&#xff0c;如果存放UTF8汉字时&#xff0c;只能存6个&#xff08;每个汉字3字节&#xff09; 5.0版本以上&#xff0c;varchar(20)&#xff0c;指的是20字符&#xff0c;无论存放…

bzoj 1232: [Usaco2008Nov]安慰奶牛cheer【最小生成树】

有趣 每条边在算答案的时候被算了二倍的边权值加上两个端点的权值&#xff0c;然后睡觉点额外加一次 所以可以用这个权做MST&#xff0c;然后加上点权最小的点 #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N1…

JavaScript --- [学习笔记]观察者模式 理解对象 工厂模式 构造函数模式

说明 本系列(JS基础梳理)为后面TCP的模拟实现做准备本篇的主要内容: 观察者模式、工厂模式、构造函数模式 和 对对象的理解 1. 观察者模式 参考JavaScript设计模式 1.1 消息注册方法 “将订阅者注册的消息推入到消息队列中” [算法思路] : 在推入到消息队列时,如果此消息…

java_day19_MVC和配置文件

简单的MVC设计 MVC的全名是Model View Controller&#xff0c;是模型(model)&#xff0d;视图(view)&#xff0d;控制器(controller)的缩写&#xff0c;是一种软件设计典范。它是用一种业务逻辑、数据与界面显示分离的方法来组织代码&#xff0c;将众多的业务逻辑聚集到一个部件…