国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Home Web Front-end JS Tutorial How to use the Diff algorithm in Vue 2.5

How to use the Diff algorithm in Vue 2.5

Jun 23, 2018 pm 05:00 PM
diff vue algorithm

This article will analyze the Virtual Dom used in Vue 2.5.3 version. updataChildren is the core of the Diff algorithm, so this article conducts a graphic analysis of updataChildren. Let me share with you the Diff algorithm of Vue 2.5 through this article. Friends who need it can refer to it

DOM is "inherently slow", so all major front-end frameworks provide ways to optimize DOM operations. In Angular It is dirty value checking. React first proposed Virtual Dom, and Vue2.0 also added Virtual Dom, which is similar to React.

This article will analyze the Virtual Dom used in Vue 2.5.3 version.

updataChildren is the core of the Diff algorithm, so this article conducts a graphic analysis of updataChildren.

1.VNode object

A VNode instance contains the following attributes. This part of the code is in src/core/vdom/vnode.js Inside

export default class VNode {
 tag: string | void;
 data: VNodeData | void;
 children: ?Array<VNode>;
 text: string | void;
 elm: Node | void;
 ns: string | void;
 context: Component | void; // rendered in this component&#39;s scope
 key: string | number | void;
 componentOptions: VNodeComponentOptions | void;
 componentInstance: Component | void; // component instance
 parent: VNode | void; // component placeholder node

 // strictly internal
 raw: boolean; // contains raw HTML? (server only)
 isStatic: boolean; // hoisted static node
 isRootInsert: boolean; // necessary for enter transition check
 isComment: boolean; // empty comment placeholder?
 isCloned: boolean; // is a cloned node?
 isOnce: boolean; // is a v-once node?
 asyncFactory: Function | void; // async component factory function
 asyncMeta: Object | void;
 isAsyncPlaceholder: boolean;
 ssrContext: Object | void;
 functionalContext: Component | void; // real context vm for functional nodes
 functionalOptions: ?ComponentOptions; // for SSR caching
 functionalScopeId: ?string; // functioanl scope id support
  • tag: The tag name of the current node

  • data: The data object of the current node. For specific fields, please refer to vue source code types The definition of VNodeData in /vnode.d.ts

  • children: array type, containing the child nodes of the current node

  • text: current The text of the node. Generally, text nodes or comment nodes will have this attribute

  • elm: the real dom node corresponding to the current virtual node

  • ns : Node namespace

  • context: Compilation scope

  • functionalContext: Functional component scope

  • key: The key attribute of the node is used as the identifier of the node, which is beneficial to the optimization of the patch.

  • componentOptions: The option information used when creating a component instance

  • child: the component instance corresponding to the current node

  • parent: the placeholder node of the component

  • raw: raw html

  • isStatic: The identifier of the static node

  • isRootInsert: Whether to insert as the root node, is

  • isComment: Whether the current node is a comment node

  • isCloned: Whether the current node is a clone node

  • isOnce: Whether the current node has v- once directive

2. Classification of VNode

VNode can be understood as a base class of VueVirtual Dom, through VNode The VNnode instances generated by the constructor can be of the following categories:

  • EmptyVNode: Annotation node without content

  • TextVNode: Text node

  • ElementVNode: Ordinary element node

  • ComponentVNode: Component node

