在上一篇博客中,我们讲到策略是以默认为优先,以用户配置为覆盖。
那么接下来,我们需要考虑一下,为什么需要有一个默认的策略?
如果说有默认的策略,那么是不是还应该有一个自定义的策略呢?
那么自定义策略是用来干嘛的呢?自定义策略主要是用来分析我们传过来的这些选项。
如果说,我们注册一个局部组件,也给它加上一个 el: '#app',那这样的话,可以吗?
我们引用源码,可以看到控制台报错了。
它会告诉我们,当前这个组件,你并不能这样去定义,因为我们的 el 选项只能用在创建实例的时候,来进行绑定。
所以局部组件里面是不能有 el 这个选项的。
那局部组件它本身又是 Vue 的一个子类,因此我们就会发现,有一些配置我们实际上是不能够使用的。
那么我们应该在哪里进行阻拦呢?我们就是通过自定义的策略来检测用户所传过来的这些选项,它们最终再来检测的一个规则。
那么接下来,我们就来实现它。首先,我们需要来建立一个配置文件。
那么在它里面,我们会来进行一些定义,定义啥?首先就定义一个,对于选项的自定义策略。
那么在源码里面,我们也可以看到里面有一个配置文件 config。那么我们来看下它是怎么来做的。
我们可以看到,从 390 行开始,到 482 行,就是整个的配置文件。
然后 optionMergeStrategies 这个属性,对应的就是我们的自定义策略。
所以我们给 optionMergeStrategies 赋值一个空对象。
那么 optionMergeStrategies 这个自定义的策略,对应的空对象是什么含义呢?
我们可以先简单的从单词的字面意思来了解下。
首先 option 就是选项的意思,Merge 就是合并,Strategies 就是策略。
那么我们会有一个疑问,这种策略,更多的不应该是个方法吗,怎么会是个对象呢?
实际上,它是做了一个这样的事情的,我们会直接的把 config 里面的这个自定义策略 optionMergeStrategies 的这项配置,挂载在 strats 这个变量里面。
如果说,你想要给哪一个选项来做一些自定义的策略的配置,那你就可以直接写,比如刚才说到的 el。
那么我们就可以来写一个 el 的配置:
那么接下来,我们就可以在 mergeField 方法里面做一个这样的事情:
我们会找到 strats 有没有当前 key 的属性,如果说你有这个属性,那我就直接把你的返回值拿到。
那么,这里的 strats[key] 指的是谁? 就是我们在上面写的自定义策略 optionMergeStrategies 里面的属性。
如果说当前这个 key 是 el,那就代表着它是有值的,你有值,那我就直接把你的值给返回出去。
如果没有值,就把 defaultStrat 给返回出去。
所以,我们在 mergeField 方面里面就可以做这样的改动:
所以,我们究竟要调用自定义策略,还是默认策略,最终,我就只看 result 这个表达式的结果就行了。
如果 strats 里面没有值,就是去 defaultStrat 里面找。
那么就很明显了,defaultStrat 是我们在上面定义的一个固定的函数,你有可能有值,也可能没有值。没有自定义策略的时候,当然是没值的。
然后回到 mergeField 函数中,因为我们调用 result(parent[key], child[key], vm, key) 是传入了4个参数。
所以我们在 strats.el 也是接收的 parent, child, vm, key。
那我们怎么才能去判断,在调用局部组件的时候,是使用 el,还是不使用 el 呢?
实际上很简单,因为我们在创建局部组件的时候,我们也会调用 result(parent[key], child[key], vm, key) 这个方法。
那我们去调用 result 这个方法的时候,就不会给它传 vm 这个参数。
也就是说,我们判断要不要使用 el 这个选项,成功或者失败的权限,依据就是当前里面的 vm 是否指向 Vue 的实例。
所以我们在 strats.el 里面直接判断 vm 是否有值就可以了。因为我们在创建一些局部组件和Vue子类的时候,在调用 result 的时候是并不会传 vm 的。
所以如果没值,我们就会输出一个报错信息,告诉你 el 只能在实例中使用。那如果没有报错,我们就会去调用 defaultStrat 默认策略的方法,再把 parent, child 给传过去。
那么我们从头梳理一遍:
在 mergeField 方法中,如果说 key 是 el 的时候,很显然,我们最终调用的也是默认策略 defaultStrat 这个方法。
但是我们会先经过 strats[key] 先给你晒选一遍,你在调用 strats.el 这个方法的时候,你里面的 vm 所指向的是不是 Vue 的实例。
那么谁会给我们传 vm 过来呢?我们在 mergeOptions 合并选项的时候,就会把 vm 传过来了。
那么 mergeOptions 它的 vm 又是谁传过来的呢?它的 vm 是在 initMixin 里面传过来的。所以 vm 就是指的 vm 实例。
我们在一些组件里面,它是不能够配置 el 这个选项的。
如果说你配置了,那么最终又会去调用 result 这个方法的时候,那么我就会给你报错,告诉你不能使用 el 的选项。
因为我们组件里面,你给我所传过来的配置,最终我们也是要来进行合并,和一些规范的检测。
并不是只有我们自身所传过来的 option 对象来进行检测。
在局部组件,Vue的子类里面,我们也是需要来检测的。