vue面试题(二)

140 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

一、key的作用和原理

源码地址:src/core/vdom/patch.js image.png image.png

二、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与之对应。当组件发生变化时,只会调用该组件的渲染函数和更新函数。所以合理分割组件,有助于提升应用性能。
  • 组件应该是高内聚、低耦合的。
  • 遵循单向数据流原则。