mergeField解析(构造函数)
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. 实例化时合并
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 {...}
}
- 实例化时传入了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解析(构造函数)相关推荐
- android arrayadapter 构造函数,Android无法解析构造函数ArrayAdapter
我知道这个问题之前已经被多次询问过,但没有一个解决方案适用于我.这是我的代码:Android无法解析构造函数ArrayAdapter public class reminderDAO extends ...
- 无法解析构造函数‘Employee(int,java.lang.String,java.lang.String,int,com.kuang.pojo.Department)‘
前言:在写这篇博客的时候,本来博客名字打算叫:"在给Java伪造数据库里面的伪数据的相关字段插入数据时,插入失败,是什么原因导致的?",后来思前想后,还是决定直接拷贝使用编译器上面 ...
- 【构造函数】解析构造函数的作用
百度一下:构造函数 构造函数 ,是一种特殊的方法.主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数 ,可根据 ...
- 百行代码打造一个DI容器(支持瞬时生命周期、单利生命周期、构造函数自动注入、属性自动注入、字段自动注入)...
DI注入在.Net平台是非常流行的, 很多项目都用到了,很多开发人员或多或少也用到DI容器了,感觉DI容器很神奇很厉害.本文将通过百行代码展示DI容器的内部核心代码(包括组件的瞬时生命周期.单利生命周 ...
- C++构造函数与析构函数
几乎所有的面向对象的编程语言都保护构造函数与析构函数,好学者就要举手了,啥情况啊,Java里面不就没有析构函数嘛.好吧,你问倒我了,不过可以认为Java的垃圾自动回收机制实现了对象析构的功能.管他呢, ...
- 【Kotlin】Kotlin 构造函数 ( 主构造函数 | 主构造函数声明属性 | init 初始化代码块 | 次构造函数 | 构造函数委托 | 调用构造函数创建实例对象 )
文章目录 I . 主构造函数 II . 主构造函数声明属性 III . init 初始化代码块 IV . 主构造函数参数 和 成员变量访问方式 V . 主构造函数 可见性 设置 VI . 次构造函数 ...
- Laravel开发:Laravel核心——Ioc服务容器源码解析(服务器绑定)
服务容器的绑定 bind 绑定 bind 绑定是服务容器最常用的绑定方式,在 上一篇文章中我们讨论过,bind 的绑定有三种: 绑定自身 绑定闭包 绑定接口 今天,我们这篇文章主要从源码上讲解 Ioc ...
- spring IOC 之篇三:默认标签的解析
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {// 对import标签的处 ...
- Spring Ioc 源码分析(一)- XML 解析
2019独角兽企业重金招聘Python工程师标准>>> 注 :源码对应版本为 4.2.8.RELEASE 引入Spring依赖的时候,是否发现spring依赖有spring-bean ...
- 使用base标签后图片无法加载_Spring 源码学习(二)-默认标签解析
`Spring` 解析默认标签~ 从上一篇笔记可以看出,在容器注册 bean 信息的时候,做了很多解析操作,而 xml 文件中包含了很多标签.属性,例如 bean . import 标签, meta ...
最新文章
- cocos2d-x 3.1.1 学习笔记[15] Shader 著色器
- 2017-7-6日记
- 查看Product table entry数量的几种办法
- 论ORM框架—EntityFrameworkCore
- mysql数据库连接关闭_解决mysql数据库连接自动关闭问题
- excel合并两列内容_还在为合并WPS表格(Excel)中两列内容而犯愁?此方法简单高效...
- java thread 输出结果_大神来看看这段程序输出结果是什么?
- Java 程序员中位数薪资达 1.45 万,但面试屡屡被拒?
- 腾讯体育php面试题,腾讯php程序员面试题目及答案分享!
- Win7 系统 屏幕旋转快捷键取消(有可能和别的软件有冲突)
- 短信推广的规则,你知道多少?
- 2017爱创课堂vue.js视频完整版
- stack around xxx is corrupted
- 官网webp转换工具cwebp简介
- TotalControl之手机录屏神器
- Windows 常用dos命令大全
- 蜂鸣器的结构原理及制作
- 闲来无事,过了三天“神雕侠侣”的生活
- python py7zr 压缩解压 指定文件名、文件后缀
- 是男人就下100层【第一层】——高仿微信界面(8)
热门文章
- matlab 飞机大战小游戏
- TiDB2.1 报错statement count 5001 exceeds the transaction limitation, autocommit = false
- 从这条博客开始转变!
- 吉大网络教育护理学专升本病例分析
- 学单片机有前途还是嵌入式系统有前途?
- 对话微软大中华区CEO梁念坚:WP7为云而生
- java 图片缩放 失真_Java图片缩小后不失真的代码(缩略图)
- mc:Ignorable=“d“什么意思?
- 深度学习与目标检测电子书
- python idle使用_Python IDLE 基本操作