这个问题分两种状况:
- new Vue({el: ‘#app’})
- 单文件组件 template 中根元素只能有一个
要解释这个问题,最好的形式就是间接看源码
一、Vue 实例
一个 vue 实例的创立大抵分为如下两个步骤
以 vue2.5.2 版本为例:
- 调用_init 办法初始化事件和生命周期,对 options 做选项合并
- 看传进来的参数有没有 el 选项,如果有则调用 $mount 来挂载模板
_init 办法在 Vue 的构造函数中被调用
_init 办法的创立在 initMixin 中,能够看到在 Vue 的原型对象下增加了_init 办法,外面的内容能够不论,大部分都是在做选项合并的操作,间接跳到我圈进去的中央,也就是咱们接下来要说的第二步
$mount 代码非常简单,判断 el 有没有、是不是浏览器环境,是就把 query 函数的返回值给它,否则赋值为 undefined,做完这些事件之后调用 mountComponent 函数,这个函数看名字就晓得是用来挂载模板
咱们来看看 query 函数
query 函数的作用就是判断传进来的 el 是不是元素,如果是就间接返回,否则应用浏览器 document 的 querySelector API 来获取它
到这里是否曾经豁然开朗,原来答案这么简略,querySelector 只会返回第一个匹配的 dom 元素,因而就算你写了两个顶层元素也默认只会抉择第一个 dom 作为入口
如果你还不理解 querySelector,请浏览如下文档:
https://developer.mozilla.org…
因而,当咱们实例化一个 Vue 时如果写了两个入口,当初你晓得答案了吗?
let vm = new Vue({
el:'#app',
data:{msg: '你好'}
})
<body>
<div id='app'>{{msg}}</div>
<div id='app'>{{msg}}</div>
</body>
二、 单文件组件
.vue 文件会通过 vue-loader 转换成 js 代码,在你通过 import 语句导入一个.vue 时,实际上就是导入这个组件的实例,与下面同理,实例须要一个入口,如果在 template 标签中写了两个根元素,它也不晓得将哪个元素作为组件实例的入口,因而罗唆就通知你只须要一个根元素
The template root requires exactly one element
源码如下所示,圈进去的这段代码的作用就是解析 template 并转换成渲染函数,最终 $mount 办法被调用时会将解析好的模板插入到对应的节点中
本文由博客一文多发平台 OpenWrite 公布!