Skip to content

Vue介绍与Vue的特点(Lesson1 2/4) ​

本页对应 Lesson01,共 6 段视频,约 1 小时 14 分。

学习目标 ​

  1. 能够创建两个独立 Vue 实例并分别挂载到不同 id 的 DOM 元素,验证数据互不影响;能说明同一 Vue 实例挂载到多个匹配元素时仅第一个元素生效。
  2. 能够在模板中使用双大括号插值渲染字符串、数字、布尔值、数组、对象、方法返回值及三元表达式,并正确说明 undefined、null、布尔值的渲染表现。
  3. 能够使用 v-text 与 v-html 完成文本和 HTML 内容渲染,指出二者在 HTML 标签解析上的差异,并正确使用属性值引用实例数据或输出字面量字符串。
  4. 能够使用 v-if、v-else-if、v-else 实现多条件渲染,说明条件指令必须连续相邻使用的要求,并验证条件不成立时元素不渲染。
  5. 能够使用 template 包裹多个元素配合 v-if/v-else 进行条件渲染,说明 template 本身不渲染且不能与 v-html/v-text 结合使用。
  6. 能够使用 v-show 控制元素显示隐藏,比较 v-show 与 v-if 在 DOM 渲染和 display 样式控制上的差异,并正确判断空字符串、0、null、undefined、非空字符串、数字 1 作为条件值时的显示结果。

知识点 ​

直接引入:先把 Vue 跑起来 ​

为什么需要:学习阶段最怕环境没配好就先被工程化工具拦住。直接引入适合先验证“Vue 能不能用”,也方便对照官方文档理解最基础的引入方式。

怎么想:先拿到 vue.js 文件,再用 <script> 引入页面。转写稿里也是先引入 Vue 的 JS,再写 new Vue 做挂载验证。注意转写稿中的“will”“vi”“we”都是口误或同音转写,实际指 Vue;“EL”应写作 el,“井号 root”就是选择器 #root。

怎么做:按笔记给出的下载地址进入官方安装页,选择直接下载引入。

shell
# 下载地址
https://v2.cn.vuejs.org/v2/guide/installation.html

下载后在 HTML 中用 script 标签引入本地文件,再写挂载代码验证。转写稿中的验证思路是:准备一个容器,例如 id="root",然后写 new Vue({ el: '#root', data: { ... } }),页面中通过双花括号把数据显示出来。

易错点:el 的值是选择器字符串,#root 的 # 不能丢;不要写成 EL;同一个 Vue 实例如果选择器匹配到多个元素,转写稿中演示的结论是只会把第一个满足条件的元素作为挂载元素,所以不要误以为一个实例能同时挂载多个容器。不同实例分别挂载不同元素是可以的。

CDN 引入:不下载文件,直接用脚本地址 ​

为什么需要:只想快速做一个小页面、验证模板语法时,CDN 比下载文件更省事,复制脚本地址即可运行。

怎么想:CDN 引入的关键是区分开发版和生产版。笔记注释已经说明:开发环境版本包含完整警告和调试模式;生产环境版本删除了警告。学习调试应优先用开发版,因为警告能帮助定位问题。

怎么做:把笔记中的两段 CDN 代码按需选一个放入 HTML。

html
<!-- 开发环境版本,包含完整的警告和调试模式 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 生产环境版本,删除了警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>

引入后仍然用 new Vue 挂载容器,用插值表达式显示 data 中的数据,确认页面能随数据变化而更新。转写稿中反复强调“数据驱动视图”:数据变了,视图会跟着变;这就是配置成功后最直观的验证。

易错点:不要同时引入开发版和生产版,否则容易造成重复引入和警告混乱;学习阶段不要为了“干净”直接用生产版,否则调试信息少;CDN 地址要完整,vue@2/dist/vue.js 与 vue@2 不是同一个文件。

NPM 安装:进入工程化项目的入口 ​

为什么需要:当项目不再是单个 HTML 文件,而是有多个模块、需要构建和依赖管理时,就要用 NPM 安装 Vue。笔记给出的就是最基础的安装命令。

怎么想:NPM 方式不是“装完就自动生效”,它表示把 Vue 作为项目依赖安装到当前工程中。学习时先记住命令和“最新稳定版”的含义,后续再结合具体工程结构使用。

怎么做:在项目目录中执行笔记命令。

shell
# 最新稳定版
$ npm install vue

安装后按项目已有的模块方式引入 Vue,再写 new Vue 挂载。转写稿中出现的“new will”“new vi”都应纠正为 new Vue;data 中的属性可以通过插值表达式放到模板中,例如 {{ name }}。这也是验证安装是否可用的最小闭环。

易错点:命令要在项目目录执行,不要在不相关目录乱装;笔记写的是“最新稳定版”,不要自行改成不确定的版本号;不要把 NPM 安装和 CDN 引入混在同一个练习里,否则排查问题时不知道用的是哪一份 Vue。

配置完成后的最小验证:挂载、模板与调试 ​

为什么需要:环境配置不是“代码复制完就结束”,要能证明 Vue 已经接管模板并完成渲染。

怎么想:转写稿中的调试过程很典型:先引入 Vue,再准备 id="root" 的容器,然后 new Vue({ el: '#root', data: { ... } }),最后在容器内写 {{ 属性名 }}。如果页面能显示数据,说明引入、挂载、模板编译这条链路通了。

怎么做:最小结构可以写成:容器 + 引入 Vue + new Vue + 插值。转写稿中还演示了用开发者工具修改数据,页面随之更新,这能帮助理解“响应式”。注意转写稿里的“差值表达式”应纠正为“插值表达式”,“微钢”“违刚”等是 v- 指令的转写误差,本节先不展开。

易错点:挂载容器要写在 new Vue 能选到的位置;el: '#root' 不要漏引号;插值表达式写在被挂载容器内部才由 Vue 编译;如果页面原样显示 {{ name }},优先检查 Vue 是否成功引入、el 是否写对、容器 id 是否一致。转写稿中同一个实例匹配多个元素只取第一个的调试结论,也要在验证时留意。

本节目标与整体思路 ​

