Vue——模板语法

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层组件实例的数据。所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。

在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应性系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。

 

一、插值

1、文本

数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:

1
<span>Message: {{ msg }}</span>

Mustache 标签将会被替代为对应组件实例中 msg property 的值。无论何时,绑定的组件实例上 msg property 发生了改变,插值处的内容都会更新。

 

2、原始 HTML(v-html)

双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用v-html 指令

指令 (Directives) 是带有 v- 前缀的特殊 attribute。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app">
    <p>Using mustaches: {{ rawHtml }}</p>
    <p>Using v-html directive: <span v-html="rawHtml"></span></p>
</div>
 
<script>
 
    const Counter = {
        data() {
            return {
                rawHtml: "<a href=''>hello</a>"
            }
        }
    }
 
    vm = Vue.createApp(Counter).mount('#app')
 
</script>

3、value 值(v-model)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="app">
    <!-- 设置vue可以操作的html内容范围,值一般就是css的id选择器。 -->
    <p>{{ msg }}</p>
    <p><input type="text" v-model="msg"></p>
</div>
 
<script>
 
    const Counter = {
        data() {
            return {
                msg: "hello world"
            }
        }
    }
 
    vm = Vue.createApp(Counter).mount('#app')
 
</script>

  

4、Attribute(v-bind)

Mustache 语法不能在 HTML attribute 中使用,然而,可以使用 v-bind 指令进行绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id="app">
 
    <p><a :href="link">{{site}}</a></p>
    <p><a v-bind:href="link">{{site}}</a></p>
    <p>
        <input type="text" v-model="site">
        <input type="text" v-model="link">
    </p>
</div>
 
<script>
 
    const Counter = {
        data() {
            return {
                site: "百度",
                link: "http://www.baidu.com"
            }
        }
    }
 
    vm = Vue.createApp(Counter).mount('#app')
 
</script>

 

v-bind:属性名 简写格式 :属性名

指令的意思是:“将这个元素节点的 href attribute 和 Vue 实例的 link property 保持一致”。

 

5、使用 JavaScript 表达式

迄今为止,在我们的模板中,我们一直都只绑定简单的 property 键值。但实际上,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div id="app">
    <p> {{ number + 1 }}</p>
    <p> {{ ok ? 'YES' : 'NO' }}</p>
    <p> {{ msg.split('').reverse().join('') }}</p>
    <div v-bind:id="'list-' + id">{{id}}</div>
</div>
 
<script>
 
    const Counter = {
        data() {
            return {
                number:100,
                ok:"NO",
                msg: "hello world",
                id:3,
            }
        }
    }
 
    vm = Vue.createApp(Counter).mount('#app')
 
</script>

  

这些表达式会在当前活动实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式,不能是js语句,所以下面的例子都不会生效。

1
2
3
4
5
<!--  这是语句,不是表达式:-->
{{ var a = 1 }}
 
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}

  

二、样式绑定(class与style)

1、class属性操作

操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是 attribute,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。

 (1)对象语法

我们可以传给 :class (v-bind:class 的简写) 一个对象,以动态地切换 class:

1
<div :class="{ active: isActive }"></div>

  

上面的语法表示 active 这个 class 存在与否将取决于数据 property isActive 的 truthiness

你可以在对象中传入更多字段来动态切换多个 class。此外,:class 指令也可以与普通的 class attribute 共存。当有如下模板:

1
2
3
4
<div
  class="static"
  :class="{ active: isActive, 'text-danger': hasError }"
></div>

  

和如下 data:

1
2
3
4
5
6
data() {
  return {
    isActive: true,
    hasError: false
  }
}

  

渲染结果为:

1
<div class="static active"></div>

  

当 isActive 或者 hasError 变化时,class 列表将相应地更新。例如,如果 hasError 的值为 true,class 列表将变为 "static active text-danger"

绑定的数据对象不必内联定义在模板里:

1
<div :class="classObject"></div>

  

1
2
3
4
5
6
7
8
data() {
  return {
    classObject: {
      active: true,
      'text-danger': false
    }
  }
}

  

渲染的结果和上面一样。我们也可以在这里绑定一个返回对象的计算属性。这是一个常用且强大的模式:

1
<div :class="classObject"></div>

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
data() {
  return {
    isActive: true,
    error: null
  }
},
computed: {
  classObject() {
    return {
      active: this.isActive && !this.error,
      'text-danger': this.error && this.error.type === 'fatal'
    }
  }
}

  

(2)数组语法

我们可以把一个数组传给 :class,以应用一个 class 列表:

1
<div :class="[activeClass, errorClass]"></div>

  

1
2
3
4
5
6
data() {
  return {
    activeClass: 'active',
    errorClass: 'text-danger'
  }
}

  