  • CloneVNode: Clone node, which can be the above Any type of node, the only difference is that the isCloned attribute is true

3.Create-Element source code analysis

This part of the code is in src/core/vdom/create-element.js. I just paste the code and add my comments

export function createElement (
 context: Component,
 tag: any,
 data: any,
 children: any,
 normalizationType: any,
 alwaysNormalize: boolean
): VNode {
 // 兼容不傳data的情況
 if (Array.isArray(data) || isPrimitive(data)) {
 normalizationType = children
 children = data
 data = undefined
 }
 // 如果alwaysNormalize是true
 // 那么normalizationType應(yīng)該設(shè)置為常量ALWAYS_NORMALIZE的值
 if (isTrue(alwaysNormalize)) {
 normalizationType = ALWAYS_NORMALIZE
 }
 // 調(diào)用_createElement創(chuàng)建虛擬節(jié)點
 return _createElement(context, tag, data, children, normalizationType)
}

export function _createElement (
 context: Component,
 tag?: string | Class<Component> | Function | Object,
 data?: VNodeData,
 children?: any,
 normalizationType?: number
): VNode {

 /**
 * 如果存在data.__ob__,說明data是被Observer觀察的數(shù)據(jù)
 * 不能用作虛擬節(jié)點的data
 * 需要拋出警告,并返回一個空節(jié)點
 *
 * 被監(jiān)控的data不能被用作vnode渲染的數(shù)據(jù)的原因是:
 * data在vnode渲染過程中可能會被改變,這樣會觸發(fā)監(jiān)控,導致不符合預(yù)期的操作
 */
 if (isDef(data) && isDef((data: any).__ob__)) {
 process.env.NODE_ENV !== &#39;production&#39; && warn(
  `Avoid using observed data object as vnode data: ${JSON.stringify(data)}\n` +
  &#39;Always create fresh vnode data objects in each render!&#39;,
  context
 )
 return createEmptyVNode()
 }
 // object syntax in v-bind
 if (isDef(data) && isDef(data.is)) {
 tag = data.is
 }
 if (!tag) {
 // 當組件的is屬性被設(shè)置為一個falsy的值
 // Vue將不會知道要把這個組件渲染成什么
 // 所以渲染一個空節(jié)點
 // in case of component :is set to falsy value
 return createEmptyVNode()
 }
 // key為非原始值警告
 // warn against non-primitive key
 if (process.env.NODE_ENV !== &#39;production&#39; &&
 isDef(data) && isDef(data.key) && !isPrimitive(data.key)
 ) {
 warn(
  &#39;Avoid using non-primitive value as key, &#39; +
  &#39;use string/number value instead.&#39;,
  context
 )
 }
 // 作用域插槽
 // support single function children as default scoped slot
 if (Array.isArray(children) &&
 typeof children[0] === &#39;function&#39;
 ) {
 data = data || {}
 data.scopedSlots = { default: children[0] }
 children.length = 0
 }
 // 根據(jù)normalizationType的值,選擇不同的處理方法
 if (normalizationType === ALWAYS_NORMALIZE) {
 children = normalizeChildren(children)
 } else if (normalizationType === SIMPLE_NORMALIZE) {
 children = simpleNormalizeChildren(children)
 }
 let vnode, ns
 // 如果標簽名是字符串類型
 if (typeof tag === &#39;string&#39;) {
 let Ctor
 // 獲取標簽的命名空間
 ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag)
 // 如果是保留標簽
 if (config.isReservedTag(tag)) {
  // platform built-in elements
  // 就創(chuàng)建這樣一個vnode
  vnode = new VNode(
  config.parsePlatformTagName(tag), data, children,
  undefined, undefined, context
  )
  // 如果不是保留字標簽,嘗試從vm的components上查找是否有這個標簽的定義
 } else if (isDef(Ctor = resolveAsset(context.$options, &#39;components&#39;, tag))) {
  // component
  // 如果找到,就創(chuàng)建虛擬組件節(jié)點
  vnode = createComponent(Ctor, data, context, children, tag)
 } else {
  // unknown or unlisted namespaced elements
  // check at runtime because it may get assigned a namespace when its
  // parent normalizes children
  // 兜底方案,創(chuàng)建一個正常的vnode
  vnode = new VNode(
  tag, data, children,
  undefined, undefined, context
  )
 }
 } else {
 // 當tag不是字符串的時候,我們認為tag是組件的構(gòu)造類
 // 所以直接創(chuàng)建
 // direct component options / constructor
 vnode = createComponent(tag, data, context, children)
 }
 if (isDef(vnode)) {
 // 應(yīng)用命名空間
 if (ns) applyNS(vnode, ns)
 return vnode
 } else {
 // 返回一個空節(jié)點
 return createEmptyVNode()
 }
}
function applyNS (vnode, ns, force) {
 vnode.ns = ns
 if (vnode.tag === &#39;foreignObject&#39;) {
 // use default namespace inside foreignObject
 ns = undefined
 force = true
 }
 if (isDef(vnode.children)) {
 for (let i = 0, l = vnode.children.length; i < l; i++) {
  const child = vnode.children[i]
  if (isDef(child.tag) && (isUndef(child.ns) || isTrue(force))) {
  applyNS(child, ns, force)
  }
 }
 }
}

4. Patch principle

The patch function is defined in src/core/vdom/patch.js. The patch logic is relatively simple, so no code is required.

The patch function receives 6 parameters:

  • oldVnode: old virtual node or old real dom node

  • vnode: new virtual node

  • hydrating: Whether to mix it with real dom

  • removeOnly: special flag, used for

  • parentElm: parent node