这一节围绕“Vue 如何操作 DOM”展开:先看 Vue 实例如何挂载到元素,再看模板中的插值表达式,随后学习 v-html、v-text、v-if、v-else-if、v-else、template 和 v-show。转写稿里的“will / vi / 微钢 / 威刚”等同音字,实际分别指 Vue、Vue 实例、v- 指令。核心结论是:Vue 不主张直接手写 DOM 操作,而是用模板语法把数据“声明式”地绑定到视图;数据变,视图跟着变。

Vue 实例挂载:一个实例只能挂一个满足条件的元素 ​

为什么需要:要先明确 Vue 实例的作用范围,否则后续指令写在哪个容器里、数据从哪里来都会混乱。
怎么想:el 指定挂载容器,#root 表示 id 为 root 的元素。转写稿中先尝试“同一个 Vue 实例挂到不同元素”,结果发现只会把第一个满足条件的元素作为挂载元素,做不到一个实例挂多个容器。
怎么做:

html
<div id="root">
  <h1>{{ str }}</h1>
  <p>{{ str }}</p>
</div>
<script>
new Vue({
  el: '#root',
  data: { str: '万' }
})
</script>

如果要挂到不同元素,应使用不同 Vue 实例:

html
<div id="one"><h1>{{ str }}</h1></div>
<div id="two"><h1>{{ str }}</h1></div>
<script>
new Vue({ el: '#one', data: { str: 'one' } })
new Vue({ el: '#two', data: { str: 'two' } })
</script>

易错点:el: 'root' 少了 # 会选不中;同一个实例不要幻想同时挂多个容器,它只取第一个满足条件的元素。

插值表达式:把实例数据放进模板 ​

为什么需要:模板里要显示数据,不能每次都手动 innerHTML。
怎么想:{{ }} 是 Vue 模板的插值语法,里面的名字会到 Vue 实例的 data、方法等属性中查找。转写稿演示了字符串、数字、布尔值、方法、三元表达式、函数调用,甚至数组和对象。
怎么做:

html
<div id="root">
  <p>{{ name }}</p>
  <p>{{ 1 }}</p>
  <p>{{ fn() }}</p>
  <p>{{ sex === 1 ? '男' : '女' }}</p>
  <p>{{ str.split('').reverse().join('') }}</p>
</div>
<script>
new Vue({
  el: '#root',
  data: {
    name: '张三',
    sex: 1,
    str: '超级魔法师',
    arr: [1, 2, 3, 4],
    obj: { userName: '张三' }
  },
  methods: {
    fn() { return 200 }
  }
})
</script>

易错点:undefined、null 不会输出;数组不会像 React 那样直接展开,Vue 里数组仍按原样呈现;逻辑复杂或会被重复调用时,建议写方法,不要把所有逻辑塞进模板表达式。

v-text 与 v-html:文本输出和 HTML 输出 ​

为什么需要:有时要把实例属性直接写到元素里,并区分“当文本”还是“当 HTML 解析”。
怎么想:v-text 输出文本,不识别标签;v-html 会把字符串当 HTML 解析。转写稿用“百度”链接演示:v-text 显示标签文本,v-html 能生成可点击的 <a>。
怎么做:

html
<p v-text="userName"></p>
<p v-html="userName"></p>
<script>
new Vue({
  el: '#root',
  data: {
    userName: '<a href="http://baidu.com">百度</a>'
  }
})
</script>

易错点:v-text="userName" 里的 userName 是实例属性名,不是随便写的字符串;如果写成 v-text="'userName'",输出的就是字符串 userName。v-html 会覆盖元素原有内容,且不要用于不可信内容。

v-if / v-else-if / v-else:条件渲染 ​

为什么需要:页面经常要根据登录状态、年龄、权限等决定某块 DOM 是否渲染。
怎么想:v-if 为真才渲染所在元素;v-else-if 继续判断;v-else 兜底。转写稿用年龄分段演示,条件满足后下面分支不再看。
怎么做:

html
<div id="root">
  <p v-if="age > 80">老年</p>
  <p v-else-if="age > 40">中年</p>
  <p v-else-if="age > 18">青年</p>
  <p v-else>少年或儿童</p>
</div>
<script>
new Vue({ el: '#root', data: { age: 100 } })
</script>

易错点:v-else-if、v-else 必须和前面的 v-if 紧邻使用,中间不要插入其他没有指令的元素;转写稿中插入一个普通元素后,控制台出现编译异常。若把 v-else 去掉,多个条件可能同时成立,于是“老年、中年、壮年”等会一起显示。

template:只做包裹,不渲染自身 ​

为什么需要:多个元素要共享同一个条件,但又不想额外多一层 div。
怎么想:template 是包裹标签,本身不渲染,可与 v-if、v-show 结合。转写稿中把外层 div 改成 template 后,DOM 里不会多出包裹层。
怎么做:

html
<template v-if="isLogin">
  <input placeholder="请输入管理员账号">
  <input placeholder="请输入管理员密码">
</template>
<p v-else>未登录</p>

易错点:template 不能和 v-html、v-text 结合使用;它适合包裹条件内容,不要把它当成普通可见容器。

v-show:用 display 控制显示隐藏 ​

为什么需要:有些内容要频繁切换显示,但不希望反复销毁、重建 DOM。
怎么想:v-if 控制“是否渲染”,v-show 控制“是否显示”,底层通过 display: none 隐藏。转写稿对比后指出:v-show 为真显示,为假隐藏。
怎么做:

html
<p v-if="isShow">v-if 内容</p>
<p v-show="isShow">v-show 内容</p>
<script>
new Vue({ el: '#root', data: { isShow: true } })
</script>

易错点:v-show="isShow" 中 isShow 是实例属性;如果写成 v-show="'isShow'",它会把字符串 isShow 当条件。空字符串、0、undefined 作为判断条件相当于假;非空字符串、数字 1 相当于真。v-show 不会把元素从 DOM 中移除,只是加 display: none。

模板语法与挂载:先理解 Vue 在做什么 ​

为什么需要:Vue 要让我们用声明式方式把 DOM 绑定到实例数据,避免手动操作 DOM。怎么想:模板仍是合法 HTML,浏览器能解析;Vue 在底层把模板编译成虚拟 DOM 渲染函数,再结合响应系统计算最少需要更新什么。怎么做:先引入 lib 下的 vue.js,准备挂载容器,再创建实例。易错点:el 要写选择器字符串,ID 选择器必须带 #。

