从虚拟dom了解vue渲染函数
vue渲染函数就是render函数,他会返回一个VNode,VNode是一个js对象,是dom的映射
vue在介绍渲染函数那个章节看的不是很懂,所以想要彻底的理解渲染函数,首先需要了解vue的虚拟dom
关于虚拟dom的介绍,这里有一篇很好的文章,我也是看了这篇才茅塞顿开:https://www.zhihu.com/question/29504639
我来概括一下虚拟dom的工作是将浏览器的dom节点的所有信息映射到一个js对象上面,因为js本身是很快的,但是dom操作本身很慢,如果我们把dom的信息映射到js对象上面,至少当获取dom信息时候 我们不需要去遍历dom了,而另一方面对于dom的操作一直是js优化的重点,使用虚拟dom,程序员不需要自己去操作dom,所以关于dom的操作都会由虚拟dom完成,而虚拟dom一定会以最优方案来进行操作,所以虚拟dom的重点是构建一个浏览器dom的信息拷贝树,拷贝树里面必须包含所有dom节点的拷贝节点,我们把这个拷贝节点叫做VNode
关于虚拟dom的好处还有一个就是vue会把所有的dom操作缓存到一个队列,这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。请看vue官方对于异步更新队列的解释:https://cn.vuejs.org/v2/guide/reactivity.html,
刚才我们说到VNode是什么,那VNode里面包含哪些信息呢:
tag
: 当前节点的标签名data
: 当前节点的数据对象,具体包含哪些字段可以参考vue源码types/vnode.d.ts
中对VNodeData
的定义children
: 数组类型,包含了当前节点的子节点text
: 当前节点的文本,一般文本节点或注释节点会有该属性elm
: 当前虚拟节点对应的真实的dom节点ns
: 节点的namespacecontext
: 编译作用域functionalContext
: 函数化组件的作用域key
: 节点的key属性,用于作为节点的标识,有利于patch的优化componentOptions
: 创建组件实例时会用到的选项信息child
: 当前节点对应的组件实例parent
: 组件的占位节点raw
: raw htmlisStatic
: 静态节点的标识isRootInsert
: 是否作为根节点插入,被<transition>
包裹的节点,该属性的值为false
isComment
: 当前节点是否是注释节点isCloned
: 当前节点是否为克隆节点isOnce
: 当前节点是否有v-once
指令
那如何创建VNode呢,首先为什么要创建VNode,因为我们使用vue所有的操作都是针对vue的虚拟dom也就是VNode的,然后vue将虚拟dom更新到真实dom,而我们经常使用的vue组建 也是在底层先变成虚拟dom然后再变成真实dom,拿好了 既然组建是先变成虚拟dom再变成VNode,那我们理论上可以自己创建VNode,然后让vue将我们创建的VNode更新到真实dom上,这样更自由 权限更大,创建VNode的方法是createElement
createElement(tag,{},[]) 或者createElement(tag,{},string)
其中tag是创建元素的标签名
{}是创建元素的属性
[]是创建元素的子元素列表
string是文本
所以最终我们可以这样使用createElement:
Vue.component('anchored-heading', { render: function (createElement) { return createElement( 'h' + this.level, // tag name 标签名称 this.$slots.default // 子组件中的阵列 ) }, props: { level: { type: Number, required: true } } })
关于this.$slots.defalt:
slot我们知道是插槽,关于插槽我认为最好的解释是:在父组件中放入已被 `slot` 标记的内容,这些内容的顺序可以随意。之后这些内容被分发到子组件的特殊元素 `slot` 中,根据 `name` 属性在子组件中重新组合。this.$slots用来访问被插槽分发的内容,这一点vue解释的很清楚:https://cn.vuejs.org/v2/api/#vm-slots
这里使用一个例子来加深this.$slots.defalt的理解:
var getChildrenTextContent = function (children) { return children.map(function (node) { return node.children ? getChildrenTextContent(node.children) : node.text }).join('') } Vue.component('anchored-heading', { render: function (createElement) { // create kebabCase id var headingId = getChildrenTextContent(this.$slots.default) .toLowerCase() .replace(/\W+/g, '-') .replace(/(^\-|\-$)/g, '') return createElement( 'h' + this.level, [ createElement('a', { attrs: { name: headingId, href: '#' + headingId } }, this.$slots.default) ] ) }, props: { level: { type: Number, required: true } } })
这里我们首先getChildrenTextContent,getChildrenTextContent方法的参数是一个数组,说明this.$slot.defaul是一个数组,他其实就是[VNode,Vnode..],this.$slot.default数组里每一个都是VNode对象,上文我们提到到VNode有哪些属性,所以我们看到getChildrenTextContent方法里去判断VNode的children属性,如果VNode有子元素就继续向下寻找,如果没有则直接取他的文本,所以最终我们拿到的是准备放在slot位置的所有非具名元素的文本的拼接。
从虚拟dom了解vue渲染函数的更多相关文章
- vue渲染函数&JSX
Vue推荐在绝大多数情况下使用template来创建你的HTML.然而在一些场景中,你真的需要JavaScript的完全编程能力,这时你可以使用render函数,它比template跟接近编译器. 虚 ...
- Vue渲染函数
前面的话 Vue 推荐在绝大多数情况下使用 template 来创建HTML.然而在一些场景中,真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更 ...
- vue 渲染函数&jsx
前端更新状态,更新视图,所以性能问题主要由Dom操作引起的,而js解析编译dom渲染就要快得多, 所把要js和html混写. vue 的动态js操作 html 方法:reader函数: vue ...
- Vue 渲染函数
Vue 推荐在绝大多数情况下使用模板来创建你的 HTML.然而在一些场景中,你真的需要 JavaScript 的完全编程的能力.这时你可以用渲染函数,它比模板更接近编译器. 一 项目结构 二 App组 ...
- vue从入门到进阶:渲染函数 & JSX(八)
Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML.然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接 ...
- Vue如何用虚拟dom进行渲染view的
前提 vue版本:v2.5.17-beta.0 触发render vue在数据更新后会自动触发view的render工作,其依赖于数据驱动:在数据驱动的工作下,每一个vue的data属性都被监听,并且 ...
- 详解Vue中的虚拟DOM
摘要: 什么是虚拟DOM? 作者:浪里行舟 Fundebug经授权转载,版权归原作者所有. 前言 Vue.js 2.0引入Virtual DOM,比Vue.js 1.0的初始渲染速度提升了2-4倍,并 ...
- 对vue虚拟dom的研究
Vue.js通过编译将template 模板转换成渲染函数(render ) ,执行渲染函数就可以得到一个虚拟节点树 在对 Model 进行操作的时候,会触发对应 Dep 中的 Watcher 对象. ...
- vue核心之虚拟DOM
一.前言 虚拟DOM概念随着react的诞生而诞生,由facebook提出,其卓越的性能很快得到广大开发者的认可:继react之后vue2.0也在其核心引入了虚拟DOM的概念,本文将以vue2.0使用 ...
随机推荐
- day14 python各种推导式详解
推导式的套路 之前我们已经学习了最简单的列表推导式和生成器表达式.但是除此之外,其实还有字典推导式.集合推导式等等. 下面是一个以列表推导式为例的推导式详细格式,同样适用于其他推导式. variabl ...
- postman+newman+jenkins 接口自动化问题
声明:个人原创,转载请注明 1.安装postman工具 下载地址:https://www.getpostman.com/点击下载,选择自己的系统,我的是windows系统,64位 2.postman ...
- spring源码解析1--spring整体架构
一.Spring整体架构图 关于Spring的基本介绍就不再赘述了,先展示Spring框架的整体架构图如下示: 二.Spring结构介绍 Spring主要分为Core Container.Test.D ...
- SQLServer 2008以上误操作数据库恢复方法
解决方法: 对于这类问题,主要是找回误操作之前的数据,在2008之前,有个很出名的工具Log Exploer,听说还挺好用的,这个网上大把教程,这里就不多说了.但是唯一遗憾的是,不支持20 ...
- Linux的邮件服务器配置
一.邮件服务简介 1.电子邮件服务是Interne上最基本的服务之一,进入互联网的用户不需要任何纸张就可以方便地使用电子邮件来收发邮件 2.Internet上的电子邮件服务都是基于客户/服务器模式的 ...
- inputClient.js
$(document).ready(function () { loadData();}); //初始化数据function loadData(){ loadMList();//加载数据 $(&quo ...
- 关于Java多线程的一些常考知识点
前言 Java多线程也是面试中经常会提起到的一个点.面试官会问:实现多线程的两种方式以及区别,死锁发生的4个条件以及如何避免发生死锁,死锁和活锁的区别,常见的线程池以及区别,怎么理解有界队列与无界队列 ...
- 读取本地json文件,并转换为dictionary
// 读取本地JSON文件 - (NSDictionary *)readLocalFileWithName:(NSString *)name { // 获取文件路径 NSString *path = ...
- UI自动化(十四)yaml配置文件
import yamlimport jsonf = open('config.yaml','rb')data = yaml.load(f)print(json.dumps(data,indent=4) ...
- [c/c++] programming之路(31)、位运算(二)
一.取反的高级用法 #include<stdio.h> #include<stdlib.h> //取反的作用:末位清零 取反适用于各种位数不同的数据 void main0(){ ...