渲染的结果为:

1
<div class="active text-danger"></div>

  

如果你想根据条件切换列表中的 class,可以使用三元表达式:

1
<div :class="[isActive ? activeClass : '', errorClass]"></div>

  

这样写将始终添加 errorClass,但是只有在 isActive 为 truthy[1] 时才添加 activeClass

不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:

1
<div :class="[{ active: isActive }, errorClass]"></div>

  

2、style属性操作

(1)对象语法

:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:

1
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

  

1
2
3
4
5
6
data() {
  return {
    activeColor: 'red',
    fontSize: 30
  }
}

  

直接绑定到一个样式对象通常更好,这会让模板更清晰:

1
<div :style="styleObject"></div>

  

1
2
3
4
5
6
7
8
data() {
  return {
    styleObject: {
      color: 'red',
      fontSize: '13px'
    }
  }
}

  

同样的,对象语法常常结合返回对象的计算属性使用。

 

(2)数组语法

:style 的数组语法可以将多个样式对象应用到同一个元素上:

1
<div :style="[baseStyles, overridingStyles]"></div>

  

三、条件渲染

1、v-if

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。也可以用 v-else 添加一个“else 块”:

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
<div id="app">
    <div>
        <h3>if-else</h3>
        <div v-if="age>18">成年影视</div>
        <div v-else>青少年影视</div<!--  if和else要紧挨着-->
        <input type="text" v-model="age">
    </div>
 
    <h3>if-else-if</h3>
    <div>
         <div v-if="score>90">优秀</div>
         <div v-else-if="score>80">良好</div>
         <div v-else-if="score>60">及格</div>
         <div v-else>不及格</div>
         <input type="text" v-model="score">
 
    </div>
 
</div>
 
<script>
 
    Vue.createApp({
        data() {
            return {
                age: 10,
                score: 80,
            }
        },
 
    }).mount('#app')
</script>

  

2、v-show

另一个用于条件性展示元素的选项是 v-show 指令。用法大致一样:

1
<h1 v-show="ok">Hello!</h1>

  

不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS property display

注意,v-show 不支持 <template> 元素,也不支持 v-else

 

3、v-if vs v-show

v-if 是“真正”的条件渲染,因为它会确保在切换过程中,条件块内的事件监听器和子组件适当地被销毁和重建。

v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

 

四、循环渲染(v-for)

1、数组循环

我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app">
       <ul>
           <!--           v-for 还支持一个可选的第二个参数,即当前项的索引。-->
           <li v-for="stu,index in students">序号:{{index}} 姓名: {{stu.name}}  年龄:{{stu.age}}</li>
       </ul>
</div>
 
<script>
 
    Vue.createApp({
        data() {
            return {
                students:[{"name":"yuan","age":22},{"name":"rain","age":24},{"name":"eric","age":21}]
            }
        },
 
    }).mount('#app')
</script>

  

2、对象循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app">
       <ul>
<!--           提供第二个的参数为 property 名称 (也就是键名 key)-->
           <li v-for="val,key in student">{{key}} ::: {{val}}</li>
       </ul>
</div>
 
<script>
 
    Vue.createApp({
        data() {
            return {
                student:{"name":"yuan","age":22}
            }
        },
 
    }).mount('#app')
</script>

  

3、练习 —— 将所有书籍中价格大于100元的背景变蓝色

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.1.2/vue.global.js"></script>
    <style>
        body {
            font-size: 14px;
        }
 
        table, tr, th, td {
            border: 1px solid red;
            border-collapse: collapse; /* 合并边框 */
        }
 
        th, td {
            width: 200px;
            text-align: center; /* 文本水平居中 */
            height: 30px;
            line-height: 30px;
        }
 
        input {
            width: 80px;
        }
 
        .active{
            background-color: lightskyblue;
        }
    </style>
</head>
<body>
 
<div id="app">
 
    <table>
        <tr>
            <th>序号</th>
            <th>书籍名称</th>
            <th>价格</th>
        </tr>
 
        <tr v-for="book,index in books" :class="book.price > 100?active:''">
            <td>{{index + 1}}</td>
            <td>{{book.name}}</td>
            <td>{{book.price}}</td>
        </tr>
 
    </table>
</div>
 
<script>
 
    Vue.createApp({
        data() {
            return {
                books: [
                    {"name": "python入门", "price": 150},
                    {"name": "python进阶", "price": 100},
                    {"name": "python高级", "price": 75},
                    {"name": "python研究", "price": 60},
                    {"name": "python放弃", "price": 110},
                ],
                active:"active"
            }
        },
 
    }).mount('#app')
</script>
 
</body>
</html>

 

 注意我们不推荐在同一元素上使用 v-if 和 v-for

 

posted @   映辉  阅读(154)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示