Răsfoiți Sursa

选项的处理之mergeOptions函数的第一个参数解析

HcySunYang 7 ani în urmă
părinte
comite
58e4c2e185

+ 1 - 1
note/Vue的思路之以一个例子为线索.md

@@ -212,7 +212,7 @@ initProvide(vm) // resolve provide after data/props
 callHook(vm, 'created')
 ```
 
-而这些方法才是真正起作用的一些初始化方法,在这些初始化方法中,无一例外的都使用到了实例的 `$options` 属性,即 `vm.$options`。所以 `$options` 这个属性的的确确是用于 `Vue` 实例初始化的,只不过在初始化之前,我们需要一些手段产生 `$options` 属性,而这就是 `mergeOptions` 函数的作用,接下来我们就看看 `mergeOptions` 是都做了些什么,又有什么意义。
+而这些方法才是真正起作用的一些初始化方法,大家可以找到这些方法看一看,在这些初始化方法中,无一例外的都使用到了实例的 `$options` 属性,即 `vm.$options`。所以 `$options` 这个属性的的确确是用于 `Vue` 实例初始化的,只不过在初始化之前,我们需要一些手段产生 `$options` 属性,而这就是 `mergeOptions` 函数的作用,接下来我们就看看 `mergeOptions` 是都做了些什么,又有什么意义。
 
 
 

+ 124 - 0
note/Vue的思路之选项的处理.md

@@ -1,2 +1,126 @@
 ## Vue 的思路之选项的处理
 
+这一小节我们继续前面的讨论,看一看 `mergeOptions` 都做了些什么。根据 `core/instance/init.js` 顶部的引用关系可知,`mergeOptions` 函数来自于 `core/util/options.js` 文件,事实上不仅仅是 `mergeOptions` 函数,整个文件所做的一切都为了一件事:选项的合并。
+
+不过在我们深入 `core/util/options.js` 文件之前,我们有必要搞清楚一件事,就是如下代码中:
+
+```js
+vm.$options = mergeOptions(
+    resolveConstructorOptions(vm.constructor),
+    options || {},
+    vm
+)
+```
+
+传递给 `mergeOptions` 函数的三个参数到底是什么。
+
+其中第一个参数是通过调用一个函数得到的,这个函数叫做 `resolveConstructorOptions`,并将 `vm.constructor` 作为参数传递进去。第二个参数 `options` 就是我们调用 `Vue` 构造函数时透传进来的对象,第三个参数是当前 `Vue` 实例,现在我们逐一去看。
+
+`resolveConstructorOptions` 是一个函数,这个函数就声明在 `core/instance/init.js` 文件中,如下:
+
+```js
+export function resolveConstructorOptions (Ctor: Class<Component>) {
+  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)
+      console.log(options)
+      if (options.name) {
+        options.components[options.name] = Ctor
+      }
+    }
+  }
+  return options
+}
+```
+
+在具体去看代码之前,大家能否通过这个函数的名字猜一猜这个函数的作用呢?其名字 `resolve Constructor Options` 那么这个函数是不是用来*解析构造者的 `options`*的呢?答案是:对,就是干这个的。接下来我们就具体看一下它是怎么做的,首先第一句:
+
+```js
+let options = Ctor.options
+```
+
+其中 `Ctor` 即传递进来的参数 `vm.constructor`,在我们的例子中他就是 `Vue` 构造函数,可能有的同学会问:难道它还有不是 `Vue` 构造函数的时候吗?当然,当你使用 `Vue.extend` 创造一个子类并使用子类创造实例时,那么 `vm.constructor` 就不是 `Vue` 构造函数,而是子类,比如:
+
+```js
+const Sub = Vue.extend()
+const s = new Sub()
+```
+
+那么 `s.constructor` 自然就是 `Sub` 而非 `Vue`,大家知道这一点即可,但在我们的例子中,这里的 `Ctor` 就是 `Vue` 构造函数,而有关于 `Vue.extend` 的东西,我们后面会专门讨论的。
+
+所以,`Ctor.options` 就是 `Vue.options`,然后我们再看 `resolveConstructorOptions` 的返回值是什么?如下:
+
+```js
+return options
+```
+
+也就是把 `Vue.options` 返回回去了,所以这个函数的确就像他的名字那样,用来获取构造者的 `options` 的。不过同学们可能注意到了,`resolveConstructorOptions` 函数的第一句和最后一句代码中间还有一坨包裹在 `if` 语句中的代码,那么这坨代码是干什么的呢?
+
+我可以很明确的告诉大家,这里水稍微有那么点深,比如 `if` 语句的判断条件 `Ctor.super`,`super` 这是子类才有的属性,如下:
+
+```js
+const Sub = Vue.extend()
+console.log(Sub.super)  // Vue
+```
+
+也就是说,`super` 这个属性是与 `Vue.extend` 有关系的,事实也的确如此。除此之外判断分支内的第一句代码:
+
+```js
+const superOptions = resolveConstructorOptions(Ctor.super)
+```
+
+我们发现,又递归的调用了 `resolveConstructorOptions` 函数,只不过此时的参数是构造者的父类,之后的代码中,还有一些关于父类的 `options` 属性是否被改变过的判断和操作,并且大家注意这句代码:
+
+```js
+// check if there are any late-modified/attached options (#4976)
+const modifiedOptions = resolveModifiedOptions(Ctor)
+```
+
+不过这次有点不同,不同的是,我们要注意的是注释,有兴趣的同学可以根据注释中括号内的 `issue` 索引去搜一下相关的问题,这句代码是用来解决 `vue-hot-reload-api` 或者 `vue-loader` 时产生的一个 `bug` 的。
+
+现在大家知道这里的水有多深了吗?关于这些问题,我们在将 `Vue.extend` 中都会给大家一一解答,不过有一个因素从来没有变,那就是 `resolveConstructorOptions` 这个函数的作用永远都是用来获取当前实例构造者的 `options` 属性的,即使 `if` 判断分支内也不例外,因为 `if` 分支只不过是处理了 `options`,最终返回的永远都是 `options`。
+
+所以根据我们的例子,`resolveConstructorOptions` 函数目前并不会走里面的判断分支,即此时这个函数相当于:
+
+```js
+export function resolveConstructorOptions (Ctor: Class<Component>) {
+  let options = Ctor.options
+  return options
+}
+```
+
+所以,根据我们的例子,此时的 `mergeOptions` 函数的第一个参数就是 `Vue.options`,那么大家还记得 `Vue.options` 长成什么样子吗?不记得也没关系,这就得益于我们整理的 [附录/Vue构造函数整理-全局API](/note/附录/Vue构造函数整理-全局API) 了,通过查看我们可知 `Vue.options` 如下:
+
+```js
+Vue.options = {
+	components: {
+		KeepAlive
+		Transition,
+    	TransitionGroup
+	},
+	directives: Object.create(null),
+	directives:{
+	    model,
+        show
+	},
+	filters: Object.create(null),
+	_base: Vue
+}
+```
+
+
+
+
+