内容渲染指令
内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容。常用的内容渲染指令有如下2 个:
v-text(类似innerText)
-
- 使用语法:
<p v-text="name">hello</p>
,意思是将 name 值渲染到 p 标签中 - 类似 innerText,使用该语法,会覆盖 p 标签原有内容
- 使用语法:
v-html(类似 innerHTML)
-
- 使用语法:
<p v-html="intro">hello</p>
,意思是将 intro 值渲染到 p 标签中 - 类似 innerHTML,使用该语法,会覆盖 p 标签原有内容
- 类似 innerHTML,使用该语法,能够将HTML标签的样式呈现出来。
- 使用语法:
条件渲染指令
条件判断指令,用来辅助开发者按需控制 DOM 的显示与隐藏。条件渲染指令有如下两个,分别是:
v-show
- 作用: 控制元素显示隐藏
- 语法: v-show = “表达式” 表达式值为 true 显示, false 隐藏
- 原理: 切换 display:none 控制显示隐藏
- 场景:频繁切换显示隐藏的场景
v-if
- 作用: 控制元素显示隐藏(条件渲染)
- 语法: v-if= “表达式” 表达式值 true显示, false 隐藏
- 原理: 基于条件判断,是否创建 或 移除元素节点
- 场景: 要么显示,要么隐藏,不频繁切换的场景
事件绑定指令
methods
基本定义
methods
是 Vue 实例或组件的一个选项,值为一个对象,对象中定义组件的方法:
export default {methods: {methodName() {// 逻辑代码},// 其他方法...}
}
核心特性
(1) 绑定 this
-
方法中的
this
自动绑定到 Vue 实例,可以直接访问data
、props
、computed
等属性:methods: {increment() {this.count++; // 直接操作 data 中的 count} }
(2) 模板中调用
-
在模板中通过
v-on
(或@
)绑定事件,或在插值中直接调用:<button @click="increment">点击增加</button> <p>{{ formatDate() }}</p>
(3) 传递参数
-
支持手动传递参数,包括原生事件对象
$event
:<button @click="say('Hello', $event)">传递参数</button>
methods: {say(message, event) {console.log(message, event.target);} }
与事件处理的结合
methods
常与 v-on
配合,处理用户交互事件:
<template><button @click="handleClick">点击</button><input @input="handleInput">
</template><script>
export default {methods: {handleClick() {alert('按钮被点击!');},handleInput(event) {console.log('输入内容:', event.target.value);}}
}
</script>
与 computed 的区别
methods | computed |
---|---|
每次调用都会执行 | 基于依赖缓存,依赖不变时复用 |
适合处理事件或需要主动触发的逻辑 | 适合派生数据(如过滤、计算) |
可以在模板中调用(如 {{ method() }} ) | 在模板中作为属性使用(如 {{ computedProp }} ) |
示例对比:
data() {return { firstName: 'John', lastName: 'Doe' };
},
methods: {fullNameMethod() {return this.firstName + ' ' + this.lastName; // 每次调用都重新计算}
},
computed: {fullNameComputed() {return this.firstName + ' ' + this.lastName; // 缓存结果,依赖不变时不重新计算}
}
异步操作
methods 中可执行异步操作(如 API 请求):
methods: {async fetchData() {try {const response = await axios.get('/api/data');this.data = response.data;} catch (error) {console.error('请求失败:', error);}}
}
避免箭头函数
-
避免在
methods
中使用箭头函数,否则this
不会绑定到 Vue 实例:// ❌ 错误:箭头函数导致 this 指向错误 methods: {badMethod: () => {console.log(this); // 指向 Window 或 undefined(严格模式)} }// ✅ 正确:普通函数确保 this 正确 methods: {goodMethod() {console.log(this); // 指向 Vue 实例} }
在生命周期钩子中调用
可以在生命周期钩子(如 created
、mounted
)中调用方法:
export default {created() {this.initData(); // 组件创建时调用方法},methods: {initData() {// 初始化逻辑}}
}
最佳实践
- 单一职责:每个方法专注于一个任务,提高可维护性。
- 避免直接操作 DOM:优先通过数据驱动视图,而非直接操作 DOM。
- 命名清晰:使用动词命名方法(如
handleClick
、fetchData
)。 - 复用逻辑:复杂逻辑封装为方法,避免在模板中写过多表达式。
完整示例
<template><div><button @click="increment">计数:{{ count }}</button><input type="text" @input="updateValue"placeholder="输入内容..."><p>输入的内容:{{ inputValue }}</p></div>
</template><script>
export default {data() {return {count: 0,inputValue: ''};},methods: {increment() {this.count++;},updateValue(event) {this.inputValue = event.target.value;}}
}
</script>
computed
在 Vue 中,computed
是用于定义计算属性的核心选项,它基于响应式依赖进行缓存,适合处理需要根据其他数据动态计算的场景。
核心特性
- 响应式依赖:
computed
属性会追踪其依赖的响应式数据(如data
、props
、其他computed
),当依赖变化时自动重新计算。 - 缓存机制:只有当依赖变化时才会重新计算,否则直接返回缓存结果,性能高效。
- 声明式逻辑:将复杂逻辑封装为计算属性,避免模板中写过多表达式。
基本语法
export default {computed: {属性名() {// 基于其他数据计算并返回值return this.data1 + this.data2;}}
}
模板中使用
<template><p>总价:{{ totalPrice }}</p>
</template>
适用场景
(1) 数据派生
将多个数据组合成一个新值:
data() {return { firstName: '张', lastName: '三' };
},
computed: {fullName() {return this.firstName + ' ' + this.lastName; // "张 三"}
}
(2) 复杂计算
如过滤列表、数学运算等:
data() {return { items: [ { price: 10 }, { price: 20 } ] };
},
computed: {totalPrice() {return this.items.reduce((sum, item) => sum + item.price, 0); // 30}
}
(3) 格式化数据
如日期格式化、文本截断:
computed: {formattedDate() {return new Date(this.rawDate).toLocaleDateString();}
}
与 methods
的对比
computed | methods |
---|---|
基于依赖缓存,依赖不变时直接返回结果 | 每次调用都会重新执行 |
通过属性名访问(无括号) | 通过方法调用(需括号) |
适合派生数据(如组合、计算) | 适合执行操作(如事件处理) |
示例对比
<template><!-- computed:高效,依赖不变时不会重复计算 --><p>{{ fullName }}</p><!-- methods:每次渲染都会调用 --><p>{{ getFullName() }}</p>
</template>
计算属性的 Setter
默认只有 getter
,但可以手动定义 setter
(较少用):
computed: {fullName: {get() {return this.firstName + ' ' + this.lastName;},set(newValue) {// 当修改 fullName 时,拆解并更新依赖数据const names = newValue.split(' ');this.firstName = names[0];this.lastName = names[1] || '';}}
}
最佳实践
- 避免副作用:
computed
应专注于计算,不要执行异步操作或修改外部状态。 - 拆分复杂逻辑:若计算逻辑复杂,可拆分为多个计算属性,提高可读性。
- 依赖明确:确保依赖的响应式数据清晰,避免依赖非响应式数据。
完整示例
<template><div><input v-model="price" type="number" placeholder="单价"><input v-model="quantity" type="number" placeholder="数量"><p>总价:{{ totalPrice }}</p><p>含税价:{{ taxedTotalPrice }}</p></div>
</template><script>
export default {data() {return {price: 0,quantity: 0,taxRate: 0.1};},computed: {totalPrice() {return this.price * this.quantity;},taxedTotalPrice() {return this.totalPrice * (1 + this.taxRate);}}
}
</script>
常见问题
Q1: computed
中可以调用异步方法吗?
- 不建议!
computed
设计用于同步计算,异步操作应放在methods
或watch
中。
Q2: computed
依赖非响应式数据会怎样?
- 如果依赖的数据不是响应式的(如未在
data
中定义),计算属性不会自动更新。
Q3: computed
和 watch
的区别?
computed
:声明式派生数据,依赖多个值。watch
:监听单个值的变化,执行副作用(如异步请求、复杂逻辑)。
总结:
computed
是 Vue 中处理复杂数据逻辑的利器,通过缓存机制提升性能,保持代码简洁。
优先使用 computed
替代模板内复杂表达式!
v-on
基本语法
<button v-on:事件类型="处理函数或表达式">按钮</button>
- 事件类型:如
click
、input
、keydown
等。 - 处理函数:在 Vue 实例的
methods
中定义的方法。 - 简写:为
@
,例如@click="handler"
。
常见用法
绑定方法
<button v-on:click="greet">点击</button>
methods: {greet() {alert('Hello!');}
}
内联表达式
<button @click="count += 1">增加计数:{{ count }}</button>
传递参数
<button @click="say('Hi', $event)">传递参数</button>
methods: {say(message, event) {alert(message);console.log(event.target); // 访问原生事件对象}
}
事件修饰符
Vue 提供修饰符简化常见事件处理逻辑,通过链式调用:
修饰符 | 作用 |
---|---|
.stop | 阻止事件冒泡(event.stopPropagation() ) |
.prevent | 阻止默认行为(event.preventDefault() ) |
.capture | 使用捕获模式触发事件 |
.self | 仅当事件在元素自身(非子元素)触发时执行 |
.once | 事件仅触发一次 |
.passive | 提升滚动性能(与 prevent 冲突) |
示例:
<form @submit.prevent="onSubmit"></form>
<a @click.stop.prevent="doSomething"></a>
按键修饰符
用于监听特定键盘按键:
<input @keyup.enter="submit"> <!-- 回车键触发 -->
<input @keyup.esc="clearInput"> <!-- ESC 键触发 --><input @keyup.enter=“submit”> <-- 回车键触发 -->
<input @keyup.esc=“clearInput”> <-- ESC 键触发 -->
支持按键别名(如 .enter
、.tab
、.esc
)或按键码(如 @keyup.13
)。
系统修饰键
监听组合按键(如 Ctrl + Click
):
<button @click.ctrl="doSomething">Ctrl + 点击触发</button>
<input @keyup.ctrl.enter="submit"> <!-- Ctrl + Enter 触发 -->
修饰符包括:.ctrl
、.alt
、.shift
、.meta
(Windows 的 Win 键,Mac 的 Command 键)。
动态事件名
通过动态绑定事件类型:
<button v-on:[eventName]="handler">动态事件</button>
eventName
可以是 Vue 实例的数据属性(如 focus
、mouseenter
)。
对象语法
绑定多个事件:
<button v-on="{ mousedown: start, mouseup: end }">按钮</button>
总结
v-on
是 Vue 事件处理的核心指令,简化了 DOM 事件监听。- 通过修饰符(如
.stop
、.prevent
)和按键处理,避免直接操作 DOM。 - 结合
methods
中的方法实现逻辑复用,保持代码清晰。
完整示例:
<template><div><button @click="increment">{{ count }}</button><input @keyup.enter="submit"@input="onInput"@focus.capture="log('聚焦')"></div>
</template><script>
export default {data() {return { count: 0, inputValue: '' }},methods: {increment() { this.count++ },submit() { alert('提交:' + this.inputValue) },onInput(event) { this.inputValue = event.target.value },log(msg) { console.log(msg) }}
}
</script>
属性绑定指令
v-bind
v-bind
是 Vue.js 中用于动态绑定属性或组件 Props的指令,它可以将 Vue 实例中的数据与 HTML 属性或组件 Props 进行绑定,实现数据到视图的动态响应。
核心功能
-
动态绑定 HTML 属性
将 HTML 元素的属性(如href
、src
、class
、style
等)绑定到 Vue 实例的数据,当数据变化时,属性自动更新。 -
传递 Props 到子组件
将父组件的数据传递给子组件的 Props,实现父子组件通信。 -
动态绑定属性名
根据数据动态决定绑定的属性名(如:[attributeName]="value"
)。
基本语法
简写:直接省略v-bind,只保留:
<!-- 完整语法 -->
<element v-bind:attribute="expression"></element><!-- 简写语法(推荐) -->
<element :attribute="expression"></element>
常见用法示例
1. 绑定普通属性
<!-- 绑定 href -->
<a :href="url">链接</a><!-- 绑定图片路径 -->
<img :src="imagePath"><!-- 动态禁用按钮 -->
<button :disabled="isDisabled">按钮</button>
2. 绑定 class
和 style
<!-- 动态 class(对象语法) -->
<div :class="{ active: isActive, error: hasError }"></div><!-- 动态 class(数组语法) -->
<div :class="[activeClass, errorClass]"></div><!-- 动态 style(对象语法) -->
<div :style="{ color: textColor, fontSize: fontSize + 'px' }"></div><!-- 动态 style(数组语法) -->
<div :style="[baseStyles, overrideStyles]"></div>
3. 绑定对象(批量绑定属性)
<!-- 将对象的所有属性绑定到元素 -->
<div v-bind="attributeObject"></div>
对应的数据:
data() {return {attributeObject: {id: 'container',class: 'box','data-custom': '123'}}
}
4. 绑定 Props 到子组件
<!-- 父组件传递数据给子组件的 prop -->
<child-component :title="parentTitle" :content="parentContent"></child-component>
5. 动态属性名
<!-- 根据 dynamicAttrName 的值决定绑定的属性名 -->
<input :[dynamicAttrName]="value">
数据:
data() {return {dynamicAttrName: 'placeholder',value: '请输入内容'}
}
关键细节
-
表达式与静态值
v-bind
的值是 JavaScript 表达式,而非字符串。例如:<!-- 传递一个布尔值 --> <button :disabled="isDisabled">按钮</button><!-- 传递一个数字 --> <input :max="10"><!-- 传递一个对象 --> <child-component :config="{ size: 'large', theme: 'dark' }"></child-component>
- 没有
v-bind
的陷阱
如果直接写属性而不加v-bind
,Vue 会将其视为字符串:
- 没有
<!-- 传递字符串 'data.id' -->
<div id="data.id"></div><!-- 传递变量 data.id 的值 -->
<div :id="data.id"></div>
-
修饰符(Modifiers)
-
.prop
:强制将属性绑定为 DOM 属性(而非 HTML 属性)。<div :some-prop.prop="value"></div>
-
.camel
:将属性名从短横线格式转为驼峰格式(用于模板中使用短横线命名的属性)。<svg :view-box.camel="viewBox"></svg>
-
列表渲染指令
v-for
在 Vue.js 中,v-for
是用于循环渲染列表数据的核心指令,可以遍历数组、对象或数字,生成动态的 DOM 元素或组件。
基本语法
<template v-for="(item, index) in list" :key="唯一标识"><!-- 渲染内容 -->
</template>
item
: 当前遍历的元素(数组项、对象值、数字迭代值)。index
: 当前项的索引(仅数组和对象遍历时可用)。:key
: 必须提供唯一标识(用于 Vue 的虚拟 DOM 高效更新)。
常见用法示例
1. 遍历数组
<ul><li v-for="(item, index) in items" :key="item.id">{{ index }} - {{ item.name }}</li>
</ul>
数据:
data() {return {items: [{ id: 1, name: 'Apple' },{ id: 2, name: 'Banana' },]}
}
2. 遍历对象
<div v-for="(value, key, index) in object" :key="key">{{ index }}. {{ key }}: {{ value }}
</div>
数据:
data() {return {object: {name: 'John',age: 30}}
}
3. 遍历数字
<span v-for="n in 5" :key="n">{{ n }}</span>
<!-- 输出:1 2 3 4 5 -->
4. 遍历组件
<child-component v-for="item in items" :key="item.id":item-data="item"
/>
核心规则
1. 必须绑定 :key
-
通过
:key
提供唯一标识(如item.id
),避免用索引index
(除非列表静态不变)。 -
错误示例:
<div v-for="(item, index) in items" :key="index"></div>
当列表顺序变化时,用 index 作为 key 会导致渲染错误或性能问题。
2. 响应式更新
-
Vue 能检测以下数组方法自动触发更新:
push(), pop(), shift(), unshift(), splice(), sort(), reverse()
-
直接修改数组索引或长度不会触发更新:
// 错误!不会更新视图 this.items[0] = { id: 3, name: 'Orange' }; // 正确做法 this.items.splice(0, 1, { id: 3, name: 'Orange' });
3. v-for
与 v-if
的优先级
-
Vue 2:
v-for
优先级高于v-if
,不推荐同时使用。 -
Vue 3:
v-if
优先级高于v-for
。 -
最佳实践:用计算属性过滤数据,避免同时使用:
<template v-for="item in filteredItems" :key="item.id"><div v-if="item.isActive">{{ item.name }}</div> </template>
常见问题
1. 为什么列表渲染不更新?
-
原因:直接修改数组或对象未触发响应式。
-
解决:使用变异方法(如
push
)或Vue.set
/this.$set
:// 动态添加对象属性 this.$set(this.object, 'newKey', 'newValue');
2. 如何遍历多层嵌套数据?
用嵌套的 v-for
:
<div v-for="group in groups" :key="group.id"><div v-for="item in group.items" :key="item.id">{{ item.name }}</div>
</div>
3. 如何跳过某些元素?
结合 v-if
或计算属性过滤:
<div v-for="item in items" :key="item.id" v-if="item.isVisible"></div>
双向绑定指令
v-model
v-model
是 Vue.js 中用于实现表单输入元素与数据双向绑定的核心指令,它能将表单控件(如 <input>
、<textarea>
、<select>
)的值与 Vue 实例的数据自动同步,无需手动操作 DOM。
核心机制
- 双向绑定:
v-model
是v-bind
(数据到视图)和v-on
(视图到数据)的语法糖。- 数据 → 视图:将数据绑定到表单元素的
value
/checked
属性。 - 视图 → 数据:监听表单元素的
input
或change
事件,更新数据。
- 数据 → 视图:将数据绑定到表单元素的
基本用法
1. 绑定文本输入(<input type="text">
、<textarea>
)
<input v-model="message" placeholder="请输入内容">
<p>输入的内容是:{{ message }}</p>
数据:
data() {return {message: ''}
}
2. 绑定复选框(单个/多个)
<!-- 单个复选框(布尔值) -->
<input type="checkbox" v-model="isChecked"> 是否同意<!-- 多个复选框(数组) -->
<input type="checkbox" value="apple" v-model="fruits"> 苹果
<input type="checkbox" value="banana" v-model="fruits"> 香蕉
数据:
data() {return {isChecked: false,fruits: []}
}
3. 绑定单选框
<input type="radio" value="male" v-model="gender"> 男
<input type="radio" value="female" v-model="gender"> 女
数据:
data() {return {gender: ''}
}
4. 绑定下拉框(<select>
)
<select v-model="selectedCity"><option value="beijing">北京</option><option value="shanghai">上海</option>
</select>
数据:
data() {return {selectedCity: ''}
}
修饰符(Modifiers)
1. .lazy
将 input
事件的同步改为 change
事件(输入完成后更新):
<input v-model.lazy="message"> <!-- 在输入框失焦后更新数据 -->
2. .number
将输入值自动转为数字类型:
<input v-model.number="age" type="number"> <!-- 输入 "30" → 30(数字) -->
3. .trim
自动去除输入内容的首尾空格:
<input v-model.trim="username"> <!-- 输入 " John " → "John" -->
自定义组件中的 v-model
在组件中使用 v-model
可以实现父子组件数据的双向绑定。
Vue 2 用法
-
默认绑定
value
prop 和input
事件。 -
示例:
<!-- 父组件 --> <custom-input v-model="message"></custom-input><!-- 子组件(CustomInput.vue) --> <template><input :value="value" @input="$emit('input', $event.target.value)"> </template> <script> export default {props: ['value'] } </script>
Vue 3 用法
-
默认绑定
modelValue
prop 和update:modelValue
事件。 -
支持多个
v-model
绑定:<!-- 父组件 --> <custom-input v-model:title="title" v-model:content="content"></custom-input><!-- 子组件 --> <template><input :value="title" @input="$emit('update:title', $event.target.value)"><input :value="content" @input="$emit('update:content", $event.target.value)"> </template> <script> export default {props: ['title', 'content'] } </script>
v-model的原理拆解
Vue 的 v-model
是一个语法糖,用于实现表单元素和组件的双向数据绑定。其核心原理可以拆解为以下部分:
1. 原生表单元素的双向绑定
对于原生表单元素(如 <input>
、<textarea>
、<select>
),v-model
会根据元素类型自动绑定对应的属性和事件,实现双向更新:
-
文本输入(text、textarea):
<input v-model="message" />
等价于:
<input :value="message" @input="message = $event.target.value" />
- 绑定
value
属性,监听input
事件。
- 绑定
-
复选框(checkbox):
<input type="checkbox" v-model="checked" />
等价于:
<input type="checkbox" :checked="checked" @change="checked = $event.target.checked" />
- 绑定
checked
属性,监听change
事件。
- 绑定
-
单选按钮(radio) 和 下拉框(select):
类似逻辑,绑定value
和监听change
事件。
2. 自定义组件的双向绑定
在自定义组件中,v-model
默认绑定 modelValue
属性和 update:modelValue
事件(Vue 3):
父组件使用:
<CustomComponent v-model="message" />
等价于:
<CustomComponent :modelValue="message" @update:modelValue="newValue => message = newValue"
/>
子组件实现:
// 接收父组件传递的 modelValue
props: ['modelValue'],// 触发更新事件
emits: ['update:modelValue'],
methods: {handleChange(e) {this.$emit('update:modelValue', e.target.value);}
}
3. 多个 v-model 绑定(Vue 3+)
Vue 3 允许通过参数绑定多个 v-model
,例如:
<CustomComponent v-model:title="title" v-model:content="content"
/>
等价于:
<CustomComponent :title="title" @update:title="newTitle => title = newTitle" :content="content" @update:content="newContent => content = newContent"
/>
4. 修饰符处理
v-model
支持修饰符,用于对输入值进行处理:
.lazy
:将input
事件改为change
事件(延迟同步)。.trim
:自动去除首尾空格。.number
:将输入转为数值类型。
<input v-model.lazy.trim.number="value" />
5. 底层实现机制
- 模板编译:Vue 编译器将
v-model
转换为对应的属性和事件绑定。 - 响应式系统:数据变化通过 Vue 的响应式系统驱动视图更新。
- 事件监听:用户输入触发事件,更新数据层,形成闭环。
总结
v-model
的核心是 语法糖,通过自动绑定属性和事件实现双向数据流:
- 对原生元素:根据类型绑定
value
/checked
属性和input
/change
事件。 - 对组件:默认绑定
modelValue
和update:modelValue
,支持自定义参数和多个绑定。 - 结合修饰符,可灵活处理输入值。