|
@@ -79,9 +79,9 @@ function mergeField (key) {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-`mergeField` 函数只要两句代码,第一句代码定义了一个常量 `start`,它的值是通过指定的 `key` 访问 `strats` 对象得到的,而当访问的属性不存在时,则使用 `defaultStrat` 作为值。
|
|
|
+`mergeField` 函数只有两句代码,第一句代码定义了一个常量 `start`,它的值是通过指定的 `key` 访问 `strats` 对象得到的,而当访问的属性不存在时,则使用 `defaultStrat` 作为值。
|
|
|
|
|
|
-这里我就要明确了,`starts` 是什么?想弄明白这个问题,我们需要从整体角度去看一下 `options.js` 文件,首先看 `import` 语句下的第一句代码:
|
|
|
+这里我我就要明确了,`starts` 是什么?想弄明白这个问题,我们需要从整体角度去看一下 `options.js` 文件,首先看文件顶部的一堆 `import` 语句下的第一句代码:
|
|
|
|
|
|
```js
|
|
|
/**
|
|
@@ -92,7 +92,7 @@ function mergeField (key) {
|
|
|
const strats = config.optionMergeStrategies
|
|
|
```
|
|
|
|
|
|
-这个 `config` 对象是全局配置对象,来自于 `core/config.js` 文件,此时 `config.optionMergeStrategies` 还只是一个空的对象。注意一下这里的一段注释:*选项覆盖策略是处理如何将父选项值和子选项值合并到最终值的函数*。也就是说 `config.optionMergeStrategies` 是一个合并选项的策略对象,这个对象下包含很多函数,这些函数就可以认为是合并特定选项的策略。这样不同的选项使用不同的合并策略,如果你使用自定义选项,那么你也可以自定义该选项的合并策略,只需要在 `Vue.config.optionMergeStrategies` 对象上添加与自定义选项同名的函数就行。而这就是 `Vue` 文档中提过的全局配置:[optionMergeStrategies](https://vuejs.org/v2/api/#optionMergeStrategies)。
|
|
|
+这句代码就定义了 `strats` 变量,且它是一个常量,这个常量的值为 `config.optionMergeStrategies`,这个 `config` 对象是全局配置对象,来自于 `core/config.js` 文件,此时 `config.optionMergeStrategies` 还只是一个空的对象。注意一下这里的一段注释:*选项覆盖策略是处理如何将父选项值和子选项值合并到最终值的函数*。也就是说 `config.optionMergeStrategies` 是一个合并选项的策略对象,这个对象下包含很多函数,这些函数就可以认为是合并特定选项的策略。这样不同的选项使用不同的合并策略,如果你使用自定义选项,那么你也可以自定义该选项的合并策略,只需要在 `Vue.config.optionMergeStrategies` 对象上添加与自定义选项同名的函数就行。而这就是 `Vue` 文档中提过的全局配置:[optionMergeStrategies](https://vuejs.org/v2/api/#optionMergeStrategies)。
|
|
|
|
|
|
那么接下来我们就看看这个选项合并策略对象都有哪些策略,首先是下面这段代码:
|
|
|
|
|
@@ -113,7 +113,75 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-在非生产环境下在 `strats` 策略对象上添加两个策略(两个属性)分别是 `el` 和 `propsData`,且这两个策略的值是一个函数。通过其策略的名字可知,这两个策略是用来合并 `el` 选项和 `propsData` 选项的。
|
|
|
+非生产环境下在 `strats` 策略对象上添加两个策略(两个属性)分别是 `el` 和 `propsData`,且这两个属性的值是一个函数。通过函数的名字可知,这两个策略函数是用来合并 `el` 选项和 `propsData` 选项的。与其说“合并”不如说“处理”,因为其本质上并没有做什么合并工作。那么我们看看这个策略函数的具体内容,了解一下它是怎么处理的 `el` 和 `propsData` 选项的。
|
|
|
+
|
|
|
+首先是一段 `if` 判断分支,判断是否有传递 `vm` 参数:
|
|
|
+
|
|
|
+```js
|
|
|
+if (!vm) {
|
|
|
+ warn(
|
|
|
+ `option "${key}" can only be used during instance ` +
|
|
|
+ 'creation with the `new` keyword.'
|
|
|
+ )
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+如果没有传递这个参数,那么便会给你一个警告,提示你 `el` 选项或者 `propsData` 选项只能在使用 `new` 操作符创建实例的时候可用。比如下面的代码:
|
|
|
+
|
|
|
+```js
|
|
|
+// 子组件
|
|
|
+var ChildComponent = {
|
|
|
+ el: '#app2',
|
|
|
+ created: function () {
|
|
|
+ console.log('child component created')
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 父组件
|
|
|
+new Vue({
|
|
|
+ el: '#app',
|
|
|
+ data: {
|
|
|
+ test: 1
|
|
|
+ },
|
|
|
+ components: {
|
|
|
+ ChildComponent
|
|
|
+ }
|
|
|
+})
|
|
|
+```
|
|
|
+
|
|
|
+上面的代码中我们在子组件中使用了 `el` 选项,就会得到如上警告。其实我们想一想 `el` 选项的作用,它作为一个挂载点,确实没有必要出现在子组件中,出现在根组件中才是有意义的,而这就是要这么处理这两个选项的原因。
|
|
|
+
|
|
|
+我们接着按照顺序看 `options.js` 文件的代码,接下来定义了两个函数:`mergeData` 以及 `mergeDataOrFn`。我们暂且不关注这两个函数的作用,我们继续看下面的代码,接下来的代码如下:
|
|
|
+
|
|
|
+```js
|
|
|
+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.call(this, parentVal, childVal)
|
|
|
+ }
|
|
|
+
|
|
|
+ return mergeDataOrFn(parentVal, childVal, vm)
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+这段代码的作用是在 `strats` 策略对象上添加 `data` 策略函数,用来合并 `data` 选项的。
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
|
|
|
|