在平常的学习和面试中,Vue常见的指令往往会被反复问到,他也贡献了很多常见的八股文,比如为什么v-for需要有key以及v-if和v-show的区别,如何创建自定义指令等等..,Vue 3 不仅提供了丰富的内置指令,还支持开发者自定义指令,极大地增强了开发的灵活性和效率。下面我们就来详细了解一下 Vue 3 的各类指令。
内部组件
1. 条件渲染指令
v-if、v-else-if、v-else
- 功能:这组指令用于根据表达式的值来条件性地渲染元素或组件。
v-if首先判断表达式的值,如果为真则渲染元素;v-else-if用于多个条件的判断;v-else则是在前面条件都不满足时渲染。 - 示例:
<template>
<div>
<p v-if="condition === 'A'">显示 A</p>
<p v-else-if="condition === 'B'">显示 B</p>
<p v-else>显示其他</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const condition = ref('A');
</script>
v-show
-
功能:根据表达式的值控制元素的显示与隐藏。它是通过修改元素的
displayCSS 属性来实现的,元素始终会被渲染到 DOM 中,只是根据条件决定是否显示。 -
示例:
<template>
<div>
<p v-show="isShown">这是一个使用 v-show 控制显示的段落</p>
<button @click="toggleShow">切换显示状态</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const isShown = ref(true);
const toggleShow = () => {
isShown.value = !isShown.value;
};
</script>
2. 列表渲染指令
v-for
- 功能:用于基于数组、对象、数字等数据源来渲染列表。可以通过解构赋值获取当前项、索引、键等信息,并且需要使用
:key来为每个渲染项提供唯一标识,以帮助 Vue 识别节点,提高渲染效率。 - 示例:
<template>
<div>
<!-- 遍历数组 -->
<ul>
<li v-for="(fruit, index) in fruits" :key="index">{{ index }} - {{ fruit }}</li>
</ul>
<!-- 遍历对象 -->
<ul>
<li v-for="(value, key) in person" :key="key">{{ key }}: {{ value }}</li>
</ul>
<!-- 遍历数字 -->
<ul>
<li v-for="n in 5" :key="n">数字 {{ n }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
const fruits = ref(['草莓', '葡萄', '西瓜']);
const person = ref({ name: '李四', age: 25, occupation: '工程师' });
</script>
3. 事件绑定指令
v-on(缩写 @)
-
功能:用于绑定 DOM 事件,当事件触发时执行对应的表达式或方法。可以绑定原生 DOM 事件,也可以绑定自定义事件。
-
示例:
<template>
<div>
<button @click="handleClick">点击触发事件</button>
</div>
</template>
<script setup>
const handleClick = () => {
console.log('按钮被点击了');
};
</script>
事件修饰符
-
.stop:阻止事件冒泡,即阻止事件继续向上层元素传播。 -
.prevent:阻止事件的默认行为,例如表单提交、链接跳转等。 -
.capture:使用事件捕获模式,事件会从外层元素开始向内层元素传播。 -
.self:只有当事件是从绑定元素本身触发时才会执行回调,而不是从其子元素触发。 -
.once:事件只会触发一次,之后该事件绑定会被移除。 -
.passive:告诉浏览器该事件处理程序不会调用preventDefault(),可以提高滚动等事件的性能。 -
示例:
<template>
<div>
<form @submit.prevent="handleSubmit">
<input type="text">
<button type="submit">提交表单</button>
</form>
<div @click.capture="handleCaptureClick">
<button @click.stop="handleStopClick">阻止冒泡</button>
</div>
</div>
</template>
<script setup>
const handleSubmit = () => {
console.log('表单提交被处理');
};
const handleCaptureClick = () => {
console.log('事件捕获触发');
};
const handleStopClick = () => {
console.log('点击按钮,但冒泡被阻止');
};
</script>
4. 属性绑定指令
v-bind(缩写 :)
-
功能:用于动态绑定 HTML 属性、组件 props 等。可以将表达式的值绑定到元素的属性上,属性值可以是静态的,也可以是动态计算得到的。
-
示例:
<template>
<div>
<!-- 绑定 src 属性 -->
<img :src="imageSource" alt="示例图片">
<!-- 绑定 class 属性 -->
<p :class="{ active: isActive }">这是一个动态添加类名的段落</p>
<!-- 绑定 style 属性 -->
<p :style="{ color: textColor }">这是一个动态设置颜色的段落</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const imageSource = ref('https://example.com/sample.jpg');
const isActive = ref(true);
const textColor = ref('red');
</script>
动态参数
- 功能:可以使用方括号
[]来定义动态的属性名,这样可以根据表达式的值动态地绑定不同的属性。 - 示例:
<template>
<div>
<button :[dynamicAttr]="dynamicValue">动态属性按钮</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const dynamicAttr = ref('disabled');
const dynamicValue = ref(true);
</script>
5. 双向数据绑定指令
v-model
-
功能:用于在表单元素(如
input、textarea、select等)或自定义组件上创建双向数据绑定。它实际上是v-bind和v-on的语法糖,能够使数据的变化自动更新到视图,视图的变化也能自动更新到数据。 -
示例:
<template>
<div>
<input v-model="message" placeholder="请输入内容">
<p>你输入的内容是: {{ message }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const message = ref('');
</script>
修饰符
.lazy:将输入框的绑定更新时机从input事件改为change事件,即只有在输入框失去焦点或按下回车键时才更新数据。.number:将输入的值转换为数字类型,如果无法转换则保持原值。.trim:自动过滤输入值的首尾空格。- 示例:
<template>
<div>
<input v-model.lazy="lazyInput" placeholder="使用 lazy 修饰符">
<input v-model.number="numericInput" type="number" placeholder="使用 number 修饰符">
<input v-model.trim="trimmedInput" placeholder="使用 trim 修饰符">
</div>
</template>
<script setup>
import { ref } from 'vue';
const lazyInput = ref('');
const numericInput = ref(0);
const trimmedInput = ref('');
</script>
自定义指令
全局自定义指令
-
功能:可以在整个应用中使用的自定义指令,通常在创建 Vue 应用实例时进行注册。
-
示例:
// main.js
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
// 注册全局自定义指令
app.directive('highlight', {
mounted(el, binding) {
el.style.backgroundColor = binding.value || 'yellow';
}
});
app.mount('#app');
vue
<!-- App.vue -->
<template>
<div>
<p v-highlight="'green'">这是一个使用全局自定义指令的段落</p>
</div>
</template>
局部自定义指令
-
功能:只能在当前组件中使用的自定义指令,在组件的
setup函数中进行定义。 -
示例:
<template>
<div>
<input v-focus />
</div>
</template>
<script setup>
import { defineDirective } from 'vue';
// 定义局部自定义指令
const focus = defineDirective({
mounted(el) {
el.focus();
}
});
</script>
7. v-memo
-
功能:这是 Vue 3 新增的指令,用于缓存一个模板的子树。当依赖项没有发生变化时,直接复用之前的渲染结果,避免不必要的重新渲染,提高性能。
-
示例:
<template>
<div>
<!-- 只有当 items 数组发生变化时才会重新渲染 -->
<ul v-memo="[items]">
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
const items = ref([
{ id: 1, name: '项目 1' },
{ id: 2, name: '项目 2' }
]);
</script>
8. v-cloak
-
功能:这个指令主要用于解决在 Vue 实例挂载之前,模板闪烁的问题。在 Vue 实例还未编译完成时,带有
v-cloak的元素会被隐藏,编译完成后该指令会被移除,元素正常显示。 -
示例:
<template>
<div v-cloak>{{ message }}</div>
</template>
<script setup>
import { ref } from 'vue';
const message = ref('加载中...');
</script>
<style scoped>
[v-cloak] {
display: none;
}
</style>
结尾
了解了Vue的几种常见的内置组件和自定义组件之后,你可以再去看看常见的那些Vue指令八股文,是不是感觉答案也就呼之欲出了呢,前言提到的答案如下
v-if和v-show的区别
- 渲染方式:
v-if是真正的条件渲染,当条件为false时,对应的 DOM 元素不会被渲染到页面中;而v-show是通过切换元素的displayCSS 属性来控制显示与隐藏,无论条件真假,元素都会被渲染到页面中。 - 性能表现:在初始渲染时,
v-if有更高的切换开销,因为它需要动态地创建和销毁 DOM 元素;v-show有更高的初始渲染开销,因为它不管条件如何都会渲染元素。 - 使用场景:如果元素可能永远不会被显示,或者在运行时条件很少改变,使用
v-if更合适;如果需要频繁切换元素的显示状态,使用v-show更高效。
. v-for中为什么要使用key?
key是给 Vue 虚拟 DOM 的一个提示,用于在列表更新时,帮助 Vue 更高效地识别各个节点。如果不使用key,Vue 在更新列表时,可能会采用就地复用的策略,导致列表中元素的状态混乱,比如输入框的内容错位、复选框的勾选状态错误等。使用唯一的key,Vue 可以精确地找到需要更新的节点,提高更新效率,确保列表渲染的正确性和稳定性。