  • refElm: The new node will be inserted before refElm

The logic of patch is:

if vnode does not exist but oldVnode exists, indicating that the intention is to destroy the old node, then call invokeDestroyHook(oldVnode) to destroy it

If oldVnode does not exist but vnode exists, indicating that the intention is to create a new node, then call createElm to create a new node

else When vnode and oldVnode both exist

If oldVnode and vnode are the same node, call patchVnode to patch

When vnode and oldVnode When they are not the same node, if oldVnode is a real dom node or hydrating is set to true, you need to use the hydrate function to map the virtual dom and the real dom, then set oldVnode to the corresponding virtual dom, find the parent node of oldVnode.elm, according to vnode creates a real dom node and inserts it into the parent node at the position of oldVnode.elm

The logic of patchVnode is:

1. If oldVnode is completely consistent with vnode, Then you don’t need to do anything

2. If oldVnode and vnode are both static nodes and have the same key, and when vnode is a clone node or a node controlled by the v-once command, you only need to change oldVnode. Both elm and oldVnode.child are copied to vnode, and no other operations are required

3. Otherwise, if vnode is not a text node or comment node

  • If oldVnode and vnode has child nodes, and the child nodes of the two parties are not completely consistent, execute updateChildren

  • If only oldVnode has child nodes, then delete these nodes

  • If only vnode has child nodes, then create these child nodes

  • If neither oldVnode nor vnode has child nodes, but oldVnode is a text node or comment node, Just set the text of vnode.elm to the empty string

4.如果vnode是文本節(jié)點或注釋節(jié)點,但是vnode.text != oldVnode.text時,只需要更新vnode.elm的文本內(nèi)容就可以

代碼如下:

 function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {
 // 如果新舊節(jié)點一致,什么都不做
 if (oldVnode === vnode) {
  return
 }
 // 讓vnode.el引用到現(xiàn)在的真實dom,當el修改時,vnode.el會同步變化
 const elm = vnode.elm = oldVnode.elm
 // 異步占位符
 if (isTrue(oldVnode.isAsyncPlaceholder)) {
  if (isDef(vnode.asyncFactory.resolved)) {
  hydrate(oldVnode.elm, vnode, insertedVnodeQueue)
  } else {
  vnode.isAsyncPlaceholder = true
  }
  return
 }
 // reuse element for static trees.
 // note we only do this if the vnode is cloned -
 // if the new node is not cloned it means the render functions have been
 // reset by the hot-reload-api and we need to do a proper re-render.
 // 如果新舊都是靜態(tài)節(jié)點,并且具有相同的key
 // 當vnode是克隆節(jié)點或是v-once指令控制的節(jié)點時,只需要把oldVnode.elm和oldVnode.child都復制到vnode上
 // 也不用再有其他操作
 if (isTrue(vnode.isStatic) &&
  isTrue(oldVnode.isStatic) &&
  vnode.key === oldVnode.key &&
  (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))
 ) {
  vnode.componentInstance = oldVnode.componentInstance
  return
 }
 let i
 const data = vnode.data
 if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {
  i(oldVnode, vnode)
 }
 const oldCh = oldVnode.children
 const ch = vnode.children
 if (isDef(data) && isPatchable(vnode)) {
  for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)
  if (isDef(i = data.hook) && isDef(i = i.update)) i(oldVnode, vnode)
 }
 // 如果vnode不是文本節(jié)點或者注釋節(jié)點
 if (isUndef(vnode.text)) {
  // 并且都有子節(jié)點
  if (isDef(oldCh) && isDef(ch)) {
  // 并且子節(jié)點不完全一致,則調(diào)用updateChildren
  if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
  // 如果只有新的vnode有子節(jié)點
  } else if (isDef(ch)) {
  if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, &#39;&#39;)
  // elm已經(jīng)引用了老的dom節(jié)點,在老的dom節(jié)點上添加子節(jié)點
  addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
  // 如果新vnode沒有子節(jié)點,而vnode有子節(jié)點,直接刪除老的oldCh
  } else if (isDef(oldCh)) {
  removeVnodes(elm, oldCh, 0, oldCh.length - 1)
  // 如果老節(jié)點是文本節(jié)點
  } else if (isDef(oldVnode.text)) {
  nodeOps.setTextContent(elm, &#39;&#39;)
  }
  // 如果新vnode和老vnode是文本節(jié)點或注釋節(jié)點
  // 但是vnode.text != oldVnode.text時,只需要更新vnode.elm的文本內(nèi)容就可以
 } else if (oldVnode.text !== vnode.text) {
  nodeOps.setTextContent(elm, vnode.text)
 }
 if (isDef(data)) {
  if (isDef(i = data.hook) && isDef(i = i.postpatch)) i(oldVnode, vnode)
 }
 }

