虚拟DOM与render函数

news2024/12/24 3:38:01

目录

一、虚拟DOM

1、虚拟DOM是什么

2、为什么要使用虚拟DOM

(1)浏览器显示网页的五步过程:

(2)虚拟DOM的优点

3、Diff算法

二、VNode简介

1、VNode是什么

2、VNode的作用

 3、VNode的优点

4、VNode如何生成:在Vue源码中,VNode是通过一个构造函数生成的。

 VNode的生成过程如下:

 三、render函数

1、初识render函数:

 2、为什么使用render函数

3、render函数的解析

四、实例属性

1、组件树的访问

2、虚拟DOM的访问:

五、实例方法

1、实例DOM方法的使用

2、实例event方法的使用

3、$watch()的使用


一、虚拟DOM

1、虚拟DOM是什么

​ (1) Vue通过建立一个虚拟DOM树对真实DOM发生的变化保持追踪。

​ (2)一棵真实DOM树的渲染需要先解析CSS样式和DOM树,然后将其整合成一棵渲染树,再通过布局算法去计算每个节点在浏览器中的位置,最终输出到显示器上。而虚拟DOM则可以理解为保存了一棵DOM树被渲染前所包含的所有信息,这些信息可以 通过对象的形式一直保存在内存中,并通过javascript的操作进行维护

2、为什么要使用虚拟DOM

(1)浏览器显示网页的五步过程:

​         a、解析标签,生成元素树(DOM树)

        ​ b、解析样式,生成样式树

​         c、生成元素与样式的关系

        ​ d、生成元素的显示坐标

        ​ e、显示页面

若修改真实的DOM元素,那么上述5步将重新走一遍,修改几次就走几遍,性能很差。如果使用虚拟DOM,虚拟DOM存储在内存中,对每个元素的修改是在内存中进行的,修改完后,比较虚拟DOM和真实DOM的差异,当有差异时,再一次过去更新网页的显示,而不是每次都重新按照浏览器的运行过程走。

(2)虚拟DOM的优点

a、保证性能的下限:框架的虚拟DOM需要适应任何上层API可能产生的操作,它的一些DOM操作的实现必须是普适的,所以它的性能并不是最优的,但是比起粗暴的DOM操作性能要好很多,因此框架的虚拟DOM至少可以保证在不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限

b、无须手动操作DOM:只需要编写好View-Model的代码逻辑,框架会根据虚拟DOM和数据双向绑定,以可以预期的方式更新视图,极大的提高开发效率

c、跨平台:虚拟DOM本质是javascript对象,而DOM与平台强相关。相比之下虚拟DOM可以进行更方便地跨平台操作

3、Diff算法

当虚拟DOM发生改变时,为了以最小的性能开销完成更新操作,需要比较新旧虚拟DOM,用于比较的算法称为Diff算法

​ Diff算法本身非常复杂,实现难度很大。常用的核心函数有两个

(1)patch(container,vnode):将虚拟DOM渲染成真正的DOM。即在初次渲染的时候,将虚拟的DOM渲染成真正的DOM,然后插入到容器里面

function createElement(vnode){
    var tag = vnode.tag
    var attrs = vnode.attrs || {}
    var children = vnode.children || []
    if(!tag){
       return null
    }
    //创建真实的DOM元素
    var vm = document.createElement(tag)
    //定义属性
    var attrName
    for(attrName in attrs){
       if(attrs.hasOwnProperty(attrName)){
           vm.setAttribute(attrName,attrs[attrName])
       }
    }
    //定义子元素
    children.forEach(function(childVnode){
       //给vm添加子元素,如果还有子节点,则递归的生成子节点
       vm.appendChild(createElement(childVnode))
    })
    //返回真实的DOM元素
    return  vm
}

(2)patch(vnode,newVnode);再次渲染的时候,将新的VNode和旧的VNode进行对比,然后将之间的差异应用到所构建的真实DOM树上。

function updateChildren(vnode,newVnode){
   var children = vnode.children || []
   var newChildren = newVnode.children || []
   //遍历现有的children
   children.forEach(function(childVnode,index){
      var newChildVnode = newChildren[index]
      if(childVnode.tag === newChildVnode.tag){
         //深层次对比,递归
         updateChildren(childVnode,newChildVnode)
      }else{
         //两者tag不一样,则替换
         replaceNode(childVnode,newChildVnode)
      }
   })
}

二、VNode简介

1、VNode是什么

 VNode是JavaScript对象。VNode表示Virtual DOM,用JavaScript对象来描述真实的DOM把DOM标签,属性,内容都变成对象的属性。就像使用JavaScript对象对一种动物进行说明一样{name: ‘Hello Kitty’, age: 1, children: null}。

2、VNode的作用

通过rendertemplate模版描述成VNode,然后进行一系列操作之后形成真实的DOM进行挂载。

 3、VNode的优点

