乐趣区

关于前端:Vue关于实例中为什么只能有一个根元素

这个问题分两种状况:

  • 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 公布!

退出移动版