html
<div id="root">
  <h1>{{ str }}</h1>
</div>
<script src="lib/vue.js"></script>
<script>
new Vue({
  el: '#root',
  data: { str: '万' }
})
</script>

同一实例与多个实例的挂载 ​

为什么需要:要弄清“实例”和“挂载元素”是不是一对一。怎么想:转写稿里先尝试同一个实例挂多个同 ID 元素,结果只渲染第一个满足条件的元素;再试不同实例挂不同元素,可以成功。怎么做:同一实例写 el: '#root' 时,页面中即使有多个 id="root",Vue 也只把第一个作为挂载元素;不同实例分别写 el: '#one'、el: '#two',各管各的容器。易错点:不要以为一个实例能同时挂载多个同选择器元素;重复 ID 本身也不规范。

html
<div id="one"><h1>{{ str }}</h1></div>
<div id="two"><h1>{{ str }}</h1></div>
<script>
new Vue({ el: '#one', data: { str: 'one' } })
new Vue({ el: '#two', data: { str: 'two' } })
</script>

插值表达式:把实例数据放进模板 ​

为什么需要:模板里要显示数据。怎么想:双花括号 {{ }} 是模板语法,会被 Vue 编译;里面可以写实例属性、字符串、数字、对象、方法调用和简单表达式。怎么做:data 里的属性可直接用属性名访问;也可写 {{ 1 }}、{{ 'abc' }}、三元表达式、fn()。易错点:undefined、null 不输出;数组不会像 React 那样直接展开,仍按数组形态显示;对象可以输出;逻辑复杂或重复调用时建议用方法,简单表达式可直接写。

html
<p>{{ name }}</p>
<p>{{ 1 }}</p>
<p>{{ flag ? '男' : '女' }}</p>
<p>{{ fn() }}</p>

转写稿中还演示了方法内 this 指向 Vue 实例,因此 this.str 能取到数据;例如把字符串反转后返回,模板里写 {{ fn() }} 即可渲染结果。

v-text 与 v-html:文本输出和 HTML 解析 ​

为什么需要:有时要输出纯文本,有时要输出带标签的 HTML。怎么想:指令是特殊属性,以 v- 开头;v-text 输出文本,v-html 会把字符串当 HTML 解析。怎么做:v-text="userName" 会去实例中找 userName;v-html="userName" 同样取值,但标签会被浏览器识别。易错点:v-text 会覆盖元素原有内容;值写属性名时不要乱写未定义属性,否则控制台报“属性或方法未定义”;双引号里再套单引号、或用反引号,表示直接输出这个字符串,而不是取实例属性。

html
<p v-text="userName"></p>
<p v-html="userName"></p>

v-if / v-else-if / v-else:条件渲染 ​

为什么需要:根据条件决定元素是否渲染。怎么想:v-if 为真渲染所在元素,为假不渲染;多条件按顺序判断,满足后下面分支不再看。怎么做:可写 v-if、v-else-if、v-else;多条件也可用函数返回结果。易错点:v-else-if、v-else 必须与 v-if 结构上紧邻,中间不要插入没有 v-if 的其他元素,否则编译会异常;多个独立 v-if 会同时判断,可能同时显示多个结果。

html
<p v-if="age > 80">老年</p>
<p v-else-if="age > 40">中年</p>
<p v-else-if="age > 18">青年</p>
<p v-else>少年</p>

template 包裹与 v-show ​

为什么需要:条件渲染多个元素时不想多一层真实 DOM;只想切换显示隐藏时又不想销毁元素。怎么想:template 是包裹标签,不渲染外层;v-show 通过 display 控制显示隐藏。怎么做:<template v-if="isLogin">...</template> 可包多个元素;v-show="isShow" 为真显示,为假隐藏。易错点:template 不能和 v-html、v-text 结合使用;v-show 的空字符串、0、null、undefined 作为判断条件相当于假;v-if 是渲染/不渲染,v-show 是显示/隐藏。转写稿还提到 Vue 1.0 有 v-hide,2.0 已移除,可用 v-show 取反实现隐藏。

html
<template v-if="isLogin">
  <input placeholder="请输入管理员账号">
  <input placeholder="请输入管理员密码">
</template>
<p v-show="isShow">显示或隐藏</p>

从构造函数到实例:先引入 Vue ​

为什么需要:要创建 Vue 实例,必须先让页面拿到 Vue 构造函数;否则 new Vue 不存在。
怎么想:笔记里先通过 <script src="lib/vue.js"></script> 引入核心模块,它提供构造函数 Vue。
怎么做:在脚本中写 const vm = new Vue({ ... }),vm 就是 Vue 实例,构造函数接收一个配置对象。
易错点:路径要写对,笔记中是 lib/vue.js;不要把 Vue 写成普通函数调用,必须用 new。转写稿里“will/lab”是口误,实际是 Vue 和 lib。

配置对象:data 与 methods ​

为什么需要:实例需要保存数据和可复用逻辑,配置对象就是入口。
怎么想:data 放实例数据,类型是对象;methods 放方法,类型也是对象。
怎么做:笔记中示例为:

js
const vm = new Vue({
  data: {
    a: 1,
    b: 2,
    c: { userName: "zhangsan" },
    d: [1, 2, 3]
  },
  methods: {
    fn() {}
  }
});

易错点:data 中对象的属性会作为 vm 的实例属性,例如 vm.a、vm.c.userName;方法建议统一放 methods,不要随意挂到实例外部。

data 与实例属性的同步关系 ​

为什么需要:很多初学者以为 vm.a 和 data.a 是两份数据,实际它们是同一份数据的代理访问。
怎么想:Vue 会把 data 对象的属性代理到实例上,所以改 data.a 会影响 vm.a,改 vm.a 也会影响 data.a。
怎么做:笔记中的调试代码是:

js
const data = { a: 1 };
const vm = new Vue({ data });
data.a = 100;
vm.a = 200;
console.log(vm.a, data.a);

推导过程:先执行 data.a = 100,此时 vm.a 也变为 100;再执行 vm.a = 200,因为访问的是同一份数据,所以 data.a 也变为 200。最终控制台输出 200 200。
易错点:不要误以为最后输出 100 200;同步的关键是“属性代理”,不是复制。转写稿里“想水”应理解为“响应式”:数据变化会驱动视图变化,但本节先抓住实例属性同步。

