目录
插值语法
- 多数情况下,
Vue.js 3
使用HTML模板(template
)语法,通过声明式将组件开发实例的数据与DOM绑定在一起。模板语法的核心是插值(mustache
)语法和指令。在Vue.js 3
中,要将数据显示到模板中,常见的方式是使用插值语法,也称双大括号语法 - 下面的代码演示了插值语法的具体应用
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<h4> {{ message }} - {{ isShow }}</h4>
<h4> {{ counter * 100 }}</h4>
<h4> {{ message.split(" ").join(",")}}</h4>
<h4> {{ getReverseMessage() }} </h4>
<h4> {{ isShow ? "三元运算符": ""}}</h4>
<button @click="toggle">切换控制显示</button>
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: 'Hello World',
counter: 100,
isShow: true,
}
},
methods: {
getReverseMessage() {
return this.message.split(" ").reverse().join(" ")
},
toggle() {
this.isShow = !this.isShow
}
}
}
Vue.createApp(App).mount('#app')
</script>
</body>
</html>
-
效果如下
-
上述例子说明插值语法支持绑定
data
中的属性、还支持javascript
表达式、调用方法、三元运算符等
基本指令
- 在
template
中,我们会经常看到以v-
开头的属性(attribute
),它们被称为指令,通常,指令带有前缀v-
,意味着这是Vue.js 3
提供的特殊属性。它们会在渲染的DOM上应用特殊的响应式行为。下面介绍几种常见的指令
v-once
v-once
指令用于指定元素或组件只渲染一次。当数据发生变化时,元素或组件及其所有的子组件将被视为静态内容,跳过更新。通常在需要进行性能优化时使用v-once
指令
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<h2>h2 : {{ counter }}</h2>
<!-- 下面的内容只会被渲染一次-->
<h3 v-once>h3 : {{ counter }}</h3>
<div v-once>
<h4>h4 : {{ counter }}</h4>
<h5>h5 : {{ message }}</h5>
</div>
<!-- 点击触发重新渲染-->
<button @click="increment">+1</button>
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
template: "#my-app",
data() {
return {
counter: 100,
message: "Hello World!"
}
},
methods: {
increment() {
this.counter += 1
}
}
}
Vue.createApp(App).mount("#app")
</script>
</body>
</html>
- 效果如下,只有
<h2>
标签的元素会被重新渲染,其他的都只渲染一次
v-text
v-text
指令用于更新元素的textContent
,也就是说,实际上v-text
指令就相当于插值语法
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<!-- 这两种用法效果一样-->
<h2 v-text="message"></h2>
<h2> {{ message }}</h2>
</template>
</body>
<script src="./js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World"
}
}
}
Vue.createApp(App).mount('#app')
</script>
</html>
v-html
- 当展示的内容是HTML字符串时,Vue.js 3不会对其进行特殊的解析。如果希望HTML字符串的内容可以被Vue.js 3解析出来,那么可以使用
v-html
指令,如下所示
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<!-- 这段代码会将message对应的HTML代码解析出来-->
<h2 v-html="message"></h2>
<h2> {{ message }}</h2>
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: '<span style="color: red; background: blue"> Hello Vue.js 3</span>'
}
}
}
Vue.createApp(App).mount('#app')
</script>
</body>
</html>
v-pre
v-pre
指令用于跳过元素及其子元素的编译过程,从而加快编译速度,如下所示
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<h2 v-pre> {{ message }}</h2>
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World"
}
}
}
Vue.createApp(App).mount('#app')
</script>
</body>
</html>
- 上面的代码会原样显示
{``{ message }}
,而不会显示message
的值,因为绑定v-pre
指令后的<h2>
元素和它的子元素将会跳过编译过程
v-cloak
- v-cloak指令需要隐藏未编译的
mustache
标签,直到组件实例完成编译。它需要和CSS规则一起使用,例如[v-cloak] { display: none}
- 在Vue.js 3中,这个指令的使用频率不高。因为生产阶段的模板已提前编译完成,所以不需要使用
v-cloak
指令
v-bind
1. 绑定基本属性
- 上面的指令用于为元素绑定内容,元素除了绑定内容之外,还需要绑定各种各样的属性。此时,可以使用
v-bind
指令来绑定这些属性 - 很多时候,元素的属性是动态的,比如
<a>
元素的href
属性、<img>
元素的src属性等。通常需要动态插入值,这时可以使用v-bind
指令来绑定这些属性
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<img v-bind:src="imgUrl" alt="">
<a v-bind:href="link">百度一下</a>
<img :src="imgUrl" alt="" sty>
<img src="imgUrl" alt="">
</template>
<script src="./js/vue.js"></script>
<script>
const app = {
template: '#my-app',
data() {
return {
imgUrl: "https://v2.cn.vuejs.org/images/logo.svg",
link: "https://www.baidu.com"
}
}
}
Vue.createApp(app).mount('#app')
</script>
</body>
</html>
- :是
v-bind
指令的简写,:src="imgUrl"
的意思就是把imgUrl变量绑定到src属性上
2. 绑定class属性
v-bind
可以用于绑定元素或者组件的class属性,支持绑定的类型有字符串、对象和数组类型。代码示例如下
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<div :class="'abc'">class绑定字符串1</div>
<div :class="className">class绑定字符串2</div>
<div :class="{'active': isActive}">class绑定对象1</div>
<div :class="{active: isActive, title: true}">class绑定对象2</div>
<div class="abc cba" :class="{active: isActive, title: true}">默认class和动态class结合</div>
<div class="abc cba" :class="classObj">绑定属性中的对象</div>
<div class="abc cba" :class="getClassObj()">绑定methods/computed返回的对象</div>
<button @click="toggle()">切换isActive</button>
</template>
<script src="./js/vue.js"></script>
<script>
const app = {
template: '#my-app',
data() {
return {
className: "hello world",
isActive: true,
classObj: {
active: true,
title: true
}
}
},
methods: {
toggle() {
this.isActive = !this.isActive
},
getClassObj() {
return {
active: false,
title: true
}
}
}
}
Vue.createApp(app).mount('#app')
</script>
</body>
</html>
- 此外v-bind还可绑定其他类型。具体可以参考其他资料
v-on
- 交互是前端开发非常重要的一部分,,例如处理单击、拖拽、键盘事件等。在Vue.js 3中,使用v-on指令可以实现对这些事件的监听,这个指令简写为@
1. 绑定事件
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<button v-on:click="btn1Click">监听按钮单击(完整写法)</button>
<div class="area" v-on:mousemove="mouseMove">监听鼠标移动事件</div>
<!-- @是v-on的语法糖-->
<button @click="btn1Click">监听按钮点击(简写)</button>
<button @click="counter++">单击+1: {{ counter }}</button>
<div class="area" v-on="{click: btn1Click, mousemove: mouseMove}">监听鼠标移动事件</div>
<div class="area" @="{click: btn1Click, mousemove: mouseMove}">监听鼠标移动事件(简写)</div>
</template>
<script src="./js/vue.js"></script>
<script>
const app = {
template: '#my-app',
data() {
return {
message: 'Hello World',
counter: 100
}
},
methods: {
btn1Click() {
console.log('按钮1发生了单击')
},
mouseMove() {
console.log('鼠标移动')
}
}
}
Vue.createApp(app).mount('#app')
</script>
</body>
</html>
2. 事件对象和传递参数
- 事件在发生时会产生事件对象,我们可以在事件回调函数中获取事件对象,还是用上面的例子,但是
btn2Click
加了个name参数,$event
是固定写法,专门用于获取事件对象
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<button v-on:click="btn1Click">监听按钮单击(完整写法)</button>
<div class="area" v-on:mousemove="mouseMove">监听鼠标移动事件</div>
<!-- @是v-on的语法糖-->
<button @click="btn2Click($event, 'hello')">监听按钮点击(简写)</button>
<button @click="counter++">单击+1: {{ counter }}</button>
<div class="area" v-on="{click: btn1Click, mousemove: mouseMove}">监听鼠标移动事件</div>
<div class="area" @="{click: btn1Click, mousemove: mouseMove}">监听鼠标移动事件(简写)</div>
</template>
<script src="./js/vue.js"></script>
<script>
const app = {
template: '#my-app',
data() {
return {
message: 'Hello World',
counter: 100
}
},
methods: {
btn1Click(event) {
console.log(event);
},
btn2Click(event, name) {
console.log(event, name)
},
mouseMove() {
console.log('鼠标移动')
}
}
}
Vue.createApp(app).mount('#app')
</script>
</body>
</html>
3. 修饰符
- 在JavaScript中,可通过
event.stopPropagation
阻止事件冒泡;在Vue.js 3中,可使用v-on
指令的.stop修饰符阻止事件冒泡
html
...
<template id="my-app">
<div @click="divClick" :style="{width: '100px', 'height': '65px', backgroundColor:'#ddd'}"
>
div
<!-- 如果不用.stop修饰符, 那么触发完这个button, 事件会冒泡到父级组件中, 也就是会触发divClick函数-->
<button @click.stop="btnClick">button按钮</button>
</div>
<!-- .enter修饰符的作用是只有用户输入enter的时候, 才会触发enterKeyup函数的回调-->
<input type="text" @keyup.enter="enterKeyup">
</template>
<script src="./js/vue.js"></script>
<script>
const app = {
template: '#my-app',
data() {
return {
message: 'Hello World',
counter: 100
}
},
methods: {
divClick() {
console.log('divClick')
},
btnClick() {
console.log('btnClick')
},
enterKeyup(event) {
console.log('keyup', event.target.value)
}
}
}
Vue.createApp(app).mount('#app')
</script>
...
- 如上面代码的演示
条件渲染
- 在前端开发中,有时需要根据当前条件决定是否渲染特定的元素或组件。Vue.js 3提供了
v-if,v-else,v-else-if,v-show
指令,用于实现条件判断
v-if
- 下面的代码实现了单击按钮的时候切换显示和隐藏上面
<h2>
标签内容的功能
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<h2 v-if="isShow">v-if条件渲染基本使用</h2>
<button @click="toggle()">单击切换显示和隐藏内容</button>
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
isShow: true
}
},
methods: {
toggle() {
this.isShow = !this.isShow
}
}
}
Vue.createApp(App).mount('#app')
</script>
</body>
</html>
- 使用v-if指令时,必须将其添加到某一个元素上,,例如
<div>
元素等,但是如果希望显示和隐藏多个元素,有两种常见的实现方式。第一种是使用<div>
元素包裹多个元素,然后使用v-if
指令控制该<div>
元素的显示和隐藏即可,缺点是<div>
元素也会被渲染;第二种实现方式是使用HTML5的<template>
包裹多个元素,优点是<template>
元素不会被渲染出来,也就是说template
不会出现在最终的DOM中,这可以通过js的document.getElementById
方法验证。推荐是使用这种方式
v-show
v-show
也可以用于控制显示和隐藏某一块内容,用法和v-if
一致,区别如下
v-show
不支持在<template>
标签上使用v-show
不可与v-else
一起使用v-show
控制的元素无论是否需要显示到浏览器上,它的DOM都会被渲染。本质上是通过CSS的display属性来控制显示和隐藏- 当
v-if
的条件为false时,对应的元素不会被渲染到DOM中
开发过程中的选择建议如下
- 如元素需要在显示和隐藏之间频繁切换,则使用
v-show
- 如不需要频繁切换显示和隐藏,则使用
v-if
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<h2 v-if="isShow">v-if控制显示和隐藏</h2>
<h2 v-show="isShow">v-show控制显示和隐藏</h2>
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
isShow: false
}
}
}
Vue.createApp(App).mount('#app')
</script>
</body>
</html>
- 可以看到第一个
<h2>
不会被渲染到DOM中,第二个<h2>
通过CSS的display属性来控制显示和隐藏
列表渲染
- 在真实的开发过程中,通常需要从服务器获取一组数据并渲染到页面上。这是可以使用Vue.js 3中的
v-for
指令来实现。v-for
指令类似于JavaScript中的for循环,可以用于遍历一组数据,并将每个元素渲染到页面上
v-for
- 在Vue.js 3中,使用v-for指令语法的方式为
v-for="item in 数组"
或v-for="(item, index) in 数组"
- 数组:通常来自
data
或prop
,也可以来自methods
和computed
- item:可以给数组中的每项元素起一个别名,这个别名可以自行命名。
item
在循环过程中代表当前遍历到的数组元素 - index:表示当前元素在数组中的索引位置
- 代码示例如下所示
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<h2>遍历数组</h2>
<ul>
<li v-for="j in my_list">
{{ j }}
</li>
</ul>
<ul>
<li v-for="(my_l, index) in my_list">
{{index + 1}}.{{my_l}}
</li>
</ul>
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
my_list: [
'first',
'second',
'third'
]
}
}
}
Vue.createApp(App).mount('#app')
</script>
</body>
</html>
- 此外
v-for
还支持对象类型和数字类型的遍历
数组的更新检测
- 在data中定义的变量属于响应式变量,修改这些变量时会自动触发视图的更新。对于定义为数组类型的响应式变量,在调用
filter()
、concat()
和slice()
方法时不会触发视图更新,而调用push()
、pop()
等方法会触发 - 可以用下面的代码来进行测试
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<h2>遍历数组</h2>
<ul>
<li v-for="(my_l, index) in my_list">
{{index + 1}}.{{my_l}}
</li>
</ul>
<input type="text" v-model="new_list">
<button @click="addToList">添加</button>
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
my_list: [
'first',
'second',
'third'
],
new_list: ""
}
},
methods: {
addToList() {
this.my_list.push(this.new_list)
this.new_list = ""
}
}
}
Vue.createApp(App).mount('#app')
</script>
</body>
</html>