5.updataChildren原理

updateChildren的邏輯是:

分別獲取oldVnode和vnode的firstChild、lastChild,賦值給oldStartVnode、oldEndVnode、newStartVnode、newEndVnode

如果oldStartVnode和newStartVnode是同一節(jié)點,調(diào)用patchVnode進行patch,然后將oldStartVnode和newStartVnode都設(shè)置為下一個子節(jié)點,

如果oldEndVnode和newEndVnode是同一節(jié)點,調(diào)用patchVnode進行patch,然后將oldEndVnode和newEndVnode都設(shè)置為上一個子節(jié)點,重復上述流程

如果oldStartVnode和newEndVnode是同一節(jié)點,調(diào)用patchVnode進行patch,如果removeOnly是false,那么可以把oldStartVnode.elm移動到oldEndVnode.elm之后,然后把oldStartVnode設(shè)置為下一個節(jié)點,newEndVnode設(shè)置為上一個節(jié)點,重復上述流程

如果newStartVnode和oldEndVnode是同一節(jié)點,調(diào)用patchVnode進行patch,如果removeOnly是false,那么可以把oldEndVnode.elm移動到oldStartVnode.elm之前,然后把newStartVnode設(shè)置為下一個節(jié)點,oldEndVnode設(shè)置為上一個節(jié)點,重復上述流程

如果以上都不匹配,就嘗試在oldChildren中尋找跟newStartVnode具有相同key的節(jié)點,如果找不到相同key的節(jié)點,說明newStartVnode是一個新節(jié)點,就創(chuàng)建一個,然后把newStartVnode設(shè)置為下一個節(jié)點

如果上一步找到了跟newStartVnode相同key的節(jié)點,那么通過其他屬性的比較來判斷這2個節(jié)點是否是同一個節(jié)點,如果是,就調(diào)用patchVnode進行patch,如果removeOnly是false,就把newStartVnode.elm插入到oldStartVnode.elm之前,把newStartVnode設(shè)置為下一個節(jié)點,重復上述流程

如果在oldChildren中沒有尋找到newStartVnode的同一節(jié)點,那就創(chuàng)建一個新節(jié)點,把newStartVnode設(shè)置為下一個節(jié)點,重復上述流程

如果oldStartVnode跟oldEndVnode重合了,并且newStartVnode跟newEndVnode也重合了,這個循環(huán)就結(jié)束了

具體代碼如下:

function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {
 let oldStartIdx = 0 // 舊頭索引
 let newStartIdx = 0 // 新頭索引
 let oldEndIdx = oldCh.length - 1 // 舊尾索引
 let newEndIdx = newCh.length - 1 // 新尾索引
 let oldStartVnode = oldCh[0] // oldVnode的第一個child
 let oldEndVnode = oldCh[oldEndIdx] // oldVnode的最后一個child
 let newStartVnode = newCh[0] // newVnode的第一個child
 let newEndVnode = newCh[newEndIdx] // newVnode的最后一個child
 let oldKeyToIdx, idxInOld, vnodeToMove, refElm
 // removeOnly is a special flag used only by <transition-group>
 // to ensure removed elements stay in correct relative positions
 // during leaving transitions
 const canMove = !removeOnly
 // 如果oldStartVnode和oldEndVnode重合,并且新的也都重合了,證明diff完了,循環(huán)結(jié)束
 while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
  // 如果oldVnode的第一個child不存在
  if (isUndef(oldStartVnode)) {
  // oldStart索引右移
  oldStartVnode = oldCh[++oldStartIdx] // Vnode has been moved left
  // 如果oldVnode的最后一個child不存在
  } else if (isUndef(oldEndVnode)) {
  // oldEnd索引左移
  oldEndVnode = oldCh[--oldEndIdx]
  // oldStartVnode和newStartVnode是同一個節(jié)點
  } else if (sameVnode(oldStartVnode, newStartVnode)) {
  // patch oldStartVnode和newStartVnode, 索引左移,繼續(xù)循環(huán)
  patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue)
  oldStartVnode = oldCh[++oldStartIdx]
  newStartVnode = newCh[++newStartIdx]
  // oldEndVnode和newEndVnode是同一個節(jié)點
  } else if (sameVnode(oldEndVnode, newEndVnode)) {
  // patch oldEndVnode和newEndVnode,索引右移,繼續(xù)循環(huán)
  patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue)
  oldEndVnode = oldCh[--oldEndIdx]
  newEndVnode = newCh[--newEndIdx]
  // oldStartVnode和newEndVnode是同一個節(jié)點
  } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
  // patch oldStartVnode和newEndVnode
  patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue)
  // 如果removeOnly是false,則將oldStartVnode.eml移動到oldEndVnode.elm之后
  canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm))
  // oldStart索引右移,newEnd索引左移
  oldStartVnode = oldCh[++oldStartIdx]
  newEndVnode = newCh[--newEndIdx]
  // 如果oldEndVnode和newStartVnode是同一個節(jié)點
  } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
  // patch oldEndVnode和newStartVnode
  patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue)
  // 如果removeOnly是false,則將oldEndVnode.elm移動到oldStartVnode.elm之前
  canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm)
  // oldEnd索引左移,newStart索引右移
  oldEndVnode = oldCh[--oldEndIdx]
  newStartVnode = newCh[++newStartIdx]
  // 如果都不匹配
  } else {
  if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
  // 嘗試在oldChildren中尋找和newStartVnode的具有相同的key的Vnode
  idxInOld = isDef(newStartVnode.key)
   ? oldKeyToIdx[newStartVnode.key]
   : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
  // 如果未找到,說明newStartVnode是一個新的節(jié)點
  if (isUndef(idxInOld)) { // New element
   // 創(chuàng)建一個新Vnode
   createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
  // 如果找到了和newStartVnodej具有相同的key的Vnode,叫vnodeToMove
  } else {
   vnodeToMove = oldCh[idxInOld]
   /* istanbul ignore if */
   if (process.env.NODE_ENV !== &#39;production&#39; && !vnodeToMove) {
   warn(
    &#39;It seems there are duplicate keys that is causing an update error. &#39; +
    &#39;Make sure each v-for item has a unique key.&#39;
   )
   }
   // 比較兩個具有相同的key的新節(jié)點是否是同一個節(jié)點
   //不設(shè)key,newCh和oldCh只會進行頭尾兩端的相互比較,設(shè)key后,除了頭尾兩端的比較外,還會從用key生成的對象oldKeyToIdx中查找匹配的節(jié)點,所以為節(jié)點設(shè)置key可以更高效的利用dom。
   if (sameVnode(vnodeToMove, newStartVnode)) {
   // patch vnodeToMove和newStartVnode
   patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue)
   // 清除
   oldCh[idxInOld] = undefined
   // 如果removeOnly是false,則將找到的和newStartVnodej具有相同的key的Vnode,叫vnodeToMove.elm
   // 移動到oldStartVnode.elm之前
   canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm)
   // 如果key相同,但是節(jié)點不相同,則創(chuàng)建一個新的節(jié)點
   } else {
   // same key but different element. treat as new element
   createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
   }
  }
  // 右移
  newStartVnode = newCh[++newStartIdx]
  }
 }

6.具體的Diff分析

不設(shè)key,newCh和oldCh只會進行頭尾兩端的相互比較,設(shè)key后,除了頭尾兩端的比較外,還會從用key生成的對象oldKeyToIdx中查找匹配的節(jié)點,所以為節(jié)點設(shè)置key可以更高效的利用dom。

diff的遍歷過程中,只要是對dom進行的操作都調(diào)用api.insertBefore,api.insertBefore只是原生insertBefore的簡單封裝。

比較分為兩種,一種是有vnode.key的,一種是沒有的。但這兩種比較對真實dom的操作是一致的。

對于與sameVnode(oldStartVnode, newStartVnode)和sameVnode(oldEndVnode,newEndVnode)為true的情況,不需要對dom進行移動。

總結(jié)遍歷過程,有3種dom操作:上述圖中都有

1.當oldStartVnode,newEndVnode值得比較,說明oldStartVnode.el跑到oldEndVnode.el的后邊了。

2.當oldEndVnode,newStartVnode值得比較,oldEndVnode.el跑到了oldStartVnode.el的前邊,準確的說應(yīng)該是oldEndVnode.el需要移動到oldStartVnode.el的前邊”。

3.newCh中的節(jié)點oldCh里沒有, 將新節(jié)點插入到oldStartVnode.el的前邊

在結(jié)束時,分為兩種情況:

1.oldStartIdx > oldEndIdx,可以認為oldCh先遍歷完。當然也有可能newCh此時也正好完成了遍歷,統(tǒng)一都歸為此類。此時newStartIdx和newEndIdx之間的vnode是新增的,調(diào)用addVnodes,把他們?nèi)坎暹Mbefore的后邊,before很多時候是為null的。addVnodes調(diào)用的是insertBefore操作dom節(jié)點,我們看看insertBefore的文檔:parentElement.insertBefore(newElement, referenceElement)

如果referenceElement為null則newElement將被插入到子節(jié)點的末尾。如果newElement已經(jīng)在DOM樹中,newElement首先會從DOM樹中移除。所以before為null,newElement將被插入到子節(jié)點的末尾。

2.newStartIdx > newEndIdx, it can be considered that newCh is traversed first. At this time, the vnode between oldStartIdx and oldEndIdx no longer exists in the new child node. Call removeVnodes to delete them from the dom.

The above is what I compiled for everyone. I hope it will be helpful to everyone in the future.

Related articles:

Chrome Firefox comes with debugging tools (detailed tutorial)

About how Vue.js implements infinite scrolling loading

How to implement table filtering using Angular

How to implement a calculator using JavaScript

The above is the detailed content of How to use the Diff algorithm in Vue 2.5. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to add functions to buttons for vue How to add functions to buttons for vue Apr 08, 2025 am 08:51 AM

You can add a function to the Vue button by binding the button in the HTML template to a method. Define the method and write function logic in the Vue instance.

React vs. Vue: Which Framework Does Netflix Use? React vs. Vue: Which Framework Does Netflix Use? Apr 14, 2025 am 12:19 AM

Netflixusesacustomframeworkcalled"Gibbon"builtonReact,notReactorVuedirectly.1)TeamExperience:Choosebasedonfamiliarity.2)ProjectComplexity:Vueforsimplerprojects,Reactforcomplexones.3)CustomizationNeeds:Reactoffersmoreflexibility.4)Ecosystema

Netflix's Frontend: Examples and Applications of React (or Vue) Netflix's Frontend: Examples and Applications of React (or Vue) Apr 16, 2025 am 12:08 AM

Netflix uses React as its front-end framework. 1) React's componentized development model and strong ecosystem are the main reasons why Netflix chose it. 2) Through componentization, Netflix splits complex interfaces into manageable chunks such as video players, recommendation lists and user comments. 3) React's virtual DOM and component life cycle optimizes rendering efficiency and user interaction management.

How to jump to the div of vue How to jump to the div of vue Apr 08, 2025 am 09:18 AM

There are two ways to jump div elements in Vue: use Vue Router and add router-link component. Add the @click event listener and call this.$router.push() method to jump.

React, Vue, and the Future of Netflix's Frontend React, Vue, and the Future of Netflix's Frontend Apr 12, 2025 am 12:12 AM

Netflix mainly uses React as the front-end framework, supplemented by Vue for specific functions. 1) React's componentization and virtual DOM improve the performance and development efficiency of Netflix applications. 2) Vue is used in Netflix's internal tools and small projects, and its flexibility and ease of use are key.

How to jump a tag to vue How to jump a tag to vue Apr 08, 2025 am 09:24 AM

The methods to implement the jump of a tag in Vue include: using the a tag in the HTML template to specify the href attribute. Use the router-link component of Vue routing. Use this.$router.push() method in JavaScript. Parameters can be passed through the query parameter and routes are configured in the router options for dynamic jumps.

How to implement component jump for vue How to implement component jump for vue Apr 08, 2025 am 09:21 AM

There are the following methods to implement component jump in Vue: use router-link and &lt;router-view&gt; components to perform hyperlink jump, and specify the :to attribute as the target path. Use the &lt;router-view&gt; component directly to display the currently routed rendered components. Use the router.push() and router.replace() methods for programmatic navigation. The former saves history and the latter replaces the current route without leaving records.

How to develop a complete Python Web application? How to develop a complete Python Web application? May 23, 2025 pm 10:39 PM

To develop a complete Python Web application, follow these steps: 1. Choose the appropriate framework, such as Django or Flask. 2. Integrate databases and use ORMs such as SQLAlchemy. 3. Design the front-end and use Vue or React. 4. Perform the test, use pytest or unittest. 5. Deploy applications, use Docker and platforms such as Heroku or AWS. Through these steps, powerful and efficient web applications can be built.

See all articles