挂载与多实例:el 的选择 ​

为什么需要:实例要知道把模板渲染到页面哪个容器里。
怎么想:配置项 el 用来指定挂载元素,#root 中的 # 表示 ID 选择器。
怎么做:new Vue({ el: '#root', data: { ... } })。转写稿中做过调试:两个 div 分别设 id="one"、id="two",两个实例分别挂载 #one、#two,页面可以分别渲染,这是“多个实例挂载不同元素”。
易错点:同一个实例如果写 el: 'div',而页面有多个 div,只会把第一个满足条件的元素作为挂载元素,不会同时挂载到所有 div。这就是转写稿中“只会将第一个满足条件的元素作为挂载元素”的结论。

插值与指令初识 ​

为什么需要:数据要显示到模板中,条件要控制元素是否出现。
怎么想:{{ name }} 是插值表达式;v-text 输出文本,v-html 解析 HTML;v-if 控制是否渲染,v-show 用 display:none 隐藏。
怎么做:转写稿中把布尔值从 true 改成 false 观察:v-if 对应元素会从 DOM 中消失;v-show 元素还在,但样式变为隐藏。v-else-if、v-else 必须和 v-if 结构配合使用。
易错点:v-text 不会把字符串当 HTML 解析,v-html 才会;v-else-if/v-else 所在元素之间不要插入无关元素,否则结构容易出错。template 是包裹标签,本身不渲染,转写稿中验证过它不能和 v-html/v-text 直接结合使用,但常和 v-if 等配合。

完整示例代码 ​

html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
	<!--1- 引入核心模块,提供了构造函数Vue	-->
	<script src="lib/vue.js"></script>
</head>
<body>

</body>
<script>
	// 1- vm即是Vue实例。
	// 2- Vue构造函数接收一个配置对象。
	// 3- 配置对象中可以设置data属性(类型是一个对象)
	// 4- data对象的属性会作为vm的实例属性(记住)。
	// 5- 建议将方法放置到methods属性中(类型也是一个对象)
	// const vm = new Vue({
	// 	// 实例中的数据
	// 	data:{
	// 		a:1,
	// 		b:2,
	// 		c:{
	// 			userName:"zhangsan"
	// 		},
	// 		d:[1,2,3]
	// 	},
	// 	// 定义方法
	// 	methods:{
	// 		fn(){
	//
	// 		}
	// 	}
	// });
	// console.log(vm);
	
	
	// 关于data的特点:
	// 1- data中的属性会作为Vue实例中的属性
	// 2- data的属性值发生改变,那么Vue实例中对应的属性值也会发生改变
	// 3- Vue实例中的属性值发生改变,那么data中的属性值也会发生改变。
	const data = {
		a:1
	}
	const vm = new Vue({
		data
	});
	data.a = 100;
	vm.a = 200;
	console.log(vm.a,data.a);
</script>
</html>

挂载到底在解决什么问题 ​

为什么需要:new Vue({...}) 只是创建了一个 Vue 实例,但页面上哪一块 DOM 归它管,必须明确指定。这个“指定作用范围”的动作就是挂载。没有挂载,模板里的 {{str}} 不会被 Vue 编译,数据也不会驱动视图。

怎么想:把 Vue 实例想成一个“编译器 + 数据源”,el 告诉它从哪里开始编译;挂载到的元素及其内部内容,此后就可以称为 Vue 模板。

怎么做:在实例配置里写 el。推荐用 ID 选择器:

js
const vm = new Vue({
  el: "#root",
  data: {
    str: "我现在开始学习Vue,第一步要进行挂载"
  }
});

易错点:el:"body"、el:"html" 不允许;el:".root"、el:"div" 虽然可能选中元素,但不建议,因为选择范围不明确,容易挂错。

el 选择器与“第一个匹配元素” ​

为什么需要:同一个页面可能有多个 div 或多个同类名元素,Vue 必须知道到底挂哪一个。

怎么想:转写稿里反复调试得出一个关键结论:同一个 Vue 实例写 el:"div" 时,只会把第一个满足条件的元素作为挂载元素,而不是把所有 div 都接管。

怎么做:优先写唯一 ID,例如 el:"#root";也可以用 el:document.querySelector("#root") 传入 DOM 元素。不同 Vue 实例可以分别挂到不同元素上,例如一个挂 #one,另一个挂 #two,这是可以的。

易错点:不要指望“一个实例挂多个元素”。同一个实例挂多个同类元素做不到;需要多个实例分别挂载。转写稿里的“相同 Vue 实例挂载到不同元素”实验,最后验证的就是“只取第一个满足条件的元素”。

模板中为什么能直接写属性、this 和 vm ​

为什么需要:模板里要显示数据,如果每次都写很长的实例路径会很麻烦。

怎么想:Vue 会把 data 中的属性代理到实例上,模板作用域里可以直接访问这些属性;同时模板中的 this 指向 Vue 实例。转写稿里的“模块中可以使用 this”应纠正为“模板中可以使用 this”,但不建议依赖它。

怎么做:笔记代码中三种写法:

html
<h1>{{str}}</h1>
<h1>{{this.str}}</h1>
<h1>{{vm.str}}</h1>

前两种分别直接访问 data.str 和通过模板上下文 this.str 访问。注意:代码的 data 里又定义了一个 vm:{str:"vm"},所以 {{vm.str}} 实际取到的是 data.vm.str,输出 vm,并不是外部 const vm 实例。这里要按代码实际结构理解,不能想当然。

易错点:模板里能用 this 不代表推荐写 this;日常直接写 {{str}} 最清晰。若在 data 中定义了与外部实例同名的 vm,模板里的 vm 会优先指向 data.vm,容易混淆。

完整代码与调试过程 ​

转写稿里的调试路径是:先写 el:"#root",再在模板里写 {{str}},刷新看到数据;然后把 el 改成 div 并复制多个 div,发现只有第一个满足条件的元素生效;再分别建两个实例挂 #one、#two,验证“不同实例挂不同元素可以”。这比只背结论更能理解挂载边界。

本节笔记代码如下,保留原代码:

html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
	<script src="lib/vue.js"></script>
