mergeField

  • strats 对象
    • el 、propsData
    • data
    • props、methods、inject、computed
    • watch
    • provide
    • components、directives、filters
    • 生命周期函数合并
  • defaultStrat 合并方法

根据不同的配置项使用不同的方法合并配置,

mergeOptions 代码片段

var options = {}
var keyfor(key in parent) {mergeField(key)}
for(key in child) {mergeField(key)}function mergeField(key) {var strat = strats[key] || defaultStratoptions[key] = strat(parent[key],child[key],vm)
}

strats 对象

starts 对象预制了一些方法用来处理一些固定的配置项

el 、propsData

这2个选项将使用默认合并方法defaultStrat 合并数据, 但是它们只有在创建实例的时候才有效, 如果不是在实例时合并,就会提示错误,但还是会合并

strats.el = strats.propsData = function(parent,child,vm,key){if(!vm) {...}return defaultStrat(parent,child)
}

data

合并data配置项,parentV就是 Vue.options.data , childV就是传入的data , 接着执行 mergeDataOrFn函数

strats.data = function(parentV,childV,vm) {if(!vm) {if(childV && typeof childV != "function") {return parentV}return mergeDataOrFn(parentV,childV)}return mergeDataOrFn(parentV,childV,vm)
}

mergeDataOrFn 分为2种合并,1. extend、mixin 合并和 2. 实例化时合并

  1. extend、mixin合并: 只要一侧传入的是undefined,就没有合并的必要,直接返回另一侧 data函数. 当两个参数都有值时,返回一个闭包函数 mergeDataFn ,它的参数就是各自的data数据
function mergeDataOrFn(parentV,childV,vm) {if(!vm) {if(!childV) {return parentV}if(!parentV) {return childV}return function mergeDataFn() {return mergeData(typeof childV === "function" ? childV.call(this,this) : childV,typeof parentV === "function" ? parentV.call(this,this) : parentV )}} else {...}
}
  1. 实例化时传入了vm参数,则返回一个 mergedInstanceDataFn 闭包函数, 其实细看的话,和mergeDataFn差不多
if(!vm){...} else {return function mergedInstanceDataFn() {var instanceData = typeof childVal === 'function' ? childVal(vm,vm) : childValvar defaultData = typeof parentVal === 'function' ? parentVal(vm,vm) : parentValif(instanceData) {return mergeData(instanceData,defaultData)} else {return defaultData}}
}

props、methods、inject、computed

这几个属性公用一个函数,功能是一致的.就是将 Vue.options上的和传入的配置项合并到一个空的对象中并返回 . 完整代码:

strats.props =
strats.methods =
strats.inject =
strats.computed = function (parentV,childV,vm,key) {if(childV && "development" != "production") {assertObjectType(key,childV,vm)}if(!parentV) {return childV}var ret = Object.create(null)extend(ret,parentV)if(childV){extend(ret,childV)}return ret
}

assertObjectType 就是对配置项验证,格式必须为 [object Object]
如果 Vue.options 上没有对应的配置,则无需合并,直接返回传入的配置

if(!parentV) {return childV}

用一个空的对象来合并childV和parentV, 依次遍历属性添加到对象中

var ret = Object.create(null)
extend(ret,parentV)
if(childV) {extend(ret,childV)}
return ret

extend(to,from) 它的功能就是遍历对象,将from里的属性挨个添加到 to 上面

function extend(to,from) {for(var key in from) {to[key] = from[key]}return to
}

watch

先看看合并后的结果,如果两边都有数据,则合并后的watch是一个数组

watch: {test: [fn,fn]
}
  • 用户没有传入 watch选项时, 把Vue.options上的 watch 作为原型新建一个对象返回
  • Vue.options 上没有 watch选项时, 原样返回用户传入的watch配置
  • 两边都有时,先遍历Vue.options的watch把属性添加到临时变量ret上(又见extend函数,上面了解过它就是遍历对象把属性添加到另一个对象上,在这里也就是 ret对象),再遍历用户传入的配置
