zoukankan      html  css  js  c++  java
  • 【Vue】源码——为什么 Vue 实例只能有一个根元素?

    Vue 实例

    首先,我觉得这个问题要先从 Vue 的实例开始讲起。Vue 的实例一般都是长成下面这个样子,不同的只是 id 名的不同。

    <div id="app"></div>
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {}
        ...
    })
    这就是 Vue 实例的基本结构,并不陌生。从这里可以看到,el 的指定是一个 id 为 app 的 div 元素,Vue 实例接管了对它的控制,减少了我们的 DOM 操作,需要被 vm 控制的元素全部加在它的内部。如果是需要控制不同的部分,这就需要多个 Vue 的实例来实现。疑问就来了,为什么需要不同的 Vue 实例来接管?

    入口问题

    在 Vue 中指定 el 选项是给 Vue 实例指定一个 SPA 入口,有可能你的页面会长成像下面这样:

    <div id="app"></div>
    <div id="app1"></div>
    <div id="app2"></div>

    虚拟 DOM

    学习 Vue 不得不说的就是2.0引入的Virtual DOM,引入虚拟 DOM 后,在框架的内部将虚拟 DOM 树型结构与真实 DOM 做了映射,让我们不用再命令式的去操作 DOM。

    引用里面的一张图片:

     从这张图可以看出来虚拟 DOM 的一个渲染过程,那我们再回到本文的话题:为什么只能由一个根元素?
    我们来看一个例子,假设你的 Vue 实例接管的 DOM 结构长成这个样子:

    <div id="app">
        <h1 id="h3">My title</h1>
        <span>Content</span>
        Other text
        <!-- annotation text -->
    </div>

    它在浏览器内部的表现是一个这样的 DOM 树:

     

    从这可以看出它是一个树的结构,每个元素、文字、注释都是一个节点,虚拟 DOM 遵循的也是这样的一个树的数据结构。

    回到正题,我们的指定的 el 也就是整个 DOM 结构的根。现在就很好说了,我们只有指定了唯一的 el 根元素,才能交给 Vue 实例在内部通过 createElement 方法生成一个对应的虚拟 DOM 结构映射真实的 DOM 元素进行操作渲染成真正的 HTML。

    换句话来说,可以把 el 对应的元素理解成 Vue 接管部分中的一个顶级标签,就像基本的 HTML 结构中,顶级标签是 <html></html>,只能有一个这样的标签存在。对应到 Vue 中也是这样,如果你给它两个顶级标签,那么对应的 DOM 结构就无法生成了,这也就解释了之前的疑惑:为什么不能指定多个入口让 Vue 实例一个个的试。

    vue-cli

    现在实际的项目开发中,使用脚手架 vue-cli 开发居多,我们来看看。

    vue-cli 的形式是单文件组件,一个 .vue 页面的基本结构是这样的:

    <template>
      <div></div>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style>
    
    </style>

    在这里,<template> 标签下也只能有一个根元素 div,这是为什么?

    在说这个话题之前,我们需要了解 H5 新标签 <template> 的一些特性,可以参考文档,它保证了内部的内容有效但不会被渲染。vue-cli 本质上是会把 .vue 文件通过 webpack 配置打包成一系列的 js/css 文件注入到一个 html 文件中交给浏览器进行解释执行,我们看一个打包好的文件目录:

     这也就是说,每个 .vue 文件都会是一个 Vue 的实例,而 <template> 标签中的内容就是 Vue 实例接管形成虚拟 DOM 的那部分内容。如果在 template 下有多个 div,那么虚拟 DOM 树就没办法生成了。

    问题抽象

    其实这个问题归结到最后,也可以抽象为一个问题:为什么抽象出来的 DOM 树只能有一个根?

    1. 从查找和遍历的角度来说,如果有多个根,那么我们的查找和遍历的效率会很低。
    2. 如果一个树有多个根,说明可以优化,肯定会有一个节点是可以访问到所有的节点,那这个节点就会成为新的根节点。
    3. 再从 Vue 本身来说,如果说一个组件有多个入口多个根,那不就意味着你的组件还可以进一步拆分成多个组件,进一步组件化,降低代码之间的耦合程度。
    转自:https://juejin.cn/post/6844904074438000648#heading-0
  • 相关阅读:
    读书笔记——吴军《态度》
    JZYZOJ1237 教授的测试 dfs
    NOI1999 JZYZOJ1289 棋盘分割 dp 方差的数学结论
    [JZYZOJ 1288][洛谷 1005] NOIP2007 矩阵取数 dp 高精度
    POJ 3904 JZYZOJ 1202 Sky Code 莫比乌斯反演 组合数
    POJ2157 Check the difficulty of problems 概率DP
    HDU3853 LOOPS 期望DP 简单
    Codeforces 148D. Bag of mice 概率dp
    POJ3071 Football 概率DP 简单
    HDU4405 Aeroplane chess 飞行棋 期望dp 简单
  • 原文地址:https://www.cnblogs.com/vickylinj/p/14415527.html
Copyright © 2011-2022 走看看