</head>
<body>
	<div class="root" id="root">
		<h1>{{str}}</h1>
		<h1>{{this.str}}</h1>
		<h1>{{vm.str}}</h1>
	</div>
</body>
<script>
	// 注意重点:在Vue模板中可以直接使用Vue实例中的属性或方法(不需要使用this,不需要使用this)
	// 注意重点:模块中可以使用this(不建议),说明模块所处的环境上下文中的this指向的是Vue实例。
	// 挂载(Vue实例挂载):指定Vue实例应用的范围(元素)
	const vm = new Vue({
		// 将ID为root的元素作为Vue实例挂载的元素(挂载的元素自此可以称为Vue模板)
		// el:document.querySelector("#root"),
		
		// 将ID为root的元素作为Vue实例挂载的元素(挂载的元素自此可以称为Vue模板)
		// el:"#root",
		
		// 将class为root的元素作为Vue实例挂载的元素( 不建议)
		// el:".root",
		
		// 将标签名字为div的元素作为Vue实例挂载的元素( 不建议)
		// el:"div",
		
		// el:"body",// 不允许
		// el:"html",// 不允许
		data:{
			str:"我现在开始学习Vue,第一步要进行挂载",
			vm:{
				str:"vm"
			}
		}
	})
</script>
</html>

易错点清单 ​

  1. el 写 #root 不要漏掉 #,转写稿里“井号代表 ID”就是提醒这一点。
  2. 不要把 el:"body"、el:"html" 当作挂载点。
  3. 一个实例只接管第一个匹配元素,不要用同类选择器做“批量挂载”。
  4. 模板里直接写 {{str}} 最稳;{{this.str}} 能工作但不建议;{{vm.str}} 要看清 data 中是否已有 vm 对象。
  5. 转写稿中的“差值表达式”应纠正为“插值表达式”,“微钢/违装衣服”等是口误或同音字,实际是 v- 指令、v-if 等,本节先牢牢掌握挂载边界。

本节要解决的问题 ​

为什么需要:初学 Vue 时,很容易把 el 当成“批量选择器”,以为写 el:"div" 就能让页面上所有 div 都变成 Vue 的挂载点,于是两个 div 里的 {{str}} 都应该显示同一个数据。本节就是要澄清:一个 Vue 实例到底能不能同时挂载到多个元素上。

怎么想:el 本质上是给 Vue 指定“根挂载元素”的选择器。Vue 会按选择器去找元素,但一个实例只认一个根挂载点;当选择器匹配到多个元素时,它只会取第一个满足条件的元素,而不是把匹配到的元素全部接管。

怎么做:先看本节笔记中的原始示例:

html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
	<script src="lib/vue.js"></script>
</head>
<body>
	<div>
		<h1>{{str}}</h1>
	</div>
	<div>
		<h1>{{str}}</h1>
	</div>
</body>
<script>
	// 只会将第一个符合条件的元素作为挂载元素
	new Vue({
		el:"div",
		data:{
			str:"one"
		}
	})
</script>
</html>

易错点:不要把 el:"div" 理解成“所有 div 都挂载”。这里的 div 是选择器,页面中有两个 div,Vue 只把第一个当作挂载元素。第二个 div 不会被这个实例编译,里面的 {{str}} 也不会按这个实例的数据渲染。

复现现象:两个 div 只渲染第一个 ​

为什么需要:只看结论容易记混,必须通过调试看到“只生效第一个”的现象,才能理解实例和挂载点是一对一关系。

怎么想:转写稿中的调试思路是:先写一个容器,例如 id="root",用 el:"#root" 能正常渲染;然后把容器复制一份,再把 el 改成 "div",刷新页面观察两个 div 的表现。此时两个 div 都写了 {{str}},但只有第一个被 Vue 接管并显示 one,第二个仍然是模板原样或未被该实例渲染。

怎么做:按笔记代码运行后,重点看两个 div 中的 h1。第一个会显示 one;第二个不会跟着变成 one,因为它不是这个 Vue 实例的挂载根元素。控制台通常不会因为这个写法直接报错,所以不能只靠“有没有报错”判断挂载是否成功。

易错点:看到第二个没渲染,不要先怀疑 data 写错。这里 data 没有问题,问题在 el 匹配到了多个元素,而实例只取第一个。调试时应先检查“这个实例到底挂到了哪个元素上”。

为什么相同实例不能挂载多个元素 ​

为什么需要:理解 Vue 实例的边界。一个 new Vue({...}) 创建的是一个实例,el 指定的是它的根挂载元素;实例的模板编译、数据绑定都围绕这个根展开。

怎么想:转写稿里明确总结:“只会将第一个满足条件的元素作为你的挂载元素”。也就是说,相同 Vue 实例挂载到不同元素这件事做不到。不是说数据不能共享,而是“一个实例同时接管多个根元素”这个动作不成立。

怎么做:如果业务上确实有两个区域都要受 Vue 控制,正确方向不是让一个实例硬挂多个元素,而是拆成两个实例,或者后续用组件组织。就本节而言,先掌握“一个实例一个挂载根元素”。

易错点:不要复制多个 div 后仍写 el:"div",然后以为两个都会生效。也不要因为第二个没生效就去改 data 里的 str,那不会改变挂载点的选择结果。

正确做法:不同实例挂载不同元素 ​

为什么需要:当页面上确实有多个独立区域时,需要让每个区域有明确的挂载点,避免选择器匹配到多个元素后只取第一个。

怎么想:转写稿中的做法是给两个 div 分别加唯一 id,例如一个 id="one",一个 id="two";然后写两个 Vue 实例,分别用 el:"#one" 和 el:"#two" 挂载。这样两个实例各管一个根元素,数据也可以各自独立。

怎么做:可写成下面的结构:

html
<div id="one">
	<h1>{{str}}</h1>
</div>
<div id="two">
	<h1>{{str}}</h1>
</div>

<script>
	new Vue({
		el: "#one",
		data: {
			str: "one"
		}
	})

	new Vue({
		el: "#two",
		data: {
			str: "two"
		}
	})
</script>

运行后,上面显示 one,下面显示 two。这就验证了:相同实例不能挂多个元素,但不同实例可以分别挂载不同元素。

易错点:el 里的 ID 选择器要写 #;页面中 id 要唯一;两个实例的 data 要分别写清楚。不要把 el:"one" 当成 ID 选择器,ID 选择器应写 "#one"。