(1)兼容性强,不受执行环境的影响。VNode因为是JS对象,不管Node还是浏览器,都可以统一操作,从而获得了服务端渲染、原生渲染、手写渲染函数等能力。

(2)减少操作DOM,任何页面的变化,都只使用VNode进行操作对比,只需要在最后一步挂载更新DOM,不需要频繁操作DOM,从而提高页面性能。

4、VNode如何生成:在Vue源码中,VNode是通过一个构造函数生成的。

export default class VNode {
  constructor (
    tag?: string,
    data?: VNodeData,
    children?: ?Array<VNode>,
    text?: string,
    elm?: Node,
    context?: Component,
    componentOptions?: VNodeComponentOptions,
    asyncFactory?: Function
  ) {
    this.tag = tag
    this.data = data
    this.children = children
    this.text = text
    this.elm = elm
    this.ns = undefined
    this.context = context
    this.fnContext = undefined
    this.fnOptions = undefined
    this.fnScopeId = undefined
    this.key = data && data.key
    this.componentOptions = componentOptions
    this.componentInstance = undefined
    this.parent = undefined
    this.raw = false
    this.isStatic = false
    this.isRootInsert = true
    this.isComment = false
    this.isCloned = false
    this.isOnce = false
    this.asyncFactory = asyncFactory
    this.asyncMeta = undefined
    this.isAsyncPlaceholder = false
  }
}

 VNode的生成过程如下:

// 模版
<a class="demo" style="color: red" href="#">
    generator VNode
</a>
// VNode描述
{
  tag: 'a',
  data: {
    class: 'demo',
    attrs: {
      href: '#'
    },
    style: {
      color: 'red'
    }
  },
  children: ['generator VNode']
}
//这个JS对象,已经囊括了整个模板的所有信息,完全可以根据这个对象来构造真实DOM。

 三、render函数

1、初识render函数:

import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
new Vue({
  el: '#app',
  render: h => h(App)
})

 2、为什么使用render函数

 vue推荐在绝大多数情况下使用template来创建我们的HTML。然而在一些场景中,我们真的需要JavaScript的完全编程的能力,这就是render函数,它比template更接近编译器。(这是官方的话)

import Vue from "vue";

这一个引入你看似没有任何问题,但问题恰恰就是出在这。在不同版本的vue中,有vue.js和vue.runtime.xxx.js这两种js文件。其中 

(1)vue.js是完整版的vue,包含核心功能+模板解析器。

​ (2)vue.runtime.xxx.js是运行版vue,只包含核心功能,没有模板解析器。

​ vue开发者为了让我们打包的文件能尽可能小一点,在上述引入的是运行版vue。因为vue.runtime.xxx.js没有模板解析器,所以不能使 用template配置项,这时候就需要使用render函数去接收到的createElement函数去指定具体内容,创建html模板。

3、render函数的解析

​ render 函数即渲染函数,它是个函数,它的参数 createElement 也是个函数。

​ 上边的代码中 render: h => h(App) ,这是 ES6的箭头函数的写法,可以把 h 当作 createElement 的别名。所以这段代码其实相当​ 于:

render: function (createElement) {
    return createElement(App);
}

 这个函数的作用就是生成一个 VNode节点,render 函数得到这个 VNode 节点之后,返回给 Vue.js 的 mount 函数,渲染成真实DOM 节点,并挂载到根节点上。

createElement 函数的返回值是 VNode(即:虚拟节点)

​ createElement 函数的3个参数

(1)一个 HTML 标签字符串,组件选项对象,或者解析上述任何一种的一个 async 异步函数。类型:String | Object | Function。必 需。

​ (2)一个包含模板相关属性的数据对象,你可以在 template 中使用这些特性。类型:Object。可选。

​ (3)子虚拟节点 (VNodes),由 createElement() 构建而成,也可以使用字符串来生成“文本虚拟节点”。类型:String | Array。可选。

new Vue({
  el: '#app',
  render:function (createElement) {
    //1.普通用法
    // createElement(标签,{属性},[内容])
    return createElement("h2",{class:"box"},['hello',createElement("button",["按钮"])])
  }
})

 

 同时createElement也可以传进去一个组件,因此

render: h => h(App)
//等同于
render:function (createElement) {
    return createElement(App)
  }

四、实例属性

​ Vue实例暴露了一些有用的实例属性与方法,这些实例属性与方法都有前缀$,以便与代理的数据属性区分

1、组件树的访问

​ (1)$parent:用来访问组件实例的父实例(父组件)

​ (2)$root:用来访问当前组件树的根实例(根组件)

​ (3)$children:用来访问当前组件实例的直接子组件实例

​ (4)$refs:用来访问v-refs指令的子组件

2、虚拟DOM的访问:

