Vue2指令,全局API部分原理(简易) - 功能(更新中...)

458 阅读1分钟

前言

  • 针对一些常见的
  • vue2源码

Vue.use原理

主要目的是将当前Vue版本引入到插件中

/**
 * @description 将argement从1还是收集 返回一个数组
 */
export function toArray (list: any, start?: number): Array<any> {
  start = start || 0
  let i = list.length - start
  const ret: Array<any> = new Array(i)
  while (i--) {
    ret[i] = list[i + start]
  }
  return ret
}

import { toArray } from '../util/index'

export function initUse (Vue: GlobalAPI) {
  Vue.use = function (plugin: Function | Object) {
  	// 第一行 看收集插件是否已有 如有返回
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    if (installedPlugins.indexOf(plugin) > -1) {
      return this
    }

    // 看这里
    const args = toArray(arguments, 1)
    
    // 当前this指向Vue 收集到新的数组
    args.unshift(this)
    
    if (typeof plugin.install === 'function') {
      // 调用插件 并将包含当前版本的Vue数组传给插件
      // plugin: Object 所以将当前插件里的this指向自己
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {
      plugin.apply(null, args)
    }
    
    // 收集插件 排除重复 看上面
    installedPlugins.push(plugin)
    return this
  }
}

v-if和v-for原理

// v-if源码
function genIfConditions (
  conditions: ASTIfConditions,
  state: CodegenState,
  altGen?: Function,
  altEmpty?: string
): string {
  if (!conditions.length) {
    return altEmpty || '_e()'
  }

  const condition = conditions.shift()
  if (condition.exp) { // 如果有表达式
    return `(${condition.exp})?${ // 将表达式作为条件继续
      genTernaryExp(condition.block)
    }:${
      genIfConditions(conditions, state, altGen, altEmpty)
    }`
  } else { // 没有表达式直接生成元素
    return `${genTernaryExp(condition.block)}`
  }

  // v-if with v-once should generate code like (a)?_m(0):_m(1)
  function genTernaryExp (el) {
    return altGen
      ? altGen(el, state)
      : el.once
        ? genOnce(el, state)
        : genElement(el, state)
  }
}

// v-show
{
	bind (el: any, { value }: VNodeDirective, vnode: VNodeWithData) {
    vnode = locateNode(vnode)
    const transition = vnode.data && vnode.data.transition
    const originalDisplay = el.__vOriginalDisplay =
      el.style.display === 'none' ? '' : el.style.display
    if (value && transition) {
      vnode.data.show = true
      enter(vnode, () => {
        el.style.display = originalDisplay
      })
    } else {
      el.style.display = value ? originalDisplay : 'none'
    }
  },
}