这个问题分两种状况:

  • new Vue({el: '#app'})
  • 单文件组件template中根元素只能有一个

要解释这个问题,最好的形式就是间接看源码

一、Vue实例

一个vue实例的创立大抵分为如下两个步骤

以vue2.5.2版本为例:

  1. 调用_init办法初始化事件和生命周期,对options做选项合并
  2. 看传进来的参数有没有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 公布!