本节结论与检查方法 ​

为什么需要:把现象上升为可复用的判断规则,后面写多个 Vue 区域时才不会反复踩坑。

怎么想:记住两条:第一,el:"div" 这类选择器匹配到多个元素时,只把第一个满足条件的元素作为挂载元素;第二,同一个 Vue 实例不能同时挂载到多个不同元素上,多个区域应使用多个实例或组件化组织。

怎么做:检查时先看 el 写的是什么选择器,再看页面上匹配到了几个元素,最后确认实际渲染的是不是第一个。若需要两个区域都渲染,就给不同根元素不同 id,分别 new Vue。

易错点:把“第一个满足条件”误记成“全部满足条件”;把“不同实例挂不同元素”误写成“相同实例挂不同元素”;选择器写错导致根本没挂上。

需求:同一页面里让两块内容各自显示不同数据 ​

为什么需要:实际页面经常不是只有一个根容器,比如左侧导航和右侧内容区、两个独立卡片、两个互不影响的计数器。如果所有内容都塞进同一个 Vue 实例,数据和模板会耦合在一起;把不同区域交给不同 Vue 实例管理,结构更清楚。

怎么想:先明确“实例”和“挂载元素”是一对一关系。一个 new Vue({ el: ... }) 只负责一个 el 指定的容器;如果页面上有两个容器,就准备两个实例。每个实例有自己的 data,模板里写 {{ str }} 时,会到“当前实例”的 data 里找 str。

怎么做:下面保留本节笔记代码。注意转写稿里“will / lab / EL”等是口述谐音或大小写误写,实际应写 Vue、lib/vue.js、el。

html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
	<script src="lib/vue.js"></script>
</head>
<body>
<div id="one">
	<h1>{{str}}</h1>
</div>
<div id="two">
	<h1>{{str}}</h1>
</div>
</body>
<script>
	// 同一个页面,支持多个实例挂载至不同元素中。
	new Vue({
		el:"#one",
		data:{
			str:"one"
		}
	})
	new Vue({
		el:"#two",
		data:{
			str:"two"
		}
	})
</script>
</html>

易错点:el:"#one" 里的 # 不能漏,# 表示 id 选择器;两个容器 id 不能重复;两个实例的 data 是彼此独立的,上面实例的 str 是 "one",下面实例的 str 是 "two",不会互相覆盖。

挂载容器:el 指向谁,模板范围就是谁 ​

为什么需要:Vue 需要知道“从哪一块 DOM 开始接管”。el 就是挂载点。转写稿中反复强调“指定一个元素作为挂载的容器”“井号代表 id”,目的就是让实例知道自己编译哪一块模板。

怎么想:先写容器,再写实例。容器里放 {{ str }},实例里用 el 找到容器,用 data 提供 str。浏览器先解析 HTML,Vue 再把 el 范围内的插值编译成数据。

怎么做:先写 <div id="one"><h1>{{str}}</h1></div>,再写 new Vue({ el:"#one", data:{ str:"one" } })。刷新后,#one 里的 h1 显示 one。同理复制一份,把 id 改成 two,把 el 改成 "#two",把 data.str 改成 "two",下面显示 two。转写稿的调试过程就是:先做一个容器,验证能显示;再复制容器和实例,分别改 id、el、data,刷新确认上下都生效。

易错点:模板插值必须写在 el 挂载的容器内部;el 写错 id,页面不会按预期渲染;data 里没有 str,模板里的 {{str}} 就取不到值。不要把 el 写成 "one",那会被当作标签名选择器,而不是 id。

关键结论:不同实例可以挂不同元素,同一实例不要试图挂多个元素 ​

为什么需要:初学者容易把“多个容器”误解成“一个实例写多个 el”或“一个实例同时管两块”。转写稿专门做了对照实验:同一个实例换到不同元素,做不到;不同实例挂到不同元素,可以。

怎么想:Vue 实例的挂载点是单值配置,不是数组。转写稿里说,如果让选择器满足多个元素,“只会将第一个满足条件的元素作为挂载元素”。所以正确思路不是让一个实例管两个容器,而是“一个容器一个实例”。

怎么做:按笔记写两个 new Vue,分别 el:"#one" 和 el:"#two"。运行后检查:第一个 h1 是 one,第二个 h1 是 two。转写稿中的验证话术是“上面这个 H1 呈现出来的是 one,下面这个 H1 呈现出来的是 two”,说明两个实例各自工作。

易错点:不要写两个 el 字段,也不要把 el 写成 "#one,#two" 期待一个实例管两块;不要复制实例后忘记改 data.str,否则两个区域可能显示同一个值;不要把两个容器写成相同 id,否则选择器只会命中第一个,第二个实例行为就不符合预期。

小结 ​

本节核心不是复杂语法,而是建立“实例与挂载元素一对一”的模型:页面可以有多块区域,每块区域用独立 Vue 实例挂载;el 用 #id 精确指定容器;data 为当前实例提供数据;模板中的 {{str}} 只在当前实例范围内取值。按转写稿的调试路径:先单容器验证,再复制成两个容器,分别改 id、el、data,刷新对照上下显示结果,就能稳定复现“不同 Vue 实例挂载到不同元素”的效果。

课堂画面 ​

课堂画面 1

课堂画面 2

课堂画面 3

课堂画面 4

课堂画面 5

课堂画面 6

代码示例 ​

示例一:Vue 实例与挂载 ​

html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Vue 实例与挂载</title>
	<!-- 开发环境版本,包含完整的警告和调试模式 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
	<!-- 1. el 指定的元素就是 Vue 实例的挂载点,也就是"Vue 模板" -->
	<div id="root">
		<h1>{{str}}</h1>
		<h1>{{this.str}}</h1>
	</div>

	<!-- 2. 同一个选择器匹配到多个元素时,只会挂载第一个 -->
	<div class="item"><h1>{{str}}</h1></div>
	<div class="item"><h1>{{str}}</h1></div>

	<!-- 3. 一个页面允许不同实例挂载到不同元素 -->
	<div id="one"><h1>{{str}}</h1></div>
	<div id="two"><h1>{{str}}</h1></div>
