Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vue] 你知道vue中key的原理吗?说说你对它的理解 #545

Open
haizhilin2013 opened this issue Jul 2, 2019 · 13 comments
Open
Labels
vue vue

Comments

@haizhilin2013
Copy link
Collaborator

[vue] 你知道vue中key的原理吗?说说你对它的理解

@haizhilin2013 haizhilin2013 added the vue vue label Jul 2, 2019
@Aaron0525
Copy link

作用的话,便于diff算法的更新,key的唯一性,能让算法更快的找到需要更新的dom,需要注意的是,key要唯一,不然会出现很隐蔽性的更新问题。

@carrykingdow
Copy link

在绑定key的时候,最好是一个唯一的值,如item.id 而不能是简单的index

@Linkontoask
Copy link

@Aaron0525 请问 隐蔽性的更新问题 是什么意思?我的理解就是如果不使用唯一key在有状态组件中会出现渲染错误,如果使用index也可能会出现渲染错位的情况,因为diff是同级比对

@censek
Copy link

censek commented Oct 11, 2019

@RongerGitHub
Copy link

Key 不是用在循环中吗

@RussellSu
Copy link

便于Diff时更高效的进行节点查询对比。
有key时,通过createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)生成的key与索引映射关系,直接通过新子节点的key查询是否存在于旧子节点序列中。
无key时,必须遍历旧子节点序列,依次与新子节点对比判断是否为新增节点。
参考vue/src/core/vdom/patch.jsupdateChildren方法

@szjSmiling
Copy link

key的作用主要是为了高效的更新虚拟DOM;
如果没有唯一的key, 数据更新时, 相同节点更新前后无法准确一一对应起来,会导致更新效率降低;
当页面的数据发生变化时,Diff算法只会比较同一层级的节点:

  1. 如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点;
  2. 如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新;

@qq-radio
Copy link

为啥没有人说key最重要的是防止去复用dom啊

@crush2020
Copy link

key是具有唯一性的,能让算法更快的找到需要跟新的DOM,而不是一个个的去替换。还有一个就是防止复用。

@anyanyan07
Copy link

使用key不一定就高效,key的作用是维护状态和触发过渡效果

@flashyy
Copy link

flashyy commented Feb 23, 2022

#262 (comment) #262

@szjSmiling
Copy link

szjSmiling commented Feb 23, 2022 via email

@Tracymcgrady946
Copy link

Vue 中使用的算法是基于"Virtual DOM" (虚拟 DOM) 的 diff 算法,用于比较和更新两个虚拟 DOM 树之间的差异。

虚拟 DOM 是一个轻量级的 JavaScript 对象树,它是对实际 DOM 的抽象表示。当 Vue 组件发生变化时,Vue 会创建一个新的虚拟 DOM 树,并通过 diff 算法将新旧虚拟 DOM 树进行比较,找出两者之间的差异。

下面是 diff 算法的详细步骤:

创建新的虚拟 DOM 树:当组件状态发生变化时,Vue 会重新渲染组件,并生成一个新的虚拟 DOM 树。

对比新旧虚拟 DOM 树:Vue 会逐个比较新旧虚拟 DOM 树的节点,从根节点开始递归地进行比较。

查找差异:在比较过程中,Vue 会找出两个节点之间的差异。它会比较节点的标签类型、属性、子节点等信息,以确定节点是否相同或不同。

更新差异:一旦找到差异,Vue 会根据差异类型采取相应的操作。这可能涉及插入、移动、更新或删除实际 DOM 节点。

插入:当新的节点在新的虚拟 DOM 树中出现但在旧的虚拟 DOM 树中不存在时,Vue 会在相应位置插入实际 DOM 节点。
移动:当节点在新的虚拟 DOM 树和旧的虚拟 DOM 树中都存在,但位置发生变化时,Vue 会移动实际 DOM 节点到新的位置,而不是重新创建。
更新:当节点在新的虚拟 DOM 树和旧的虚拟 DOM 树中都存在,并且属性发生变化时,Vue 会更新相应的实际 DOM 节点的属性。
删除:当节点在旧的虚拟 DOM 树中存在但在新的虚拟 DOM 树中不存在时,Vue 会删除相应的实际 DOM 节点。
递归处理子节点:对于有子节点的节点,Vue 会递归地进行上述比较和更新步骤,以确保整个虚拟 DOM 树能够正确更新。

通过使用 diff 算法,Vue 可以避免直接操作实际 DOM,并且只对需要更新的部分进行操作,从而提高了性能和渲染效率。通过比较虚拟 DOM 树的差异,Vue 可以最小化对实际 DOM 的修改,减少了不必要的重绘和回流,提升了应用的性能和用户体验。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
vue vue
Projects
None yet
Development

No branches or pull requests