Vue2手录02-指令
一、Vue2指令概述
什么是Vue指令
Vue指令是带有 v-
** 前缀** 的特殊HTML属性,用于扩展HTML的原生功能,实现“数据与视图的动态关联”。其核心作用是将Vue实例中的数据(data
)或方法(methods
)映射到页面DOM,无需手动操作DOM即可实现视图更新。
- 核心特点:
- 指令属性的值支持 JavaScript执行环境(可写变量、表达式);
- 数据变化时,指令会自动触发视图更新(响应式);
- 不同指令对应不同场景(如渲染内容、绑定属性、监听事件)。
二、内容渲染指令(渲染数据到页面)
内容渲染指令用于将Vue实例中的数据渲染到HTML元素的“内容区域”,核心包括 插值表达式、v-html
、v-text
三种,需重点区分“是否识别HTML标签”及安全风险。
三种指令对比与用法
指令/语法 | 核心功能 | 是否识别HTML标签 | 安全风险 | 适用场景 |
---|---|---|---|---|
插值表达式 {{ }} | 渲染纯文本数据 | ❌ 不识别 | 无 | 大部分纯文本场景(如标题、描述) |
v-text="变量" | 等价于插值表达式,渲染纯文本 | ❌ 不识别 | 无 | 需覆盖元素全部内容的纯文本场景 |
v-html="变量" | 渲染含HTML标签的内容 | ✅ 识别 | ✅ 存在XSS风险 | 仅渲染“可信来源”的HTML(如后端过滤后的富文本) |
详细用法与示例
插值表达式({{ }}
,最常用)
- 语法:
{{ 变量/JS表达式 }}
支持任意JS表达式(算术运算、三元判断、字符串拼接),但不支持JS语句(如if-else
、for
循环)。 - 示例:
<div id="app">{{ msg }} <!-- 渲染data中的msg:"Hello Vue" -->{{ num + 1 }} <!-- 表达式:渲染3(若num=2) -->{{ isShow ? "显示内容" : "隐藏内容" }} <!-- 三元判断:根据isShow动态切换 -->{{ "<h1>标题</h1>" }} <!-- 不识别HTML:渲染为纯文本"<h1>标题</h1>" -->
</div>
<script>new Vue({el: "#app",data: { msg: "Hello Vue", num: 2, isShow: true }});
</script>
v-text
指令(纯文本渲染,少用)
- 语法:
v-text="变量/表达式"
功能完全等价于插值表达式,但会覆盖元素内的所有原有内容(插值表达式可混合静态文本,更灵活)。 - 示例:
<!-- 等价于 <div>{{ msg }}</div> -->
<div v-text="msg"></div>
<!-- 无法混合静态文本,需手动拼接:等价于 <div>"欢迎 " + msg</div> -->
<div v-text="'欢迎 ' + msg"></div>
v-html
指令(HTML渲染,慎用)
- 语法:
v-html="变量"
会将变量中的HTML标签解析并渲染(如<h1>
会显示为标题),但存在严重XSS安全风险(攻击者可注入恶意脚本)。 - 使用原则:
- 仅渲染“可信来源”的HTML(如后端通过
DOMPurify
过滤后的富文本); - 绝对禁止用于渲染用户输入的内容(如评论、昵称、表单提交内容)。
- 仅渲染“可信来源”的HTML(如后端通过
- 示例:
<div id="app"><!-- 若msg = "<h1>Vue指令</h1>",会渲染为一级标题 --><div v-html="msg"></div>
</div>
三、动态属性绑定指令(v-bind
)
v-bind
用于将Vue数据动态绑定到HTML元素的属性(如id
、src
、href
、class
等),实现“属性值随数据变化”。
基本语法与简写
- 完整语法:
v-bind:属性名="变量/表达式"
- 简写语法:
:属性名="变量/表达式"
(省略v-bind
,推荐使用) - 核心规则:
- 引号内支持JS执行环境(可写变量、表达式);
- 需动态变化的属性才用
v-bind
,静态属性直接写(如id="fixed-id"
,无需v-bind
)。
常见应用场景与示例
绑定基础属性(src
、href
、id
)
- 示例1:动态切换图片(绑定
src
)
<div id="app"><!-- 图片src随imgUrl变化,修改imgUrl可切换图片 --><img :src="imgUrl" alt="动态图片" width="300">
</div>
<script>new Vue({el: "#app",data: {// 初始图片地址,可通过代码修改(如this.imgUrl = "新地址")imgUrl: "https://v2.cn.vuejs.org/images/logo.png"}});
</script>
- 示例2:动态跳转链接(绑定
href
)
<a :href="linkUrl">跳转到Vue2官网</a>
<script>new Vue({el: "#app",data: { linkUrl: "https://v2.cn.vuejs.org/" }});
</script>
2. 多属性绑定
单个元素可同时绑定多个动态属性,且可与内容渲染指令(如{{ }}
)共存。
- 示例:
<div id="app"><!-- 同时绑定id、src、title,内容用插值表达式 --><img :id="imgId" :src="imgUrl" :title="imgTitle" alt="多属性绑定"><p>{{ imgDesc }}</p>
</div>
<script>new Vue({el: "#app",data: {imgId: "vue-logo",imgUrl: "https://v2.cn.vuejs.org/images/logo.png",imgTitle: "Vue2 Logo",imgDesc: "这是Vue2的官方Logo"}});
</script>
3. 错误示范与避坑
- ❌ 错误:
v-bind:id="'fixed-id'"
引号内加单引号会将值固定为"fixed-id"
,失去动态性,等同于静态id="fixed-id"
。 - ✅ 正确:
id="fixed-id"
(静态属性直接写)或:id="dynamicId"
(动态属性绑定变量)。
3.3 核心编程思想
v-bind
的设计体现了Vue的核心思想:“谁要变,就把谁定义成变量”,对比jQuery的差异如下:
对比维度 | jQuery(DOM驱动) | Vue(数据驱动) |
---|---|---|
实现方式 | 手动查找DOM → 修改属性(如$('#img').attr('src', '新地址') ) | 定义变量 → 绑定属性 → 修改变量(如this.imgUrl = "新地址" ) |
代码复杂度 | 需关注DOM查找和操作细节 | 仅关注数据变化,无需操作DOM |
可维护性 | DOM操作与业务逻辑混杂 | 数据与视图分离,结构清晰 |
四、特殊属性绑定(class
与style
)
class
(样式类)和style
(内联样式)是HTML中常用的样式属性,Vue对它们提供了特殊的绑定语法(支持字符串、数组、对象三种形式),满足不同样式动态控制场景。
4.1 class
动态绑定(重点)
class
绑定用于动态添加/移除样式类,三种形式对应不同场景,核心是通过“变量的变化”控制类的存在与否。
三种绑定形式对比
绑定形式 | 语法 | 核心特点 | 适用场景 |
---|---|---|---|
字符串形式 | :class="类名变量" | 变量值为单个类名字符串,仅支持一个动态类 | 单个样式类的动态切换(如“激活/未激活”) |
数组形式 | :class="[类名1, 类名2, 变量]" | 支持多个静态类+动态类,类名直接写字符串 | 多个样式类的组合(如基础样式+动态状态类) |
对象形式 | :class="{ 类名1: 布尔值, 类名2: 布尔值 }" | 布尔值控制类是否生效(true 存在,false 移除) | 多个样式类的独立开关控制(如“选中+禁用”) |
详细示例
1. 字符串形式(单个动态类)
<style>.active { color: red; font-weight: bold; }
</style>
<div id="app"><!-- 当isActive为true时,添加active类;为false时移除 --><button :class="activeClass" >点击切换状态</button>
</div>
<script>new Vue({el: "#app",data: { activeClass: "active" }, // 初始添加active类methods: {toggleClass() {// 点击切换类(也可直接修改布尔值控制,见对象形式)this.activeClass = this.activeClass === "active" ? "" : "active";}}});
</script>
2. 数组形式(多个类组合)
<style>.base-btn { padding: 8px 16px; border: 1px solid #ccc; }.active { background: blue; color: white; }.disabled { opacity: 0.5; cursor: not-allowed; }
</style>
<div id="app"><!-- 静态类base-btn + 动态类active/disabled(由变量控制) --><button :class="[ 'base-btn', activeClass, disabledClass ]">{{ btnText }}</button>
</div>
<script>new Vue({el: "#app",data: {activeClass: "active", // 动态添加激活类disabledClass: "", // 初始不禁用btnText: "提交"}});
</script>
3. 对象形式(布尔值控制类)
最灵活的形式,通过布尔值独立控制每个类的生效状态,适合“多状态切换”场景。
<style>.active { background: blue; color: white; }.disabled { opacity: 0.5; cursor: not-allowed; }
</style>
<div id="app"><!-- active类:isActive为true时生效;disabled类:isDisabled为true时生效 --><button :class="{ active: isActive, disabled: isDisabled }"@click="toggleStatus" <!-- 后续事件绑定指令,先预告 -->>{{ isActive ? "已激活" : "未激活" }}</button>
</div>
<script>new Vue({el: "#app",data: { isActive: false, isDisabled: false },methods: {toggleStatus() {this.isActive = !this.isActive; // 切换激活状态this.isDisabled = this.isActive; // 激活时禁用按钮}}});
</script>
4.2 style
动态绑定(内联样式)
style
绑定用于动态设置内联样式(直接写CSS属性),同样支持三种形式,核心是“CSS属性名的命名规则”。
关键前提:CSS属性名的两种写法
- 驼峰命名法(推荐):Vue支持直接写驼峰形式,无需引号(如
backgroundColor
、fontSize
); - 短横线命名法(需引号):若用HTML原生的短横线形式,需用引号包裹(如
'background-color'
、'font-size'
)。
三种绑定形式对比
绑定形式 | 语法 | 核心特点 | 适用场景 |
---|---|---|---|
字符串形式 | :style="样式字符串" | 需符合CSS语法,维护性差 | 简单且固定的内联样式(极少用) |
对象形式 | :style="{ CSS属性: 变量, ... }" | 单个样式对象,属性与值一一对应 | 大部分动态内联样式场景(常用) |
数组形式 | :style="[ 样式对象1, 样式对象2 ]" | 多个样式对象合并,相同属性后者覆盖 | 样式对象复用(如基础样式+动态样式) |
详细示例
1. 对象形式(常用)
<div id="app"><!-- 驼峰命名:backgroundColor;短横线命名:'font-size'(需引号) --><p :style="{ backgroundColor: bgColor, 'font-size': fontSize + 'px', color: textColor }">动态内联样式</p>
</div>
<script>new Vue({el: "#app",data: {bgColor: "#f5f5f5", // 背景色fontSize: 16, // 字体大小(需拼接单位)textColor: "#333" // 文字颜色}});
</script>
2. 数组形式(样式复用)
<div id="app"><!-- 合并baseStyle(基础样式)和dynamicStyle(动态样式) --><div :style="[ baseStyle, dynamicStyle ]">合并多个样式对象</div>
</div>
<script>new Vue({el: "#app",data: {// 基础样式(固定)baseStyle: { padding: "10px", border: "1px solid #eee" },// 动态样式(可修改)dynamicStyle: { backgroundColor: "#fff", color: "#2c3e50" }}});
</script>
五、动态属性名与数组展开语法
5.1 动态属性名(中括号语法)
当属性名本身需要动态变化时(而非属性值),可使用“中括号语法”,将属性名定义为变量。
- 语法:
:[属性名变量]="属性值"
- 注意事项:仅适用于
v-bind
绑定(含class
/style
),字符串形式不支持。 - 示例:动态切换绑定的属性(如
src
/href
)
<div id="app"><!-- 属性名由attrName变量控制:可能是src或href --><element :[attrName]="attrValue"></element><button @click="switchAttr">切换属性</button>
</div>
<script>new Vue({el: "#app",data: {attrName: "src", // 初始属性名:srcattrValue: "https://v2.cn.vuejs.org/images/logo.png" // 初始值:图片地址},methods: {switchAttr() {if (this.attrName === "src") {this.attrName = "href"; // 切换属性名为hrefthis.attrValue = "https://v2.cn.vuejs.org/"; // 切换值为链接} else {this.attrName = "src";this.attrValue = "https://v2.cn.vuejs.org/images/logo.png";}}}});
</script>
5.2 数组展开语法(...
)
数组展开语法(ES6特性)用于合并多个数组或对象,在class
/style
绑定中可实现“样式复用”。
- 核心作用:将数组/对象中的元素“展开”为单个项,避免手动拼接。
- 注意事项:
- 展开后需保证数据仍为响应式(避免直接引用其他
data
属性导致响应式失效); - 优先用于
style
绑定(class
绑定数组形式已足够灵活)。
- 展开后需保证数据仍为响应式(避免直接引用其他
- 示例:合并样式对象
<div id="app"><!-- 展开baseStyle和themeStyle,合并为一个样式对象 --><div :style="[ ...baseStyle, ...themeStyle ]">展开语法合并样式</div>
</div>
<script>new Vue({el: "#app",data: {// 基础样式(复用)baseStyle: { padding: "15px", margin: "10px", border: "1px solid #ddd" },// 主题样式(动态切换)themeStyle: { backgroundColor: "#42b983", color: "white" }}});
</script>
六、事件绑定指令(v-on
,补充核心内容)
原始笔记在“知识小结”中提及v-on
,但内容不足,此处补充完整——v-on
用于监听DOM事件(如点击、输入、鼠标移动),并触发Vue实例中的方法。
6.1 基本语法与简写
- 完整语法:
v-on:事件名="方法名/事件处理逻辑"
- 简写语法:
@事件名="方法名/事件处理逻辑"
(省略v-on
,推荐使用) - 常见事件名:
click
(点击)、input
(输入)、change
(选择变化)、mouseenter
(鼠标进入)等。
6.2 核心用法示例
1. 绑定方法(无参数)
<div id="app"><!-- 点击按钮触发handleClick方法 --><button @click="handleClick">点击触发方法</button><p>{{ count }}</p>
</div>
<script>new Vue({el: "#app",data: { count: 0 },methods: {handleClick() {this.count++; // 修改data中的count,视图自动更新}}});
</script>
2. 传递参数(含事件对象)
- 若需传递自定义参数,同时获取事件对象(
$event
),需手动传入$event
(Vue内置变量,代表原生事件对象)。 - 示例:
<div id="app"><!-- 传递自定义参数num,同时传入事件对象$event --><button @click="handleBtnClick(5, $event)">点击增加5</button><p>{{ count }}</p>
</div>
<script>new Vue({el: "#app",data: { count: 0 },methods: {handleBtnClick(num, e) {this.count += num; // 使用自定义参数nume.target.disabled = true; // 使用事件对象禁用按钮}}});
</script>
3. 事件修饰符(简化事件处理)
Vue提供“事件修饰符”,用于简化常见的事件处理逻辑(如阻止默认行为、阻止事件冒泡),无需在方法中写e.preventDefault()
或e.stopPropagation()
。
修饰符 | 作用 | 示例 |
---|---|---|
.prevent | 阻止事件默认行为(如表单提交、链接跳转) | @submit.prevent="handleSubmit" (阻止表单提交) |
.stop | 阻止事件冒泡(避免父元素触发相同事件) | @click.stop="handleClick" |
.once | 事件仅触发一次 | @click.once="handleClick" |
- 示例:阻止表单默认提交
<form @submit.prevent="handleSubmit"><input type="text" v-model="username"> <!-- v-model后续讲解,先预告 --><button type="submit">提交</button>
</form>
<script>new Vue({el: "#app",data: { username: "" },methods: {handleSubmit() {console.log("表单提交:", this.username); // 自定义提交逻辑}}});
</script>
七、数据与方法基础(配合指令使用)
7.1 data
选项:响应式数据
- 作用:存储Vue实例的响应式数据,数据变化时,所有引用该数据的指令(如
{{ }}
、v-bind
)会自动更新视图。 - 访问方式:在Vue实例内部(如
methods
中)通过this.变量名
访问(无需写this.data.变量名
)。 - 注意事项:
- 初始数据需在
data
中定义,后续新增的属性不具备响应式(需用Vue.set
添加); - 数组直接通过索引修改元素(如
this.arr[0] = "newVal"
)不触发响应式更新,需用数组变异方法(如push
、splice
)或Vue.set
。
- 初始数据需在
7.2 methods
选项:方法定义
- 作用:存储Vue实例的方法,用于处理事件逻辑、业务计算等。
- 调用方式:
- 事件绑定:通过
@click="方法名"
调用; - 内部调用:在
methods
中通过this.方法名()
调用(如handleA()
中调用handleB()
)。
- 事件绑定:通过
- 与
data
的区别:data
:存储“数据”(如count
、msg
);methods
:存储“逻辑”(如handleClick
、calculate
),不能用于存储数据(方法执行后返回值不会自动更新视图)。
7.3 数组更新检测(重点避坑)
Vue对数组的响应式支持有限,仅数组变异方法会触发视图更新,非变异方法(如slice
、filter
)不会。
类型 | 方法列表 | 是否触发响应式更新 |
---|---|---|
变异方法 | push() 、pop() 、shift() 、unshift() 、splice() 、sort() 、reverse() | ✅ 是 |
非变异方法 | slice() 、filter() 、concat() 、map() | ❌ 否(需重新赋值) |
- 示例:正确更新数组
<div id="app"><ul><li v-for="item in list">{{ item }}</li> <!-- v-for后续讲解,先预告 --></ul><button @click="updateList">更新数组</button>
</div>
<script>new Vue({el: "#app",data: { list: ["a", "b", "c"] },methods: {updateList() {// 1. 变异方法:直接修改原数组,触发更新this.list.push("d"); // 2. 非变异方法:重新赋值给原数组,触发更新// this.list = this.list.filter(item => item !== "a");}}});
</script>