stras.watch =  function (parentV,childV,vm,key) {if(!childV) {return Object.create(parentV || null)}if(!parentV) {return childV}var ret = {}extend(ret,parentV)for(var key$1 in childV) {var parent = ret[key$1]var child = child[key$1]if(parent && !Array.isArray(parent)) {parent = [parent]}ret[key$1] = parent ? parent.concat(child) : Array.isArray(child) ? child : [child]}return ret
}

现在对遍历用户传入的配置做一下拆分,那么for-in的代码可以理解为:

for(var key in childV) {var parent = parentV[key]var child = childV[key]if(parent && !Array.isArray(parent)) {parent = [parent]}if(child && !Array.isArray(child)) {child = [child]}ret[key] = parent ? parent.concat(child): child
}

provide

provide 则使用与 data 合并时一样的 mergeDataOrFn函数, 只要有一侧没有 provide 就不会合并, 原样返回有数据的那一侧.否则返回 mergeDataFn 闭包函数,将在实例化的时候调用

strats.provide = mergeDataOrFn

components、directives、filters

这3个配置项将使用 mergeAssets 合并, 首先将 Vue.options 中对应的属性作为原型创建一个新的对象(之前Vue.extend的分析中了解到初始的Vue.options中是含有默认的 components、directives、filters),然后遍历用户传入的配置,依次添加到这个对象上

var res = Object.create(parent || null)
return extend(red,child)
/************************/
function extend(to,from) {for(var key in from) {to[key] = from[key]}return to
}

生命周期函数合并

生命周期函数统一使用 mergeHook 合并数据, 处理后的生命周期是一个数组

var LIFECYCLE_HOOLS = ['beforeCreate','created','beforeMount','mounted','beforeUpdate','updated','beforeDestroy','destroyed','activated','deactivated'
]
LIFECYCLE_HOOLS.forEach(function(hook){strats[hook] = mergeHook
})/************************/function mergeHook(parentV,childV) {var res = childV ? (parentV ? parentV.concat(childV) : Array.isArray(childV) ? childV : [childV]) : [parentV]return res ? dedupeHooks(res) : res
}

为了简述这个三元表达式,我以 if() 表述帮助分析,大致如下:

  • 用户传入了某个生命周期函数并且Vue.options中也有一样的,则把用户传入的添加到数组的末尾.也就是这样形式

    created: [fn,fn]
    
  • 用户传入了但是Vue.options上没有,如果不是数组则包装成数组[ childV ],否则原样返回
  • 用户没有传入,但Vue.options上有,则把它包装成数组[ parentV ] 返回
var res = null
if(childV) {if(parentV) {res = parentV.concat(childV)} else {res = Array.isArray(childV) ? childV : [childV]}
} else {res = [parentV]
}

最后再调用去重方法 dedupHooks, 这部分就不分析了,代码也很简单

function dedupHooks(hooks) {var res = []for(var i = 0; i < hooks.length; i++) {if(res.indexOf(hooks[i] === -1)) {res.push(hooks[i])}}return res
}

defaultStrat 合并方法

除了 strats 预制的合并方法, 其余的都用 defaultStart 来处理合并, 它内部就是一个三元表达式, 用户有传入配置就使用用户传入的,否则使用Vue.options上的

function defaultStart(parentVal,childVal) {return childVal === undefind ? parentVal : childVal
}

