小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
一、key的作用和原理
源码地址:src/core/vdom/patch.js
二、patchVnode方法的具体实现过程
源码地址:src/core/vdom/patch.js
- vnode与oldNode完全一样?是,退出程序。
- vnode与oldNode都为静态节点? 是,退出程序。
- vnode有text属性? 是,vnode与oldNode的文本不同? 是,用vnode的文本替换真实DOM中内容。
- vnode和oldNode都有子节点?是,子节点不同?是,调用updateChildren方法更新子节点。
- 只有vnode有子节点? 是,oldNode有文本?是,清空真实DOM中的文本,把vnode子节点添加到真实DOM中;否,把vnode子节点添加到真实DOM中。
- 只有oldNode有子节点?是,清空真实DOM中的子节点。
- 只有oldNode有文本?是,清空真实DOM中的文本。
function patchVnode (
oldVnode,
vnode,
insertedVnodeQueue,
ownerArray,
index,
removeOnly
) {
// oldVnode和vnode完全一样则退出程序
if (oldVnode === vnode) {
return
}
if (isDef(vnode.elm) && isDef(ownerArray)) {
// clone reused vnode
vnode = ownerArray[index] = cloneVNode(vnode)
}
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.
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)
}
if (isUndef(vnode.text)) {
if (isDef(oldCh) && isDef(ch)) {
if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
} else if (isDef(ch)) {
if (process.env.NODE_ENV !== 'production') {
checkDuplicateKeys(ch)
}
if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, '')
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
} else if (isDef(oldCh)) {
removeVnodes(oldCh, 0, oldCh.length - 1)
} else if (isDef(oldVnode.text)) {
nodeOps.setTextContent(elm, '')
}
} 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)
}
}
三、vue组件化
- 定义:组件是独立和可复用的代码组织单元。组件系统是Vue的核心特性之一,它使开发者使用小型、独立和可复用的组件构建大型应用。
- 优点:组件化开发能大幅提高应用开发效率、测试性、复用性等。
- 分类:组件按使用分成页面组件、通用、业务组件。
- vue组件是基于配置的,我们通常写的组件并非真正的组件,而是组件配置,框架后续会生成其构造函数。如何生成呢?基于VueComponent这个类,扩展自Vue类,在扩展过程中会继承Vue中的已经有的选项。
- 常用的组件化技术有:属性prop,自定义事件,插槽等。它们主要用于组件通信、扩展等。
- mountComponent方法中每个组件有一个watcher与之对应。当组件发生变化时,只会调用该组件的渲染函数和更新函数。所以合理分割组件,有助于提升应用性能。
- 组件应该是高内聚、低耦合的。
- 遵循单向数据流原则。