​ (1)$el:表示挂载当前组件实例的DOM元素

​ (2)$data:用来访问组件实例观察的数据对象

五、实例方法

1、实例DOM方法的使用

​ (1)$appendTo(elementOrSelector,callback):将el所指的DOM元素插入目标元素

​ (2)$before(elementOrSelector,callback):将el所指的DOM元素插入目标元素之前

​ (3)$after(elementOrSelector,callback):将el所指的DOM元素插入目标元素之后

​ (4)$remove(callback):将el所指的DOM元素或片段从DOM中删除

​ (5)$nextTick(callback):用来在下一次DOM更新循环后执行指定的回调函数

2、实例event方法的使用

​ (1)$on(event,callback):监听实例的自定义事件

​ (2)$once(event,callback):监听实例的自定义事件,但是只能触发一次

​ (3)$dispatch(event,args):派发事件,先在当前实例触发,再沿父链一层层向上,对应的监听函数返回false则停止

​ (4)$emit(event,args):触发事件

3、$watch()的使用

var obj = { a: 1 }
var vm = new Vue({
   el: '#app',
   data: obj
})
vm.$data === obj  //-> true
vm.$el === document.getElementById('app') // ->true
vm.$watch('a',function(newVal,oldVal){
    //这个回调函数将在vm.a改变后触发
})

 

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

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

相关文章

【FreeRTOS】详细讲解FreeRTOS中消息队列并通过示例讲述其用法

讲解FreeRTOS中消息队列及其用法使用消息队列的原因消息队列函数解析示例遇到的问题使用消息队列的原因 在裸机系统中&#xff0c;两个程序间需要共享某个资源通常使用全局变量来实现&#xff1b;但在含操作系统(下文就拿FreeRTOS举例)的开发中&#xff0c;则使用消息队列完成。…

MonekyRunner

MonekyRunner 文章目录MonekyRunner一、简介二、JDK环境变量三、配置Android SDK环境变量3.1.下载并解压&#xff1a;3.2.环境变量&#xff1a;3.3.查看MonkeyRunner&#xff1a;四、编写Python脚本五、运行脚本一、简介 MonkeyRunner是Android SDK中自带的工具之一&#xff0…

python3:基础语法、及6种基本数据类型、找到字典的下标 index、获取list中指定元素的位置索引

基础语法 源码文件以 UTF-8 编码&#xff0c;所有字符串都是 unicode 字符串 Python 3 中&#xff0c;可以用中文作为变量名&#xff0c;非 ASCII 标识符也是允许的 标识符 第一个字符必须是字母表中字母或下划线 _ 。 标识符的其他的部分由字母、数字和下划线组成。 标识…

Java---微服务---微服务保护Sentinel

微服务保护Sentinel1.初识Sentinel1.1.雪崩问题及解决方案1.1.1.雪崩问题1.1.2.超时处理1.1.3.仓壁模式1.1.4.断路器1.1.5.限流1.1.6.总结1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel1.3.2.安装Sentinel1.4.微服务整合Sentinel2.流量控制2.1.簇点链路2.1.快…

【自然语言处理】基于sklearn-crfsuite进行命名实体识别

基于sklearn-crfsuite进行命名实体识别0. 条件随机场1. 训练数据2. 特征提取3. 训练一个CRF模型4. 评估5. 超参数优化6. 检查参数空间7. 检查在测试数据上的最优估计器8.检查分类器学到了什么东西9.检查模型权重10. 定制化11.在控制台中进行格式化参考资料本文中&#xff0c;针…

一种前端无源码定制化开发能力专利解读

背景 目前市面上一些web前端工程在打包发布之前都会进行代码混淆加密。代码混淆(Obfuscated code)是将计算机程序的代码&#xff0c;转换成一种功能上等价&#xff0c;但是难于阅读和理解的形式的行为。代码混淆可以用于程序源代码&#xff0c;也可以用于程序编译而成的中间代…

Leetcode刷题Day38-------------------动态规划

Leetcode刷题Day38-------------------动态规划 1. 理论基础 文章链接&#xff1a;https://programmercarl.com/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html视频链接&#xff1a;https://www.bilibili.com/video/BV13Q4y197Wg题目链接&a…

GBASE荣获“2022证券基金行业信息技术应用创新联盟年度优秀成员奖

日前&#xff0c;证券基金行业信息技术应用创新联盟2022年度峰会于上海成功举办&#xff0c;在会上&#xff0c;GBASE南大通用作为联盟成员单位&#xff0c;积极相应联盟号召&#xff0c;有力支撑证券信创建设&#xff0c;荣获“2022证券基金行业信息技术应用创新联盟年度优秀成…

第一章 Arm 架构概述(2023新)

