Vue 源码(四):Vue

在上一篇博客中,我们完成了 isBuiltInTag 方法,那么接下来我们再来完成 isReservedTag。

isReservedTag 这个方法很明显规定的是一些 html 和 svg 它们下面的一些标签,我们不能定义为组件名。

但是因为我们并不知道有哪些 html 和 svg 的标签名称,所以我们需要想办法知道。

那么我们可以直接通过源码,将 isHTMLTag 和 isSVG 给 copy 过来。

然后我们可以看到,在 isHTMLTag 和 isSVG 中,它都调用了 makeMap 方法。

那么我们知道,实际上 makeMap 方法它会给我们返回一个匿名函数。

因为我们实际上都是把那些字符串都存储在 list 这个数组里面,然后我们在 map 里面来拓展一个这样的属性。

那么我们就可以利用 isHTMLTag 和 isSVG 来完成 isReservedTag 方法了。

那么 isReservedTag 方法的 return isHTMLTag(tag) || isSVG(tag) 这段代码怎么理解呢?

我们通过 isHTMLTag(tag) || isSVG(tag),意思就是我们实际上是去调用的 makeMap 里面的匿名函数。

当我们调用这个匿名函数的时候,我们就会把组件的名称 tag 给你传过去。

如果说你是有值的,map 里面就是 true,返回的也就是 true,那么没有值返回的就是 false 了。

然后 isHTMLTag(tag) || isSVG(tag) 的返回值就会作为 isReservedTag 这个函数的返回值。

最后我们再把 isReservedTag 方法的返回值返回出去就OK了。

我们可以看到,在源码中,它就是这么去架构的,它是先把 html 和 svg 保留的关键字都找到,然后再去调用 makeMap 这个方法,在把它的返回值返回的这个匿名函数给到 isHTMLTag 和 isSVG,然后我们在去调用它们,来获取我们当前所注册的这个标签名,它是否与 isHTMLTag 和 isSVG 里面的 map 是否有这个属性。

这时候我们可以更改下组件名为 div,我们就可以在控制台看到报错信息了。

这个就是我们对于组件的名称所做的一步规范的检测。

那么让我们回到 mergeOptions 方法,下面需要做的事情就是合并,那么我们应该怎么来进行合并,合并谁呢?

我们会把 parent, child, vm 它们来进行合并,生成一个新的对象,然后在把这个最终生成的对象返回出去就好了。

那么我们具体怎么做呢?我们可以进行2个 for in 循环。

第一个循环我们的 Vue.options 对象,也就是 parent。

第二个循环用户传过来的 options 对象,也就是 child。

然后我们在遍历的时候,都会有一个策略,会去调用一个 mergeField 方法,然后把 key 传过去。

那么我们的策略里面究竟要做什么事呢?

以默认为优先,以用户配置为覆盖。

我们会通过 defaultStrat 方法来实现,然后我们会检测 parent 是否有这项值,child 里面是否也有这项值。

其实,我们在它里面真正的只需要关心 child 是否有值就行,然后再将最后的结果赋值给 options。

然后我们还会来遍历 child,它里面是一些自定义的选项配置,比如 components, el, data, name 等等。

因为我们在上面 parent 遍历的时候已经传过了 components,所以我们给 options 拓展了一个 components 的属性了。

但是我们的 child 刚好也有 components 这项配置,所以在这里我们就会做一个重复的执行,那么我们就需要想一个解决方案。

那么我们会通过 hasOwn 这个方法来检测,在 parent 里面是否有当前这个 key 的属性。如果没有,在执行 options 的合并。

然后我们在 mergeField 方法里面来打印 options,就可以看到:

如果我们还想拓展一个自定义选项,比如 age: 18。那么我们也可以在 options 里面看到。

那如果说我们没有传 components 呢,那么这时候它肯定就是个空对象了。

因为如果说你没有给我传,那么我这个 components 默认的就是当前 Vue.options 里面的 components。

发布了61 篇原创文章 · 获赞 3 · 访问量 4387

猜你喜欢

转载自blog.csdn.net/weixin_43921436/article/details/100147544
vue