zoukankan      html  css  js  c++  java
  • vue源码解析之选项合并(二)

    选项 data 的合并策略

    我们跳过mergeData 以及 mergeDataOrFn,我们暂且不关注这两个函数的作用。暂且跳过继续看下面的代码:

    strats.data = function (
      parentVal: any,
      childVal: any,
      vm?: Component
    ): ?Function {
      if (!vm) {
        if (childVal && typeof childVal !== 'function') {
          process.env.NODE_ENV !== 'production' && warn(
            'The "data" option should be a function ' +
            'that returns a per-instance value in component ' +
            'definitions.',
            vm
          )
    
          return parentVal
        }
        return mergeDataOrFn(parentVal, childVal)
      }
    
      return mergeDataOrFn(parentVal, childVal, vm)
    }

    在strats策略对象上面添加了一个data策略函数,进行选项data的策略合并

    if (!vm) {}如同上一篇文章介绍一样 用来判断是否是子组件选项,
    如果是子组件选项
    return mergeDataOrFn(parentVal, childVal)
    如果不是 return mergeDataOrFn(parentVal, childVal, vm)
    再来看看if判断里面的内容:
    if (childVal && typeof childVal !== 'function') {}
    

      判断是否又子组件的data,并且检测是否是一个function,如果不是函数则会警告,并且返回parentVal

            如果childval是函数 则会返回mergeDataOrFn(parentVal, childVal) 执行结果

           后面就不用说了, 如果又vm 就执行mergeDataOrFn(parentVal, childVal, vm)

    接下来我们看看一直调用的mergeDataOrFn函数是什么:

    /**
     * Data
     */
    export function mergeDataOrFn (
      parentVal: any,
      childVal: any,
      vm?: Component
    ): ?Function {
      if (!vm) {
        // in a Vue.extend merge, both should be functions
        if (!childVal) {
          return parentVal
        }
        if (!parentVal) {
          return childVal
        }
        // when parentVal & childVal are both present,
        // we need to return a function that returns the
        // merged result of both functions... no need to
        // check if parentVal is a function here because
        // it has to be a function to pass previous merges.
        return function mergedDataFn () {
          return mergeData(
            typeof childVal === 'function' ? childVal.call(this, this) : childVal,
            typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal
          )
        }
      } else {
        return function mergedInstanceDataFn () {
          // instance merge
          const instanceData = typeof childVal === 'function'
            ? childVal.call(vm, vm)
            : childVal
          const defaultData = typeof parentVal === 'function'
            ? parentVal.call(vm, vm)
            : parentVal
          if (instanceData) {
            return mergeData(instanceData, defaultData)
          } else {
            return defaultData
          }
        }
      }
    }
    

      整体的也是和之前的几个函数一样 首先对vm的判断,其中就mergeData函数需要介绍下,看下mergeData源码,这个函数是用来干嘛的

    /**
     * Helper that recursively merges two data objects together.
     */
    function mergeData (to: Object, from: ?Object): Object {
      // 没有 from 直接返回 to
      if (!from) return to
      let key, toVal, fromVal
      const keys = Object.keys(from)
      // 遍历 from 的 key
      for (let i = 0; i < keys.length; i++) {
        key = keys[i]
        toVal = to[key]
        fromVal = from[key]
        // 如果 from 对象中的 key 不在 to 对象中,则使用 set 函数为 to 对象设置 key 及相应的值
        if (!hasOwn(to, key)) {
          set(to, key, fromVal)
        // 如果 from 对象中的 key 也在 to 对象中,且这两个属性的值都是纯对象则递归进行深度合并
        } else if (isPlainObject(toVal) && isPlainObject(fromVal)) {
          mergeData(toVal, fromVal)
        }
        // 其他情况什么都不做
      }
      return to
    }
    

     接收两个参数,to,from;

       根据调用传参  to 对应的是 childVal 产生的纯对象,from 对应 parentVal 产生的纯对象

      这个函数作用就是:将 from 对象的属性混合到 to 对象中,也可以说是将 parentVal 对象的属性混合到 childVal 中,最后返回的是处理后的 childVal 对象。

     合并阶段 strats.data 将被处理成一个函数,但是这个函数并没有被执行,而是到了后面初始化的阶段才执行的,

    重点:!!!!!!!!!!!

    mergeData 函数只有在初始化的时候才会执行,进行数据合并;

     Vue 的初始化的时候, inject 和 props 这两个选项的初始化是先于 data 选项的,这就保证了我们能够使用 props 初始化 data 中的数据

  • 相关阅读:
    linux centos下载地址
    什么是镜像文件?
    Linux下处理JSON的命令行工具:jq---安装
    CentOS7安装第三方yum源EPEL
    CentOS 6.5 下编译安装 Nginx 1.8.0
    CentOS 6.7 如何启用中文输入法
    Linux Yum 命令使用举例
    YUM 安装及清理
    Linux常用命令之rpm安装命令
    使用git代替FTP部署代码到服务器的例子
  • 原文地址:https://www.cnblogs.com/xweizi/p/10551938.html
Copyright © 2011-2022 走看看