mergeField解析(构造函数)相关推荐

  1. android arrayadapter 构造函数,Android无法解析构造函数ArrayAdapter

    我知道这个问题之前已经被多次询问过,但没有一个解决方案适用于我.这是我的代码:Android无法解析构造函数ArrayAdapter public class reminderDAO extends ...

  2. 无法解析构造函数‘Employee(int,java.lang.String,java.lang.String,int,com.kuang.pojo.Department)‘

    前言:在写这篇博客的时候,本来博客名字打算叫:"在给Java伪造数据库里面的伪数据的相关字段插入数据时,插入失败,是什么原因导致的?",后来思前想后,还是决定直接拷贝使用编译器上面 ...

  3. 【构造函数】解析构造函数的作用

    百度一下:构造函数    构造函数 ,是一种特殊的方法.主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数 ,可根据 ...

  4. 百行代码打造一个DI容器(支持瞬时生命周期、单利生命周期、构造函数自动注入、属性自动注入、字段自动注入)...

    DI注入在.Net平台是非常流行的, 很多项目都用到了,很多开发人员或多或少也用到DI容器了,感觉DI容器很神奇很厉害.本文将通过百行代码展示DI容器的内部核心代码(包括组件的瞬时生命周期.单利生命周 ...

  5. C++构造函数与析构函数

    几乎所有的面向对象的编程语言都保护构造函数与析构函数,好学者就要举手了,啥情况啊,Java里面不就没有析构函数嘛.好吧,你问倒我了,不过可以认为Java的垃圾自动回收机制实现了对象析构的功能.管他呢, ...

  6. 【Kotlin】Kotlin 构造函数 ( 主构造函数 | 主构造函数声明属性 | init 初始化代码块 | 次构造函数 | 构造函数委托 | 调用构造函数创建实例对象 )

    文章目录 I . 主构造函数 II . 主构造函数声明属性 III . init 初始化代码块 IV . 主构造函数参数 和 成员变量访问方式 V . 主构造函数 可见性 设置 VI . 次构造函数 ...

  7. Laravel开发:Laravel核心——Ioc服务容器源码解析(服务器绑定)

    服务容器的绑定 bind 绑定 bind 绑定是服务容器最常用的绑定方式,在 上一篇文章中我们讨论过,bind 的绑定有三种: 绑定自身 绑定闭包 绑定接口 今天,我们这篇文章主要从源码上讲解 Ioc ...

  8. spring IOC 之篇三:默认标签的解析

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {// 对import标签的处 ...

  9. Spring Ioc 源码分析(一)- XML 解析

    2019独角兽企业重金招聘Python工程师标准>>> 注 :源码对应版本为 4.2.8.RELEASE 引入Spring依赖的时候,是否发现spring依赖有spring-bean ...

  10. 使用base标签后图片无法加载_Spring 源码学习(二)-默认标签解析

    `Spring` 解析默认标签~ 从上一篇笔记可以看出,在容器注册 bean 信息的时候,做了很多解析操作,而 xml 文件中包含了很多标签.属性,例如 bean . import 标签, meta ...

最新文章

  1. cocos2d-x 3.1.1 学习笔记[15] Shader 著色器
  2. 2017-7-6日记
  3. 查看Product table entry数量的几种办法
  4. 论ORM框架—EntityFrameworkCore
  5. mysql数据库连接关闭_解决mysql数据库连接自动关闭问题
  6. excel合并两列内容_还在为合并WPS表格(Excel)中两列内容而犯愁?此方法简单高效...
  7. java thread 输出结果_大神来看看这段程序输出结果是什么?
  8. Java 程序员中位数薪资达 1.45 万,但面试屡屡被拒?
  9. 腾讯体育php面试题,腾讯php程序员面试题目及答案分享!
  10. Win7 系统 屏幕旋转快捷键取消(有可能和别的软件有冲突)
  11. 短信推广的规则,你知道多少?
  12. 2017爱创课堂vue.js视频完整版
  13. stack around xxx is corrupted
  14. 官网webp转换工具cwebp简介
  15. TotalControl之手机录屏神器
  16. Windows 常用dos命令大全
  17. 蜂鸣器的结构原理及制作
  18. 闲来无事,过了三天“神雕侠侣”的生活
  19. python py7zr 压缩解压 指定文件名、文件后缀
  20. 是男人就下100层【第一层】——高仿微信界面(8)

热门文章

  1. matlab 飞机大战小游戏
  2. TiDB2.1 报错statement count 5001 exceeds the transaction limitation, autocommit = false
  3. 从这条博客开始转变!
  4. 吉大网络教育护理学专升本病例分析
  5. 学单片机有前途还是嵌入式系统有前途?
  6. 对话微软大中华区CEO梁念坚:WP7为云而生
  7. java 图片缩放 失真_Java图片缩小后不失真的代码(缩略图)
  8. mc:Ignorable=“d“什么意思?
  9. 深度学习与目标检测电子书
  10. python idle使用_Python IDLE 基本操作