</body>
<script>
	// data 中的属性会成为实例属性,且双向同步
	const data = { a: 1 };
	const vm = new Vue({ data });
	data.a = 100;
	vm.a = 200;
	console.log(vm.a, data.a); // 200 200

	// 挂载:el 可以是选择器字符串,也可以是 DOM 元素
	new Vue({
		el: '#root',
		data: {
			str: '我现在开始学习Vue,第一步要进行挂载'
		}
	});

	// el 匹配到多个 .item,只有第一个被挂载,第二个原样输出 {{str}}
	new Vue({
		el: '.item',
		data: { str: 'one' }
	});

	// 多个实例分别挂载到不同元素
	new Vue({ el: '#one', data: { str: 'one' } });
	new Vue({ el: '#two', data: { str: 'two' } });
</script>
</html>

关键行与易错点

  • new Vue({...}) 的返回值就是 vm 实例,构造函数的参数是一个配置对象,常用 data、methods、el。
  • data 里的属性会直接成为实例属性,并且双向同步:改 data.a 或改 vm.a,两边值都变(最后打印两个 200 就是这个原因)。
  • 模板里可直接写 {{str}},不需要 this;写 {{this.str}} 也能渲染,但不建议。
  • el 写成选择器字符串时等价于 document.querySelector,只取第一个满足条件的元素,所以示例二段里第二个 .item 保持原样。
  • el: "body"、el: "html" 不允许;el: "div"、el: ".item" 这类宽泛选择器能跑但不建议,因为匹配范围不可控。

示例二:插值表达式与 v-text / v-html ​

html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>模板语法与指令</title>
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
	<div id="app">
		<p>{{ name }}</p>
		<p>{{ str }}</p>
		<p>{{ 1 }}</p>
		<p>{{ bol }}</p>
		<p>{{ fn() }}</p>
		<p>{{ arr }}</p>
		<p>{{ obj }}</p>
		<p>{{ null }} | {{ undefined }}</p>
		<p>{{ sex === 1 ? '男' : '女' }}</p>
		<p>{{ str.split('').reverse().join('') }}</p>

		<hr>
		<!-- 值是"属性名"的字符串,会去实例中找同名属性 -->
		<p v-text="userName"></p>
		<p v-html="userName"></p>

		<!-- 值里再套一层引号,就直接输出这段字符串,不去实例里找 -->
		<p v-text="'userName'"></p>

		<!-- 唯一区别:v-html 会解析 HTML 标签,v-text 只当纯文本 -->
		<p v-text="link"></p>
		<p v-html="link"></p>
	</div>
</body>
<script>
	new Vue({
		el: '#app',
		data: {
			name: 'zhangsan',
			str: '超级魔法师',
			bol: true,
			arr: [1, 2, 3, 4],
			obj: { userName: '张三' },
			sex: 1,
			userName: '我是一个字符串',
			link: '<a href="http://www.baidu.com">百度</a>'
		},
		methods: {
			fn() {
				// 方法里的 this 指向 Vue 实例
				return this.str.split('').reverse().join('');
			}
		}
	});
</script>
</html>

关键行与易错点

  • 插值表达式支持:字符串、数字、布尔、对象、方法调用、三元表达式、字符串反转等表达式;methods 中的方法也会被挂到实例上,模板里可直接 fn() 调用。
  • null 和 undefined 不会做任何输出,页面只剩 |。
  • 数组 {{ arr }} 输出的是 [1,2,3,4] 原样文本,不会自动展开成元素(这点和 React 不同)。
  • 指令值是"属性名"字符串:v-text="userName" 会去实例找 userName;若实例里没有这个属性,控制台会报 Property or method "xxx" is not defined。
  • 想直接输出字符串本身,就要在双引号里再套单引号:v-text="'userName'"(等价于反引号写法),此时不会去实例里查。
  • v-text 与 v-html 唯一区别就是是否解析 HTML:v-text 输出文本、标签不生效;v-html 输出会被浏览器识别,a 标签可点击跳转。另外两者都会覆盖元素原有内容。

示例三:v-if / v-else-if / v-else、template、v-show ​

html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>条件渲染</title>
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
	<div id="app">
		<!-- 1. 多条件:v-if / v-else-if / v-else 必须紧挨着写 -->
		<p v-if="age > 80">老年</p>
		<p v-else-if="age > 40">中年</p>
		<p v-else-if="age > 28">壮年</p>
		<p v-else-if="age > 18">青年</p>
		<p v-else-if="age > 12">少年</p>
		<p v-else-if="age > 6">儿童</p>
		<p v-else>婴儿</p>

		<hr>
		<!-- 2. template 只是包裹标签,本身不渲染,可用于 v-if 分支 -->
		<template v-if="isLogin">
			<input type="text" placeholder="请输入管理员账号">
			<input type="password" placeholder="请输入管理员密码">
		</template>
		<p v-else>未登录</p>

		<hr>
		<!-- 3. v-if 与 v-show 的区别 -->
		<p v-if="isShow">v-if 控制</p>
		<p v-show="isShow">v-show 控制</p>
	</div>
</body>
<script>
	new Vue({
		el: '#app',
		data: {
			age: 100,       // 改成 60 / 19 / 3 观察分支切换
			isLogin: false, // 改成 true 观察 template 分支
			isShow: true    // 改成 false 观察 v-if 与 v-show 的区别
		}
	});
</script>
</html>

关键行与易错点

  • v-if 的值是布尔表达式:成立则渲染该元素,不成立则不渲染(元素在 DOM 中根本不存在);v-else-if、v-else 的值写法与 v-if 相同,v-else 后面不写值。
  • v-else-if / v-else 必须紧跟在 v-if 或上一个 v-else-if 之后,中间不能插入其它元素,否则会编译报错或分支错乱。把几个 v-else-if 的 v-else 去掉后,age=100 会同时命中所有条件、全部渲染——这是最典型的错误。
  • template 是包裹标签,自身不渲染任何标签,很适合给一组元素加同一个 v-if,但 template 上不能和 v-text / v-html 结合使用(没效果)。
  • v-show 与 v-if 值相同,但 v-show 是通过 display: none 控制显示隐藏,元素始终在 DOM 中;v-if 是真正销毁/重建。要频繁切换用 v-show。
  • v-show 的值会做真假判断:空字符串、0、null、undefined 都相当于 false,非空字符串、数字 1 相当于 true。

