关于this.$options._component的值。
来源:17-1 组件通信provide和inject
慕工程3718384
2019-12-03
Test 中的 _component的值 为什么首字母被小些了?而Test3组件中没有?
Vue.component('Test',{
template:"<div>{{message}}<Test2 /></div>",
provide(){
return {
elTest:this
}
},
data(){
return {
message:'message from ' + this.$options._componentTag
//_componentTag = test
}
},
methods:{
change:function(component) {
this.message = 'message from ' + component
}
}
});
Vue.component('Test2',{
template:"<Test3 />"
});
Vue.component('Test3',{
template:"<button type='button' @click='changeMessage'> change </button>",
inject:['elTest'],
methods:{
changeMessage:function () {
this.elTest.change(this.$options._componentTag);
//_componentTag = Test3
}
}
});
3回答
-
Sam
2019-12-04
你好,这是一个非常好的问题,要搞清楚这个问题需要对 Vue 的源码比较熟悉,问题出在 template 获取的部分,大致原理如下:
在 $mount 方法中,会使用如下代码获取 template 的 html 字符串:
template = getOuterHTML(el);
对于本案例中返回的结果为:
"<div id="root"> <test></test> </div>"
注意,这里的 Test 已经被转为了 test,此后在 baseCompile 的 parse 会将 template 解析为 AST,在解析 AST 过程中会将 id 为 root 的 div 的 children 解析出来,children 中包含了 test 标签,最后会生成 render 函数如下:
(function anonymous( ) { with(this){return _c('div',{attrs:{"id":"root"}},[_c('test')],1)} })
可以看到 _c('test') 中已经将 test 变成小写,而 Test 组件中的 template 为:
<div>{{message}}<Test2 /></div>
Test 组件的渲染方法如下:
child.$mount(hydrating ? vnode.elm : undefined, hydrating);
该方法中会获取组件的 template,这里的获取方法与 Vue 实例中不同:
if (!options.render) { var template = options.template; if (template) { if (typeof template === 'string') { if (template.charAt(0) === '#') { template = idToTemplate(template); /* istanbul ignore if */ if (!template) { warn( ("Template element not found or is empty: " + (options.template)), this ); } } } else if (template.nodeType) { template = template.innerHTML; } else { { warn('invalid template option:' + template, this); } return this } } else if (el) { template = getOuterHTML(el); }
最终会执行 Test 组件的 render 方法:
(function anonymous( ) { with(this){return _c('div',[_v(_s(message)),_c('Test2')],1)} })
212019-12-10 -
Sam
2019-12-04
你看源码非常细心,不过想搞清楚这个问题较为复杂,最后一句话概况,造成这种差异的原因是:template 获取方式不同。
写在 root 下的 Test 通过:
template = getOuterHTML(el);
获取 template,getOuterHTML 通过 el.outerHTML 来实现,而组件的 template 是直接返回的,没有做任何处理,所以造成了这种差异
10 -
Hemingway_AT
2019-12-10
现象是:除了第一层级的组件,_componentTag 小写,其子组件和孙子组件...都是大写
00
相似问题