第一章 启发式 Arm 架构解读 第二章 CPU微架构 第三章 系统微架构 第四章 总线微架构 第五章 监控微架构 第六章 安全微架构 第七章 虚拟化微架构 第八章 Armv9-A 架构 第九章 Armv8-M 架构 第十章 Armv8-R 架构 第十一章 Cortex-A715 解读 第十二章 Cortex-X3 解读…

图片怎么转成PDF格式?介绍三种转换思路

PDF文件作为一类办公常见格式&#xff0c;很多场合都会使用到。有时我们需要将图片转成PDF格式以方便归纳整理。图片资料怎么转成PDF呢&#xff1f;给大家介绍几个手机和电脑都可以用的方式。希望对你有帮助。方法一、用文件自带的转换功能将图片转成PDF随意打开一个PDF文件后&…

Github每日精选(第94期):免费网页在线情况监控

Upptime Upptime 是开源的正常运行时间监控和状态页面&#xff0c;完全由 GitHub Actions、Issues 和 Pages 提供支持。 Upptime 是 [GitHub Actions] 的一个非常巧妙的用法。您基本上可以根据需要获得免费的可配置正常运行时间监视器。 github 地址在这里。 特点 利用 G…

CTPN的Python实现笔记一

文章目录一、疑难代码讲解1. 文本框左上角标注置信度(1) s str(round(i[-1] * 100, 2)) %(2) cv2.putText() 函数(3) cv2.line()函数2. 文本框进行扩展操作3. 文本框进行NMS操作(1) 非极大值抑制函数def nms(dets, thresh):a. order scores.argsort()[::-1]b. xx1 np.maxim…

[oeasy]python0068_控制序列_清屏_控制输出位置_2J

光标位置 回忆上次内容 上次了解了键盘演化的过程 ESC 从 组合键到 独立按键 ESC 的目的 是进入控制序列配置控制信息 控制信息 \033[y;xH 设置光标位置\033[2J 清屏 这到底怎么控制来着&#xff1f;&#xff1f;&#xff1f;&#x1f914;现在 系统里 这些行为 是谁来实现的…

【机器学习 - 6】:梯度下降法(第一篇)

文章目录梯度下降法的理解图解极值点和最值点梯度下降法的求导运算公式推导梯度下降法的实现梯度下降法的理解 梯度下降法不是一个机器学习算法&#xff0c;既不是在做监督学习&#xff0c;也不是在做非监督学习&#xff0c;是一种基于搜索的最优化方法。 作用&#xff1a;最小…

【2319. 判断矩阵是否是一个 X 矩阵】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 如果一个正方形矩阵满足下述 全部 条件&#xff0c;则称之为一个 X 矩阵 &#xff1a; 矩阵对角线上的所有元素都 不是 0 矩阵中所有其他元素都是 0 给你一个大小为 n x n 的二维整数数组 grid &a…

JVM虚拟机知识总结

什么是虚拟机&#xff1f;从字面意思上来看&#xff0c;顾名思义即使一台虚拟的计算机&#xff0c;用来执行虚拟的计算机指令&#xff0c;从大体上来看&#xff0c;虚拟机一般分为两种。一种是系统虚拟机&#xff0c;另外一种是程序虚拟机。系统虚拟机&#xff1a;代表为VMware…

微信小程序 java中医知识库百科科普

中管理员的主要功能有&#xff1a; 1.管理员输入账户登陆后台 2.个人中心&#xff1a;管理员修改密码和账户信息 3.用户管理&#xff1a;对注册的用户信息进行删除&#xff0c;查询&#xff0c;添加&#xff0c;修改 4.中医知识管理&#xff1a;对中医的知识信息进行添加&#…

什么是地址解析协议 (ARP)?

最近不想更文章了&#xff0c;药吃完了&#xff0c; 本文目录地址解析协议 &#xff08;ARP&#xff09; 含义ARP 是做什么的&#xff0c;它是如何工作的&#xff1f;地址解析协议与 DHCP 和 DNS 的关系是什么&#xff1f;它们有何不同&#xff1f;ARP 有哪些类型&#xff1f;1…

应急救护培训报名-因疫情原因,暂停开班?

应急救护培训报名背景和急救证书区别2023年一定要被培训项目报名渠道状态上海市红十字应急救护培训上海市医疗急救中心公众课程专业课程背景和急救证书区别 关于背景和急救证书区别&#xff0c;请参考&#xff0c;程序员的生命与急救 文章 2023年一定要被培训项目 由于疫情原…

Springboot+vue冷冻仓储进销存管理系统 java

端技术&#xff1a;nodejsvueelementui 前端&#xff1a;HTML5,CSS3、JavaScript、VUE 系统分为不同的层次&#xff1a;视图层&#xff08;vue页面&#xff09;&#xff0c;表现层&#xff08;控制器类&#xff09;&#xff0c;业务层&#xff08;接口类&#xff09;和持久层&a…