常见错误 ​

  1. el 写成 "root",页面原样显示 {{str}} 现象:控制台无报错,但插值原封不动出现在页面上,Vue 开发者工具里看不到根实例。 原因:el 接收的是 CSS 选择器字符串或真实 DOM 元素,"root" 被当成标签名去找 <root>,找不到就静默不挂载。 修法:el: "#root";或 el: document.querySelector("#root")。挂载失败时优先检查这里。

  2. el 用 class 或标签名,第二个同类容器不渲染 现象:页面里两个 <div> 都写了 {{str}},只有第一个变成真实数据,第二个仍是花括号。 原因:选择器匹配到多个元素时,Vue 只取第一个命中项作为挂载点,不会批量挂载。 修法:每个实例绑定唯一 id;一个实例只对应一个容器,多个容器就多写几个 new Vue。

  3. 模板里写 {{this.str}}、{{vm.str}},或把 if/for 塞进插值 现象:有时能渲染,有时报 xxx is not defined;写语句时直接编译报错。 原因:模板表达式的作用域就是实例本身,this 可用但不该用;且插值只接受表达式,不接受语句。 修法:直接写 {{str}};多分支逻辑抽到 methods 里 {{format(x)}},或退化成三元表达式。

  4. 指令值引号用错:v-text="张三" 报未定义,v-show="'isShow'" 永远显示 现象一:控制台报 Property or method "张三" is not defined。 现象二:明明数据是 false,元素却始终可见。 原因:指令值默认按表达式解析,张三 被当作变量名去实例上找;加了一层引号后 'isShow' 变成非空字符串,恒为真值。 修法:要取数据写 v-text="userName";要输出字面量写 v-text="'张三'";v-show 只写变量名,不加内层引号。

  5. v-if / v-else-if / v-else 链中间夹了别的元素 现象:条件判断整体失效,多个分支同时渲染,或编译期报错。 原因:v-else-if / v-else 必须与紧邻的前一个 v-if 配对,中间插入任何无指令元素都会断链。 修法:删除中间元素;确实需要分组时用 <template v-if> 包裹整段,而不是在分支之间插内容。

  6. 把 v-show / v-html / v-text 写在 <template> 上 现象:页面什么都不显示,控制台也不报错,排查很久找不到原因。 原因:<template> 是编译期包裹标签,本身不产生真实 DOM 节点;v-show 靠 display 控制显隐、v-html 需要真实节点承载,都无处落脚。 修法:v-show 换成 v-if(可以作用在 <template> 上),或把指令下移到内层真实元素上。

  7. 改了数据视图不更新:vm.arr[0] = x、vm.obj.newKey = x 现象:控制台打印数据已变,页面上还是旧值,且没有任何警告。 原因:Vue 2 通过 Object.defineProperty 劫持已有属性,数组下标赋值和对象新增属性都不在劫持范围内。 修法:数组用 splice / 整体替换,对象用 Vue.set(vm.obj, 'newKey', x) 或 vm.$set;改完仍不生效时先看是不是这个原因,而不是怀疑模板写错。

  8. 用生产版 CDN 调试,警告全消失就以为没问题 现象:本地引入 vue@2(生产版)后,模板语法错误不再提示,问题被掩盖到线上才暴露。 原因:生产版移除了警告与调试模式,只保留运行时行为。 修法:开发阶段固定用 vue.js(开发版),上线再换 vue.min.js / 生产 CDN。

练习 ​

  1. 挂载纠错:给出一段代码——el: "body"、两个 <div class="box">、模板里写 {{this.msg}}、v-text="msg" 但 data 里只有 message。要求找出全部问题并改到正常渲染,同时说明每处为什么错。

  2. 同数据两种渲染:用一个 age 变量,分别用「三元表达式」「methods 方法」「v-if 指令链」三种方式渲染「老年 / 中年 / 青年 / 少年 / 儿童」。写完后对比:哪种在模板里最容易维护,哪种在 DOM 上更省节点。

  3. v-if 与 v-show 对照实验:做一个「登录 / 未登录」切换。两个版本分别用 v-if 和 v-show 实现,用开发者工具观察切换时元素是消失还是仅 display: none,并记录页面初次加载时两者的差异。

  4. v-html 与 v-text 安全练习:把 "<a href='https://www.baidu.com'>百度</a>" 分别用 v-html 和 v-text 渲染,观察结果;再假设这段内容来自用户输入框,说明为什么不能直接交给 v-html。

  5. 多实例拆分:一个页面放三个区块(头部、列表、侧栏),要求用三个独立 Vue 实例分别挂载,各自维护自己的 data。做完后思考:如果三个区块需要共享同一份数据,这种拆分方式会带来什么问题。

原视频对照 ​

#视频时长
1不同Vue实例挂载到不同元素04:16
2模板中的插值表达式16:38
3v-html v-text18:05
4v-if v-else-if v-else19:02
5补充-template06:37
6v-show10:02

小结 ​

  1. 挂载是整个流程的入口,el 写错时 Vue 往往不报错只是不干活,所以任何"页面没反应"的问题,第一步永远是确认实例有没有挂上、挂在哪个元素上。
  2. 一个实例对应一个容器,容器用唯一 id;class 和标签名选择器属于"能跑但埋雷"的写法,不要用。
  3. 模板里的一切表达式都在实例作用域内求值,写之前先问自己:这个名字在 data / methods 里存在吗?
  4. 指令的值分两种语义——表达式(默认)和字面量(额外加引号),引号层级是新手最高频的翻车点,写指令时先数清引号。
  5. v-if 与 v-show 不是二选一的美学问题,而是渲染成本 vs 切换成本的取舍;同时记住 v-if 支持 <template>,v-show 不支持。
  6. Vue 2 的响应式是有边界的,数组下标和对象新增属性是已知盲区,遇到"数据变了视图没变",先怀疑赋值方式而不是模板。
  7. 开发期一律用带警告的版本,把控制台当成第一手反馈;没有警告不等于没有问题,可能只是你把警报器关了。
  8. 这一节的所有指令与插值,本质都是在解决同一件事:用声明式写法描述"数据长什么样",把 DOM 操作交给框架——后面学组件、计算属性、v-for 时,这条主线不会变。