Vue源码学习第一天

1.vue使用了5个函数来对vue进行扩展

Vue源码学习第一天_第1张图片
image.png

1. initMixin

 vm._uid = uid++

首先给vue实例设置了唯一标识符uid,每次实例化都会递增

// a flag to avoid this being observed
    vm._isVue = true

给vm对象设置标志,避免被监听

if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options)
    } else {
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }

合并options,如果是组件则进入第一个分支,页面进入第二个分支,这里调用mergeOptions方法实现options的合并,该方法有三个参数,第一个是resolveConstructorOptions方法返回值(vm.constructor的options),第二是new Vue时传入的值(自定义的options),第三个是vue对象本身。mergeOptions就是通过一系列的合并策略,将Vue的构造函数以及自定义的options进行合并。

1.1 mergeOptions(位于core/util/options.js)

export function mergeOptions(
  parent: Object,
  child: Object,
  vm?: Component
): Object {
  if (process.env.NODE_ENV !== "production") {
    // 1.校验组件名称的合法性
    checkComponents(child);
  }

  //2.如果传入的是类型是function,则取其options
  if (typeof child === "function") {
    child = child.options;
  }

  //3.格式化props,inject,directives
 /*
    props:[],
    props:{
      info:String,
      default:''
    }
  */
  normalizeProps(child, vm);
  normalizeInject(child, vm);
  normalizeDirectives(child);

  // Apply extends and mixins on the child options,
  // but only if it is a raw options object that isn't
  // the result of another mergeOptions call.
  // Only merged options has the _base property.

  //在子选项上应用扩展和混合,
  //空对象的时候不调用
  //这是另一个合并选项调用的结果。
  //只合并具有_base属性的选项
  if (!child._base) {
    if (child.extends) {
      parent = mergeOptions(parent, child.extends, vm);
    }
    if (child.mixins) {
      for (let i = 0, l = child.mixins.length; i < l; i++) {
        parent = mergeOptions(parent, child.mixins[i], vm);
      }
    }
  }

  const options = {};
  let key;
  for (key in parent) {
    mergeField(key);
  }
  for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key);
    }
  }
  function mergeField(key) {
    const strat = strats[key] || defaultStrat;
    options[key] = strat(parent[key], child[key], vm, key);
  }
  return options;
}

该方法有三个入参,parent为resolveConstructorOptions返回的值(Vue的构造函数的options),child是我们new Vue时传入的数组对象(自定义的options),vm是Vue对象本身。方便起见,下面我们就用parent和child来称呼这两种options。
(1)合法性校验

 if (process.env.NODE_ENV !== "production") {
    // 1.校验组件名称的合法性
    checkComponents(child);
  }

规范组件的命名

(2)如果传入的是类型是function,则取其options

  //2.如果传入的是类型是function,则取其options
  if (typeof child === "function") {
    child = child.options;
  }

(3)校验props,Inject,directives的值

  normalizeProps(child, vm);
  normalizeInject(child, vm);
  normalizeDirectives(child);

(4)extends与minxins处理

  //在子选项上应用扩展和混合,
  //空对象的时候不调用
  //这是另一个合并选项调用的结果。
  //只合并具有_base属性的选项
  if (!child._base) {
    if (child.extends) {
      parent = mergeOptions(parent, child.extends, vm);
    }
    if (child.mixins) {
      for (let i = 0, l = child.mixins.length; i < l; i++) {
        parent = mergeOptions(parent, child.mixins[i], vm);
      }
    }
  }

判断是否有extends与minxins属性,使用mergeOptions进行递归调用

(5)合并策略

  const options = {};
  let key;
  for (key in parent) {
    mergeField(key);
  }
  for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key);
    }
  }
  function mergeField(key) {
    const strat = strats[key] || defaultStrat;
    options[key] = strat(parent[key], child[key], vm, key);
  }

对每种属性(key)有不同的合并策略strat[key],我们以钩子函数的合并为例。定义钩子函数的合并策略的处理方法为mergeHook

export const LIFECYCLE_HOOKS = [
  'beforeCreate',
  'created',
  'beforeMount',
  'mounted',
  'beforeUpdate',
  'updated',
  'beforeDestroy',
  'destroyed',
  'activated',
  'deactivated',
  'errorCaptured',
  'serverPrefetch'
]
function mergeHook(
  parentVal: ?Array,
  childVal: ?Function | ?Array
): ?Array {
  const res = childVal
    ? parentVal
      ? parentVal.concat(childVal)
      : Array.isArray(childVal)
      ? childVal
      : [childVal]
    : parentVal;
  return res ? dedupeHooks(res) : res;
}

1.2 resolveConstructorOptions

export function resolveConstructorOptions (Ctor: Class) {
  let options = Ctor.options
  if (Ctor.super) {
    const superOptions = resolveConstructorOptions(Ctor.super)
    const cachedSuperOptions = Ctor.superOptions
    if (superOptions !== cachedSuperOptions) {
      // super option changed,
      // need to resolve new options.
      Ctor.superOptions = superOptions
      // check if there are any late-modified/attached options (#4976)
      const modifiedOptions = resolveModifiedOptions(Ctor)
      // update base extend options
      if (modifiedOptions) {
        extend(Ctor.extendOptions, modifiedOptions)
      }
      options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions)
      if (options.name) {
        options.components[options.name] = Ctor
      }
    }
  }
  return options
}

该方法的接受的参数是vm.constructor,即构造函数Vue,返回构造函数的options

你可能感兴趣的:(Vue源码学习第一天)