v-bind 指令

描述:用于动态地将数据绑定到 HTML 元素的属性上,当数据发生变化时,其对应的属性值也会自动更新变化

语法:v-bind:attrName="expression" or :attrName="expression"

attrName 为要绑定的属性名,expression 为要绑定的数据,它可以是任意的 Vue 表达式

1. 动态绑定元素属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- src/App.vue -->
<template>
<a :href="url" :title="title">{{ title }}</a>
<!-- disabled 如果为 true, 则启用该属性, 反之则移除该属性 -->
<input type="text" :disabled="disabled" />
<!-- 动态绑定多个属性 -->
<h1 :="attrs">Hello!!!</h1>
</template>

<script setup>
import { ref, reactive } from 'vue';

const url = ref('https://www.baidu.com');
const title = ref('百度');
const disabled = ref(true);
const attrs = reactive({
title: 'Hello!!!',
id: 'title'
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- src/App.vue -->
<template>
<a :href="url" :title="title">{{ title }}</a>
<!-- disabled 如果为 true, 则启用该属性, 反之则移除该属性 -->
<input type="text" :disabled="disabled">
<!-- 动态绑定多个属性 -->
<h1 :="attrs">Hello!!!</h1>
</template>

<script>
export default {
data() {
return {
url: 'https://www.baidu.com',
title: '百度',
disabled: true,
attrs: {
title: 'Hello!!!',
id: 'title'
}
}
}
}
</script>

2. 动态绑定元素class, 对象语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- src/App.vue -->
<template>
<!-- 根据对象属性的 value 是否为 true, 来选择是否将其属性的 key 作为该元素 className -->
<div :class="{ content: isStat }">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Adipisci, fugit. Voluptatem pariatur incidunt nihil saepe perspiciatis est dolor dolorum, praesentium dignissimos tempore facere facilis sequi fugit asperiores vel aperiam maxime!</div>
</template>

<script setup>
import { ref } from 'vue';

const isStat = ref(true);
</script>

<style scoped>
.content {
font-size: 22px;
font-weight: bold;
color: blueviolet
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- src/App.vue -->
<template>
<!-- 根据对象属性的 value 是否为 true, 来选择是否将其属性的 key 作为该元素 className -->
<div :class="{ content: isStat }">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Adipisci, fugit. Voluptatem pariatur incidunt nihil saepe perspiciatis est dolor dolorum, praesentium dignissimos tempore facere facilis sequi fugit asperiores vel aperiam maxime!</div>
</template>

<script>
export default {
data() {
return {
isStat: true
}
}
}
</script>

<style scoped>
.content {
font-size: 22px;
font-weight: bold;
color: blueviolet
}
</style>

3. 动态绑定元素class, 数组语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- src/App.vue -->
<template>
<!-- 数组中每个 item 都将成为该元素的 className -->
<div :class="[className, 'style2']">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Adipisci, fugit. Voluptatem pariatur incidunt nihil saepe perspiciatis est dolor dolorum, praesentium dignissimos tempore facere facilis sequi fugit asperiores vel aperiam maxime!</div>
</template>

<script setup>
import { ref } from 'vue';

const className = ref('content');
</script>

<style scoped>
.content {
font-size: 22px;
font-weight: bold;
color: blueviolet
}

.style2 {
border: 2px solid black;
padding: 10px 15px;
background-color: chartreuse
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!-- src/App.vue -->
<template>
<!-- 数组中每个 item 都将成为该元素的 className -->
<div :class="[className, 'style2']">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Adipisci, fugit. Voluptatem pariatur incidunt nihil saepe perspiciatis est dolor dolorum, praesentium dignissimos tempore facere facilis sequi fugit asperiores vel aperiam maxime!</div>
</template>

<script>
export default {
data() {
return {
className: 'content'
}
}
}
</script>

<style scoped>
.content {
font-size: 22px;
font-weight: bold;
color: blueviolet
}

.style2 {
border: 2px solid black;
padding: 10px 15px;
background-color: chartreuse
}
</style>

4. 动态绑定元素style, 对象语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- src/App.vue -->
<template>
<div :style="content">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Adipisci, fugit. Voluptatem pariatur incidunt nihil saepe perspiciatis est dolor dolorum, praesentium dignissimos tempore facere facilis sequi fugit asperiores vel aperiam maxime!</div>
</template>

<script>
import { reactive } from 'vue';

const content = reactive({
// 如果不加引号, 则要用驼峰命名法
fontSize: '22px',
fontWeight: 'bold',
color: 'blueviolet'
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- src/App.vue -->
<template>
<div :style="content">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Adipisci, fugit. Voluptatem pariatur incidunt nihil saepe perspiciatis est dolor dolorum, praesentium dignissimos tempore facere facilis sequi fugit asperiores vel aperiam maxime!</div>
</template>

<script>
export default {
data() {
return {
content: {
// 如果不加引号, 则要用驼峰命名法
fontSize: '22px',
fontWeight: 'bold',
color: 'blueviolet'
}
}
}
}
</script>

5. 动态绑定元素style, 数组语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- src/App.vue -->
<template>
<div :style="[content, style2]">Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptates enim architecto rem nostrum, aliquam corporis. Maiores vel magni exercitationem. Odit vitae dicta ipsam earum delectus aliquid velit ipsum vel deleniti?</div>
</template>

<script setup>
import { reactive } from 'vue';

const content = reactive({
fontSize: '22px',
fontWeight: 'bold',
color: 'blueviolet'
});
const style2 = reactive({
border: '2px solid black',
padding: '10px 15px',
backgroundColor: 'chartreuse'
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- src/App.vue -->
<template>
<div :style="[content, style2]">Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptates enim architecto rem nostrum, aliquam corporis. Maiores vel magni exercitationem. Odit vitae dicta ipsam earum delectus aliquid velit ipsum vel deleniti?</div>
</template>

<script>
export default {
data() {
return {
content: {
fontSize: '22px',
fontWeight: 'bold',
color: 'blueviolet'
},
style2: {
border: '2px solid black',
padding: '10px 15px',
backgroundColor: 'chartreuse'
}
}
}
}
</script>

v-model 指令

描述:用于实现表单元素( 如 input、textarea、select 等 )和 Vue 实例数据的双向绑定,它会根据表单的类型来动态的将表单输入的内容与 Vue 组件实例的数据进行双向绑定

语法:v-model="data"

data 为要绑定的数据,必须是响应式数据

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!-- src/App.vue -->
<template>
    <h2>例1. text类型表单</h2>
    <!-- .trim 为 v-model 修饰符, 可以过滤首尾的空格 -->
    <input type="text" v-model.trim="message">
    <p>您输入的内容是:{{ message }}</p>

    <h2>例2. radio类型表单</h2>
    <p>性别:{{ sex }}</p>
    <!-- radio 类型表单需要显示的指定 value 的值 -->
    <input type="radio" name="sex" value="男" v-model="sex">
    <input type="radio" name="sex" value="女" v-model="sex">

    <h2>例3. checkbox类型表单</h2>
    <p>喜好:{{ likes }}</p>
    <!-- 如果使用了一组 checkbox 类型表单, 需要显示的指定 value 的值, 同时要将 v-model 绑定为一个数组 -->
    <input type="checkbox" name="like" value="篮球" v-model="likes"> 篮球
    <input type="checkbox" name="like" value="足球" v-model="likes"> 足球
    <input type="checkbox" name="like" value="乒乓球" v-model="likes"> 乒乓球
</template>

<script setup>
import { ref, reactive } from 'vue';

const message = ref('');
const sex = ref('男');
const likes = reactive(['乒乓球']);
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!-- src/App.vue -->
<template>
    <h2>例1. text类型表单</h2>
    <!-- .trim 为 v-model 修饰符, 可以过滤首尾的空格 -->
    <input type="text" v-model.trim="message">
    <p>您输入的内容是:{{ message }}</p>

    <h2>例2. radio类型表单</h2>
    <p>性别:{{ sex }}</p>
    <!-- radio 类型表单需要显示的指定 value 的值 -->
    <input type="radio" name="sex" value="男" v-model="sex">
    <input type="radio" name="sex" value="女" v-model="sex">

    <h2>例3. checkbox类型表单</h2>
    <p>喜好:{{ likes }}</p>
    <!-- 如果使用了一组 checkbox 类型表单, 需要显示的指定 value 的值, 同时要将 v-model 绑定为一个数组 -->
    <input type="checkbox" name="like" value="篮球" v-model="likes"> 篮球
    <input type="checkbox" name="like" value="足球" v-model="likes"> 足球
    <input type="checkbox" name="like" value="乒乓球" v-model="likes"> 乒乓球
</template>

<script>
export default {
    data() {
        return {
            message: '',
            sex: '男',
            likes: ['乒乓球']
        }
    }
}
</script>

v-model 修饰符:

  • .lazy 失去焦点或按下回车键时才更新绑定数据

  • .number 输入字符串转换为有效的数字

  • .trim 过滤首尾的空格

v-on 指令

描述:用于监听 DOM 事件,并在事件触发时执行指定的方法或表达式

语法:v-on:eventName="handler" or @:eventName="handler"

eventName 为事件名,handler 为事件触发时要执行的函数或 Vue表达式

例1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- src/App.vue -->
<template>
<!--
如果事件处理函数中无需传递参数可以不加小括号()
这样的话在事件触发时 Vue 会自动添加事件对象(event)作为第1个参数
-->
<button @click="handler">Button-1</button> <!-- PointerEvent -->
<button @click="handler('Button-2 was clicked')">Button-2</button> <!-- 'Button-2 was clicked' -->
<!--
你也可以在事件处理函数参数中显示的指定事件对象
$event 为触发该事件的事件对象
-->
<button @click="handler($event)">Button-2</button> <!-- PointerEvent -->
</template>

<script setup>
const handler = (arg) => {
console.log(arg);
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- src/App.vue -->
<template>
    <!--
      如果事件处理函数中无需传递参数可以不加小括号()
      这样的话在事件触发时 Vue 会自动添加事件对象(event)作为第1个参数
    -->
    <button @click="handler">Button-1</button> <!-- PointerEvent -->
    <button @click="handler('Button-2 was clicked')">Button-2</button> <!-- 'Button-2 was clicked' -->
    <!--
      你也可以在事件处理函数参数中显示的指定事件对象
      $event 为触发该事件的事件对象
    -->
    <button @click="handler($event)">Button-2</button> <!-- PointerEvent -->
</template>

<script>
export default {
    // 事件处理函数写在 methods 中
    methods: {
        handler(arg) {
            console.log(arg);
        }
    }
}
</script>

另外,v-on 还支持修饰符,用来对事件进行额外的处理,如 阻止默认行为、阻止事件冒泡等

常用事件修饰符列表:

修饰符描述
.prevent阻止默认行为
.stop阻止事件冒泡
.capture事件在捕获阶段触发
.self只当事件在该元素本身触发时才处理
.once事件只执行一次
.passive提升页面滚动性能
.left按下键盘左键
.right按下键盘右键
.up按下键盘上键
.down按下键盘下键
.enter按下键盘 回车 键
.delete按下键盘 Delete 键
.esc按下键盘 ESC 键
.space按下键盘 空格 键
.tab按下键盘 Tab 键
.capsLock按下键盘 CapsLock 键
.ctrl组合键,按下键盘 Ctrl 键 + Other
.alt组合键,按下键盘 Alt 键 + Other
.shift组合键,按下键盘 Shift 键 + Other
.meta组合键,按下键盘 Win 键 + Other

例2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- src/App.vue -->
<template>
<div class="bg" @click="alert1">
<!-- 阻止默认行为同时阻止事件冒泡 -->
<a href="https://www.timeic.top" @click.prevent.stop="alert2">click me!</a>
</div>
</template>

<script setup>
const alert1 = () => {
alert('alert 1');
}

const alert2 = () => {
alert('alert 2');
}
</script>

<style scoped>
.bg {
background-color: tomato;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!-- src/App.vue -->
<template>
    <div class="bg" @click="alert1">
        <!-- 阻止默认行为同时阻止事件冒泡 -->
        <a href="https://www.timeic.top" @click.prevent.stop="alert2">click me!</a>
    </div>
</template>

<script>
export default {
    // 事件处理函数写在 methods 中
    methods: {
        alert1() {
            alert('alert 1');
        },
        alert2() {
            alert('alert 2');
        }
    }
}
</script>

<style scoped>
.bg {
    background-color: tomato;
}
</style>

例3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- src/App.vue -->
<template>
    <!-- 当按下 Ctrl + Enter 键时执行 handler -->
    <input v-model="text" type="text" @keyup.ctrl.enter="handler">
</template>

<script setup>
import { ref } from 'vue';

const text = ref('');
const handler = () => {
    alert(`您输入的是 '${text.value}'`);
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- src/App.vue -->
<template>
    <!-- 当按下 Ctrl + Enter 键时执行 handler -->
    <input v-model="text" type="text" @keyup.ctrl.enter="handler">
</template>

<script>
export default {
    data() {
        return {
            text: ''
        }
    },
    // 事件处理函数写在 methods 中
    methods: {
        handler() {
            alert(`您输入的是 '${this.text}'`);
        }
    }
}
</script>

computed 计算属性

Vue 的 computed 用于定义一些基于现有数据计算得出的属性。它可以将逻辑与模板分离,使代码更加简洁、易读、易于维护。同时计算属性会通过缓存和依赖跟踪机制提供响应式和高效的性能

特点:

  • 缓存:计算属性会根据其依赖的响应式数据进行缓存( 缓存计算结果 ),只有当它所依赖的响应式数据发生变化时才会重新计算,这意味着在模板中多次访问同一个计算属性时,只会计算一次

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!-- src/App.vue -->
<template>
    <p>{{ fullName }}</p>
    姓:<input type="text" v-model="firstName"><br>
    名:<input type="text" v-model="lastName">
</template>

<script setup>
// computed 函数返回一个 RefImpl 类型 Proxy 对象( Vue 响应式数据 )
import { ref, computed } from 'vue';

const firstName = ref('王');
const lastName = ref('五');
// 这里可以使用简写形式: const fullName = computed(() => { //访问 fullName.value 时,执行此处 })
const fullName = computed({
    // 访问 fullName.value 时,执行 get()
    // get 中 return 的值为计算结果,它会根据其依赖的数据进行缓存
    get() {
        return firstName.value + ' ' + lastName.value;
    },
    // 修改 fullName.value 时,执行 set()
    set(value) {
        let [newFirstName, newLastName] = value.split(' ');
        firstName.value = newFirstName;
        lastName.value = newLastName;
    }
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!-- src/App.vue -->
<template>
    <p>{{ fullName }}</p>
    姓:<input type="text" v-model="firstName"><br>
    名:<input type="text" v-model="lastName">
</template>

<script>
export default {
    data() {
        return {
            firstName: '王',
            lastName: '五'
        }
    },
    computed: {
        // fullName 可以简写为一个函数, 例如:fullName() { //访问 fullName 时,执行此处 }
        fullName: {
            // 访问 fullName 时,执行 get()
            // get 中 return 的值为计算结果,它会根据其依赖的数据进行缓存
            get() {
                return this.firstName + ' ' + this.lastName
            },
            // 修改 fullName 时,执行 set()
            set(value) {
                let [firstName, lastName] = value.split(' ')
                this.firstName = firstName
                this.lastName = lastName
            }
        }
    }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
/* src/main.js */
import { createApp } from 'vue'
// 导入根组件
import App from './App.vue'

const app = createApp(App)

const vm = app.mount('#app')

// 修改 fullName
// vm.fullName = '李 四'

watch 侦听器

Vue 的 watch API 可以用来监听某个属性的变化,并在属性变化时执行相应的操作

当你需要在数据发生变化时执行异步或复杂的操作( 副作用操作 ),或者需要在数据变化后执行一些特定的逻辑时,可以使用 watch

watch 选项式 API

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!-- src/App.vue -->
<template>
    <h2>今天天气很{{ info }}</h2>
    <button @click="changeWeather">切换天气</button>
</template>

<script>
export default {
    data() {
        return {
            isHot: true
        }
    },
    computed: {
        info() {
            return this.isHot ? '炎热' : '凉爽'
        }
    },
    methods: {
        changeWeather() {
            this.isHot = !this.isHot
        }
    },
    watch: {
        // isHot 可以简写为一个函数, 例如:isHot() { //isHot 发生变化时执行此处 }
        isHot: {
            // 当 isHot 被修改时执行 handler 函数
            handler(newValue, oldValue) {
                console.log('isHot 被修改了', newValue, '->', oldValue);
            }
            // 配置选项...
        }
    }
}
</script>

在选项式 API 中,还可以通过组件实例上的 $watch 方法来监听数据变化:

语法:$watch(监听属性, 回调函数, 配置选项)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
export default {
    data() {
        return {
            count: 0
        }
    },
    created() {
    // $watch 函数会返回停止监听函数 stop
        const stop = this.$watch(count, (newValue, oldValue) => {
console.log('count 被修改了', newValue, '->', oldValue);
        });

count++; // 修改 count
stop(); // 停止监听
count++; // 不再触发监听
    }
}
</script>

Tips:

  • 在选项式 API 中,默认监听复杂类型(如 数组、对象)的响应式数据,会监听其引用值,而不会监听其内部属性的变化,如要监听内部属性的变化则需要配置项 deep: true

watch 组合式 API

Vue3 组合式 API 中提供了 watch 函数,用于监听 响应式数据( 包括 refreactive、计算属性 等… ) 的变化

  1. 同时监听多个数据
1
2
3
4
5
6
7
8
9
10
11
12
import { ref, watch } from 'vue';

const firstName = ref('张');
const lastName = ref('三');

// 可以用数组的方式同时监听多个数据
watch([firstName, lastName], ([newFirst, newLast], [oldFirst, oldLast]) => {
console.log(`名字变化: ${oldFirst}${oldLast}${newFirst}${newLast}`);
});

firstName.value = '李'; // 输出:名字变化: 张三 → 李三
lastName.value = '四'; // 输出:名字变化: 李三 → 李四
  1. 监听复杂类型的响应式数据
1
2
3
4
5
6
7
8
9
10
11
12
import { reactive, watch } from 'vue';

const person = reactive({
name: '张三',
age: 20
});

// 默认会监听对象内部属性的变化( 隐式深度监听 ),而不是监听对象的引用变化
watch(person, (newPerson, oldPerson) => {
// 由于对象的引用关系,这里的新值 newPerson 和 旧值 oldPerson 是相同(相等)的
console.log(`对象变化:`, newPerson);
});
  1. 停止监听
1
2
3
4
5
6
7
8
9
10
11
import { ref, watch } from 'vue';

const count = ref(0);
// watch 函数会返回停止监听函数 stop
const stop = watch(count, (newValue) => {
console.log(`count 变化: ${newValue}`);
});

count.value = 1; // 触发监听
stop(); // 停止监听
count.value = 2; // 不再触发监听

Tips:

  • reactive 对象的监听:用 reactive 函数创建的复杂类型响应式数据,默认会监听对象内部属性的变化( 隐式深度监听 ),而不会监听对象的引用变化

watch 侦听器配置选项:

  • immediate: 值为 true 时,会在组件初始化时会先调用一次回调 / handler 函数。默认值为 false

  • deep: 默认 watch 无法监听数组或对象内部数据的变化( 组合式API 除外 ),当 deep 的值为 true 时,就可以深度递归监听数组或对象内部值的变化。默认值为 false

  • once: 一次性监听。值为 true 时,数据变化时只会触发一次

例:

1
2
3
4
5
6
7
8
9
10
11
12
<template>
    <button @click="count++">{{ count }}</button>
</template>

<script setup>
import { ref, watch } from 'vue';

const count = ref(0);
watch(count, (newValue, oldValue) => {
    console.log('count 被修改了', newValue, '->', oldValue);
}, { once: true }) // once: true 一次性监听器
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
    <button @click="count++">{{ count }}</button>
</template>

<script>
export default {
    data() {
        return {
            count: 0
        }
    },
    watch: {
        count: {
            handler(newValue, oldValue) {
                console.log('count 被修改了', newValue, '->', oldValue);
            },
            once: true // once: true 一次性监听器
        }
    }
}
</script>

watchEffect

Vue3 的 watchEffect一种自动收集依赖的响应式监听器,与 watch 不同,它不需要手动指定监听的变量,而是会在回调函数执行时,自动收集依赖,并在依赖变化时重新执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script setup>
import { reactive, watchEffect } from 'vue';

const user = reactive({
    name: '张三',
    age: 25
});

watchEffect(() => {
    console.log(`用户信息变化: ${user.name} - ${user.age}`);
});

const changeUser = () => {
    user.name = '李四';
    user.age = 28;
};
</script>

<template>
    <p>姓名:{{ user.name }}</p>
    <p>年龄:{{ user.age }}</p>
    <button @click="changeUser">修改用户信息</button>
</template>

watchwatchEffect 的区别:

v-show 指令

描述:用于根据条件动态的显示与隐藏元素,当表达式的值为 false 时元素的 style 就会加上 display: none

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- src/App.vue -->
<template>
    <button @click="toggle">Toggle</button>
    <div v-show="isVisible">I am visible</div>
</template>

<script setup>
import { ref } from 'vue';

const isVisible = ref(true);
const toggle = () => {
    isVisible.value = !isVisible.value;
}
</script>

v-if 指令

描述:用于根据条件动态地渲染/销毁元素或组件。它根据表达式的值来决定是否渲染元素,它的语法为:v-if="条件"

v-if 还可以配合 v-else-ifv-else 指令来实现多条件处理

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- src/App.vue -->
<template>
    <!-- 当 type 为 A 时渲染 -->
    <div v-if="type === 'A'">这是类型 A</div>
    <!-- 当 type 为 B 时渲染 -->
    <div v-else-if="type === 'B'">这是类型 B</div>
    <!-- 当 type 既不为 A 也不为 B 时渲染 -->
    <div v-else>这是其他类型</div>
    <!-- 切换 type 的按钮 -->
    <button @click="changeType('A')"> A </button>
    <button @click="changeType('B')"> B </button>
    <button @click="changeType('O')"> O </button>
</template>

<script setup>
import { ref } from 'vue';

const type = ref('A');
const changeType = (type) => {
    type.value = type;
}
</script>

v-for 指令

描述:用于渲染列表数据,它可以将一个数组或一个对象在页面中响应式的渲染为多个相同结构的元素

语法:v-for="value in items" or v-for="(value, key) in items"

例1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!-- src/App.vue -->
<template>
    <ul>
        <h2>人员列表(数组)</h2>
        <!--
        如果数组元素的顺序发生变化, 可能会导致重复渲染, 甚至出现错位渲染的情况
        因此遍历数组时, :key 值建议为数组成员中的唯一值(id)
        -->
        <!-- element 为数组的每个元素, index 为数组的索引 -->
        <li v-for="(element, index) in persons" :key="element.id">
            {{ element.name }}-{{ element.age }}
        </li>
    </ul>

    <ul>
        <h2>汽车信息(对象)</h2>
        <!-- value 为对象属性的值, key 为对象中属性的名称 -->
        <li v-for="(value, key) in car" :key="key">
            {{ key }}-{{ value }}
        </li>
    </ul>

    <ul>
        <h2>遍历一个字符串</h2>
        <!-- char 为字符串中的每个字符, index 为每个字符的索引 -->
        <li v-for="(char, index) in string">
            {{ char }}-{{ index }}
        </li>
    </ul>

    <ul>
        <h2>遍历指定次数(5次)</h2>
        <!-- 遍历数字 1-5, number 为遍历的数字, index 为该数字的索引 -->
        <li v-for="(number, index) in 5">
            {{ number }}-{{ index }}
        </li>
    </ul>
</template>

<script setup>
import { ref, reactive } from 'vue';

const persons = reactive([
    { id: 1, name: '张三', age: 18 },
    { id: 2, name: '李四', age: 19 },
    { id: 3, name: '王五', age: 20 }
]);
const car = reactive({
    name: '宝马xxx',
    price: 'xx万',
    color: '白色'
});
const string = ref('HelloVue');
</script>

key 属性的作用:

Vue 默认按照“就地更新”的策略来更新通过 v-for 渲染的元素列表。当数据项的顺序改变时,Vue 不会随之移动 DOM 元素的顺序,而是就地更新所有的元素,确保它们在原本指定的索引位置上渲染。默认模式是高效的,但只适用于列表渲染输出的结果不依赖子组件状态或者临时 DOM 状态 (例如表单输入值) 的情况

key 属性可以帮助 Vue 在列表项更新时准确、高效地识别每个元素,避免不必要的重新渲染。具体来说,key 提供了一个唯一标识,使 Vue 在数据变化时能更智能地对比新旧元素,从而进行最小化的 DOM 渲染

例2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!-- src/App.vue -->
<template>
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入名字" v-model="keyWord">
    <button @click="sortType = 2">年龄升序</button>
    <button @click="sortType = 1">年龄降序</button>
    <button @click="sortType = 0">原顺序</button>
    <ul>
        <li v-for="e in filPersons" :key="e.id">
            {{ e.name }} - {{ e.age }} - {{ e.sex }}
        </li>
    </ul>
</template>

<script setup>
import { ref, reactive, computed } from 'vue';

const keyWord = ref('');
const sortType = ref(0);
const persons = reactive([
    { id: 1, name: 'Patricia', age: 28, sex: '女' },
    { id: 2, name: 'Jennifer', age: 22, sex: '女' },
    { id: 3, name: 'James', age: 30, sex: '男' },
    { id: 4, name: 'Robert', age: 19, sex: '男' }
]);
const filPersons = computed(() => {
    let arr = persons.filter(p => {
        return p.name.indexOf(keyWord.value) !== -1;
    })
    if (sortType.value) {
        arr.sort((p1, p2) => {
            return sortType.value === 1 ? (p2.age - p1.age) : (p1.age - p2.age);
        })
    }
    return arr;
})
</script>

v-text & v-html 指令

描述:用于更新 HTML 元素的内容

  • v-text 是将元素的 textContent 设置为指定的值

  • v-html 是将元素的 innerHTML 设置为指定的值

注意:由于 v-html 指令将字符串作为 HTML 直接解析,因此要确保绑定的数据是可信的。在使用 v-html 指令时,应该避免将用户输入的内容直接插入到 HTML 中,以防止 XSS( 跨站脚本攻击 ) 等安全问题

v-cloak 指令

描述:用于解决 Vue 编译过程出现的闪烁问题。通常与 CSS 配合使用,可以确保在 Vue 实例完全编译之前,元素不会出现 Vue 插值表达式( {{xxx}} )

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- src/App.vue -->
<template>
    <!-- 当 Vue.js 加载完成并创建应用实例完成挂载后 v-cloak 属性会被 Vue 自动删掉 -->
    <h1 v-cloak>{{ message }}</h1>
</template>

<script setup>
import { ref } from 'vue';

const message = ref('v-cloak');
</script>

<style>
[v-cloak] {
    display: none;
}
</style>

v-pre 指令

描述:用于跳过当前元素和其子元素的模板编译过程。这意味着你不能在 v-pre 标记的元素上使用 Vue指令和插值语法

例:

1
2
3
4
5
6
<!-- src/App.vue -->
<template>
<!-- 跳过静态元素(没有使用Vue指令和模板语法的元素)的模板编译过程, 可以加快编译速度 -->
<h1 v-pre>public element</h1>
<p>{{message}}</p>
</template>