vue的虚拟DOM会操作DOM吗?,vue的dom操作
本文主要介绍vue虚拟DOM的相关资料,帮助大家更好的理解和学习使用vue框架。感兴趣的朋友可以了解一下。
目录
虚拟DOM
什么是虚拟dom?
虚拟dom的功能
vue中的虚拟dom
虚拟节点
什么是vNode?
vNode的类型
修补
添加节点
删除节点
更新节点
新节点-源代码分析
删除节点-源代码分析
虚拟 DOM
什么是虚拟 dom
Dom是一种文档对象模型,它以节点树的形式表示文档。
虚拟dom不是真正的dom。它是一个javascript对象。
一个普通的dom节点用html表示如下:
div class=testId
p你好/p
p欢迎访问/p
/div
在虚拟dom中,大概是这样的:
{
标签:“div”,
属性:{
类别:[testId]
},
儿童:[
//p元素
//p元素
]
}
我们可以把虚拟dom拆分成两部分来理解:虚拟dom。
Virtual:表示虚拟dom不是真正的dom,而是一个javascript对象;
Dom:意味着虚拟dom可以用节点树的形式表示文档。
虚拟 dom 的作用
现在主流的框架都是dom声明式操作的框架。我们只需要描述状态和dom的映射关系,框架会做状态到视图(真实dom)的转换。
最残忍的方式是把状态渲染成视图,每次状态更新,整个视图又更新一次。
这种做法的表现可想而知。更好的想法是:如果状态改变,只更新与状态相关的dom节点。虚拟dom只是实现这一想法的方式之一。
具体做法:
状态-真实dom(初始)
状态-虚拟dom-真实dom(使用虚拟DOM)
改变状态,重新生成一个虚拟的dom,对比之前的和这个,找出需要更新的部分,更新真实的dom。
vue 中的虚拟 dom
真实的dom是由节点组成的,而虚拟的dom是由虚拟节点组成的。
虚拟dom在vue中主要做两件事:
提供了对应于真实节点的虚拟节点(vNode)。
将新的虚拟节点与旧的虚拟节点进行比较,找出差异,然后更新视图。
“虚拟DOM”是我们对Vue组件树,—— vue官网建立的整个VNode树的称呼。
vNode
什么是 vNode
如上所述,vNode(虚拟节点)对应于真实节点。
VNode可以理解为一个节点描述对象。描述如何创建真正的dom节点。
vue.js中有一个vNode类你可以用它来创建不同类型的vNode实例,不同类型的vNode对应不同类型的dom元素。代码如下:
导出默认类VNode {
构造器(
标签?字符串,
数据?VNodeData,
孩子?数组节点,
文字?字符串,
榆树?节点,
语境?组件,
组件选项?VNodeComponentOptions,
asyncFactory?功能
) {
this.tag=标签
this.data=数据
this.children=儿童
this.text=text
this.elm=榆树
this.ns=未定义
this.context=上下文
this.fnContext=undefined
this.fnOptions=未定义
this.fnScopeId=undefined
this.key=data data.key
this . component options=component options
this . component instance=undefined
this.parent=undefined
this.raw=false
this.isStatic=false
this.isRootInsert=true
this.isComment=false
this.isCloned=false
this.isOnce=false
this.asyncFactory=异步工厂
this.asyncMeta=undefined
this.isAsyncPlaceholder=false
}
get child (): Component void {
返回this.componentInstance
}
}
从代码中不难看出,vNode类创建的实例本质上是一个普通的javascript对象。
vNode 的类型
我们已经介绍了不同类型的vNode可以通过vNode类创建。而不同类型的vNode由有效属性来区分。比如isComment=true表示评论节点;IsCloned=true表示克隆节点等等。
vNode类型有:注释节点、文本节点、克隆节点、元素节点和组件节点。
以下是注释节点、文本节点和克隆节点的代码:
/*
注释节点
有效属性:{isComment: true,text:注释节点 }
*/
export const createEmptyVNode=(text:string= )={
const node=新VNode()
node.text=文本
//注释
node.isComment=true
返回节点
}
/*
文本节点
有效属性:{text: text node}
*/
导出函数createTextVNode(val:string number){
返回新的VNode(未定义,未定义,未定义,字符串(val))
}
//优化的浅层克隆
//用于静态节点和插槽节点,因为它们可以在
//用于静态节点和插槽节点
//多个渲染,克隆它们可以避免DOM操作依赖时的错误
//在他们的elm引用上。
//克隆节点
导出函数cloneVNode (vnode: VNode): VNode {
const cloned=新虚拟节点(
vnode.tag,
vnode.data,
//#7975
//克隆子数组以避免在克隆时改变原始数组
//一个孩子。
vnode . children vnode . children . slice(),
vnode.text,
vnode.elm,
vnode.context,
vnode.componentOptions
vnode .异步工厂
)
cloned.ns=vnode.ns
cloned.isStatic=vnode.isStatic
cloned.key=vnode.key
cloned . is comment=vnode . is comment
cloned . fn context=vnode . fn context
cloned . fn options=vnode . fn options
cloned . fnscopeid=vnode . fnscopeid
cloned . async meta=vnode . async meta
//标记是克隆节点
cloned.isCloned=true
返回克隆的
}
克隆一个节点实际上是将一个现有节点的所有属性赋给一个新节点,最后用cloned.isCloned=true将自己标记为克隆节点。
一个元素通常有以下4个属性:
标签:节点的名称。例如div,p
数据:节点上的数据。例如,类别、风格
子节点:子节点
上下文:在组件中呈现
组件节点类似于元素节点,包含两个唯一的属性:
options:component options的选项参数,如propsData、listeners、children和tag。
组件的组件实例。
patch
虚拟dom在vue中做的第一件事前面已经介绍过了:提供一个与真实节点对应的虚拟节点(VNode);接下来介绍第二件事:将新的虚拟节点与旧的虚拟节点进行比较,找出差异,然后更新视图。
vue中第二件事的实现叫做patch,意思是打补丁,打补丁。通过新旧vNode的对比,找出差异,然后修复现有的dom,从而实现视图更新。
对比vNode找差异是手段,更新视图是目的。
而更新视图无非就是添加、删除、更新节点。接下来我们逐一分析何时何地添加节点;何时删除一个节点,删除哪一个;什么时候更新节点,更新哪个;
注:当vNode与oldvNode不同时,以vNode为准。
新增节点
在一种情况下,当vNode存在但oldVNode不存在时,需要添加一个新节点。最典型的是第一次渲染,因为odlVNode不存在。
在另一种情况下,vNode和oldVNode根本不是同一个节点。这时你需要使用vNode生成真正的dom节点,并将其插入oldVNode所指向的真正的dom节点旁边。旧节点是一个废弃的节点。例如,以下情况:
差异
p v-if=type===A
我是节点a。
/p
span v-else-if=type===B
我是和a完全不同的节点B。
/span
/div
当类型从A变为B时,节点将从P变为span。由于vNode和oldVNode根本不是同一个节点,所以需要添加新的节点。
删除节点
当节点只存在于oldVNode中时,删除即可。
更新节点
前面介绍了添加节点和删除节点的场景,它们有一个共同点:vNode和oldVNode完全不同。
但是更常见的情况是vNode和oldVNode是同一个节点。然后我们需要对它们(vNode和oldVNode)进行更细致的比较,然后更新oldVNode对应的真实节点。
对于文本节点,逻辑自然简单。首先,比较旧的vNode和新的vNode,发现是同一个节点。然后,将oldVNode对应的dom节点的文本更改为VNode中的文本。但是对于复杂的vNode,比如界面中的树组件,这个过程会变得复杂。
新增节点 - 源码分析
想想看:前面提到的vNode的类型有:注释节点、文本节点、克隆节点、元素节点、组件节点。这些类型会被创建并插入到dom中吗?
答:只有评论节点、文本节点和元素节点。因为html只知道这几种。
因为只有上面三种类型的节点,所以根据类型创建响应,然后插入到相应的位置。
以一个元素节点为例。如果vNode有tag属性,说明它是一个元素节点。然后调用createElement方法创建相应的节点,再通过appendChild方法插入到指定的父节点中。如果父元素已经在视图中,在它下面插入元素会自动呈现它;如果vNode的isComment属性为true,则表示注释节点;要么是文本节点;
通常一个元素中有子元素,所以涉及到一个递归的过程,就是依次遍历vNode中的子元素,创建节点,然后插入父节点(父节点就是刚刚创建的dom节点),逐层递归进行。
请看源代码:
//创建一个元素
函数createElm(
vnode,
insertedVnodeQueue,
parentElm,
雷菲尔姆,
嵌套,
ownerArray,
指数
) {
if(isDef(vnode . elm)isDef(owner array)){
//此vnode在以前的渲染中使用过!
//现在它被用作新节点,覆盖它的elm将导致
//当它被用作插入时,可能会出现补丁错误
//引用节点。相反,我们在创建之前按需克隆节点
//它的关联DOM元素。
vnode=owner array[index]=cloneVNode(vnode);
}
vnode.isRootInsert=!嵌套;//对于转换,输入check
if (createComponent(vnode,insertedVnodeQueue,parentElm,refElm)) {
返回
}
var data=vnode.data
var children=vnode.children
var tag=vnode.tag
//有标签属性,表示是元素节点。
if (isDef(tag)) {
vnode.elm=vnode.ns
?nodeops . createelementns(vnode . ns,标记)
//创建一个元素。NodeOps涉及跨平台。
:nodeOps.createElement(tag,vnode);
set scope(vnode);
/*伊斯坦布尔忽略if */
{
//递归创建一个子节点,并将其插入父节点。
createChildren(vnode,Children,insertedVnodeQueue);
if (isDef(data)) {
invokeCreateHooks(vnode,insertedVnodeQueue);
}
//将vnode对应的元素插入父元素
insert(parentElm,vnode.elm,ref elm);
}
//isComment属性指示注释节点。
} else if(is true(vnode . is comment)){
vnode . elm=nodeops . create comment(vnode . text);
//插入父节点
insert(parentElm,vnode.elm,ref elm);
//否则,它是子节点
}否则{
vnode . elm=nodeops . create text node(vnode . text);
//插入父节点
insert(parentElm,vnode.elm,ref elm);
}
}
//递归创建一个子节点,并将其插入父节点。Vnode表示父节点。
函数createChildren (vnode,Children,insertedVnodeQueue) {
if (Array.isArray(children)) {
if (process.env.NODE_ENV!==生产){
checkDuplicateKeys(儿童);
}
//依次创建子节点,插入父节点。
for(var I=0;I .儿童.长度;i) {
createElm(children[i],insertedVnodeQueue,vnode.elm,null,true,children,I);
}
} else if(is primitive(vnode . text)){
nodeOps.appendChild(vnode.elm,nodeops . create text node(String(vnode . text)));
}
}
删除节点 - 源码分析
删除一个节点非常简单。直接看源代码:
//删除一组指定的节点
函数removeVnodes (parentElm,Vnodes,startIdx,endIdx) {
for(;startIdx=endIdxstartIdx) {
var ch=vnodes[startIdx];
if (isDef(ch)) {
if (isDef(ch.tag)) {
removeAndInvokeRemoveHook(ch);
invokedesteryhook(ch);
} else { //文本节点
//删除个节点
移除节点(通道。榆树);
}
}
}
}
//删除单个节点
函数删除节点(el) {
var parent=nodeops。父节点(El);
//由于虚拟html /虚拟文本,元素可能已经被删除
if (isDef(parent)) {
//nodeOps里封装了跨平台的方法
nodeOps.removeChild(parent,El);
}
}
以上就是某视频剪辑软件虚拟数字正射影像图快速入门的详细内容,更多关于某视频剪辑软件虚拟数字正射影像图的资料请关注我们其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。