二、Vue.js 基础语法
1.1 插值
文本
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:
<h2>{{ message }}</h2>
Mustache 标签将会被替代为对应数据对象上 message property 的值。无论何时,绑定的数据对象上 message property 发生了改变,插值处的内容都会更新。
除了可以绑定简单的 property 键值。对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。
有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效。
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>{{ message }}</h2>
<h2>{{ message }}, World</h2>
<!-- Mustache 语法中,不仅仅可以直接写变量,也可以写简单的表达式 -->
<h2>{{ firstName + lastName }}</h2>
<h2>{{ firstName + ' ' + lastName }}</h2>
<h2>{{ firstName }} {{lastName }}</h2>
<h2>{{ count * 2}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'Hello',
firstName: 'Wang',
lastName: 'Zhao',
count: 100
}
})
</script>
</body>
</html>
v-once
Vue 是响应式的,当绑定的数据对象对应的 property 发生了改变,插值处的内容都会更新。
但是,在某些情况下,我们可能不希望界面随意的跟随改变。这个时候我们就可以使用 Vue 的指令(指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM) v-once
。
- 该指令后面不需要跟任何表达式(比如之前的
v-for
后面是有跟表达式的) - 该指令表示元素和组件只渲染一次,不会随着数据的改变而改变。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
<h1 v-once>{{ message }}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'Hello'
}
})
</script>
</body>
</html>
v-html
某些情况下,我们从服务器请求的数据本身就是一个 HTML 代码,如果我们直接通过{{ }}
来输出,会将 HTML代码也一起输出。
但是我们希望可以安装 HTML 格式进行解析,并且显示对应的内容,则可以通过v-html
指令。
- 该指令后面往往会跟上一个
string
类型 - 会将
string
的 html 解析出来并进行渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>{{ url }}</h2>
<h2 v-html="url"></h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
url: "<a href='www.baidu.com'>百度</a>"
}
})
</script>
</body>
</html>
v-text
v-text
作用和 Mustache
比较相似:都是用户将数据显示在界面中,但是需要注意的是,v-text
会替换掉标签内的整个内容。
v-text
通常情况下,接受一个 string
类型。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>{{ message }}</h2>
<h2 v-text="message"></h2>
<h2>{{ message }} WangZhao</h2>
<h2 v-text="message">WangZhao</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: "Hello World"
}
})
</script>
</body>
</html>
v-pre
v-pre
用于跳过这个元素和它子元素的编译过程,显示原本的 Mustache
语法。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>{{ message }}</h2>
<h2 v-pre>{{ message }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'Hello'
}
})
</script>
</body>
</html>
v-cloak
在某些情况下,我们浏览器可能会直线显示出未编译的Mustache
标签。
为了避免这种闪动的现象,我们可以使用v-cloak
指令。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
{{ message }}
</div>
<script src="../js/vue.js"></script>
<script>
// 在vue解析之前,div中有一个属性 v-cloak
// 在vue解析之后,div中没有一个属性 v-cloak
setTimeout(function(){
const app = new Vue({
el: '#app',
data: {
message: 'Hello'
}
})
}, 1000)
</script>
</body>
</html>
1.2 动态绑定属性
前面所学习的指令主要作用是将值拆入到模板的内容当中。
但是,除了内容需要动态来决定外,某些属性我们也希望动态来绑定。
- 比如动态绑定
a
元素的href
属性 - 比如动态绑定
img
元素的src
属性
这个使用我们可以使用v-bind
指令:
- 作用:动态绑定属性
- 缩写:
:
v-bind
v-bind
用于半丁一个或多个属性值,或者项另一个组件传递props
。
在开发中,有哪些属性需要动态进行绑定呢?
- 图片的链接
src
- 网站的链接
href
- 动态绑定一些类、样式等
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 错误的做法:这里不可以使用 mustache 语法 -->
<!-- <a v-bind:href="{{ url }}">百度</a> -->
<!-- 正确的做法:使用 v-bind 指令 -->
<a v-bind:href="url">百度</a>
<!-- v-bind 可以缩写为 : -->
<a :href="url">百度</a>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
url: 'http://www.baidu.com'
}
})
</script>
</body>
</html>
1.3 Class 与 Style 绑定
操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是 attribute
,所以我们可以用 v-bind
处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind
用于 class
和 style
时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
绑定 HTML Class
很多时候,我们希望动态的来切换class
,比如:
- 当数据为某个状态时,字体显示红色
- 当数据为另一个状态时,字体显示黑色
对象语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.active {
color: red;
}
</style>
</head>
<body>
<div id="app">
<h2 :class="{active: isActive}">{{ message }}</h2>
</div>
<script src="../../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: "hello",
isActive: true
}
})
</script>
</body>
</html>
上面的语法表示 active
这个 class
存在与否将取决于数据 property isActive
。
当isActive
为true
时,我们查看对应的代码,可以看到active
这个class
确实存在。
接着我们将isActive
的值改为false
,可以看到active
这个class
确实也已经消失了。
数组语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.active {
color: red;
}
.fontStyle {
font-size: 50px;
}
</style>
</head>
<body>
<div id="app">
<h2 :class="[aClass, bClass]">{{ message }}</h2>
</div>
<script src="../../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
aClass: 'active',
bClass: 'fontStyle',
message: 'Hello',
}
})
</script>
</body>
</html>
绑定内联样式
我们可以利用 v-bind:style
来绑定一些 CSS 内联样式。
在写 CSS 属性名的时候,比如 font-size
- 我们可以使用使用驼峰式(camelCase)
fontSize
- 或短横线分割(kebab-case)
font-size
对象语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- '50px' 必须加上单引号,否则是当作一个变量去解析 -->
<!-- <h2 :style="{fontSize: '50px'}">{{ message }}</h2> -->
<!-- finalSize 当成要给变量使用 -->
<h2 :style="{fontSize: finalSize, color: finalColor}">{{ message }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'Hello',
finalSize: '50px',
finalColor: 'red'
}
})
</script>
</body>
</html>
数组语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2 :style="[style1, style2]">{{ message }}</h2>
</div>
<script src="../../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'Hello',
style1: {fontSize: '50px'},
style2: {color: 'red'}
}
})
</script>
</body>
</html>
1.4 计算属性
我们知道,在模板中可以直接通过插值语法显示一些 data 中的数据。
但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示。
- 比如我们有
firstName
和lastName
两个变量,我们需要显示完整的名称。 - 但是如果多个地方都需要显示完整的名称,我们就需要写多个
{{firtstName}} {{lastName}}
基本使用
我们可以将上面的代码换成计算属性:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>{{ firstName + ' ' + lastName }}</h2>
<h2>{{ firstName }} {{ lastName }}</h2>
<h2>{{ getFullName() }}</h2>
<h2>{{ fullName }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Wang',
lastName: 'Zhao'
},
computed: {
fullName: function() {
return this.firstName + ' ' + this.lastName;
}
},
methods: {
getFullName() {
return this.firstName + ' ' + this.lastName;
}
},
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>总价格:{{ totalPrice }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
books: [
{id: 110, name: 'Unix编程艺术', price: 119},
{id: 111, name: '代码大全', price: 120},
{id: 112, name: '深入理解计算机原理', price: 100},
{id: 113, name: '现代操作系统', price: 99},
]
},
computed: {
totalPrice: function() {
let result = 0;
for(var i = 0; i < this.books.length; i++) {
result += this.books[i].price;
}
return result;
}
},
})
</script>
</body>
</html>
setter 和 getter
每个计算属性都包含一个getter
和一个setter
- 在上面的例子中,我们只是使用
getter
来读取 - 在某些情况下,你也可以提供一个
setter
方法 - 在需要写
setter
的时候,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
{{ fullName }}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Wang',
lastName: 'Zhao'
},
computed: {
// fullName: function() {
// return this.firstName + ' ' + this.lastName;
// }
// 计算属性一般没有 set 方法,只读属性
fullName: {
set: function(newValue) {
const names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[1];
},
get: function() {
return this.firstName + ' ' + this.lastName;
}
}
},
})
</script>
</body>
</html>
计算属性的缓存
我们可能会考率这样的一个问题:
methods
和computed
看起来都可以实现我们的功能,那么为什么还要多一个计算属性这个东西呢?- 原因:计算属性是基于它们的响应式依赖进行缓存的,只在相关响应式依赖发生改变时它们才会重新求值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
<h2>{{ getFullName() }}</h2>
<h2>{{ getFullName() }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Wang',
lastName: 'Zhao'
},
computed: {
fullName: function() {
console.log('computed');
return this.firstName + ' ' + this.lastName;
}
},
methods: {
getFullName() {
console.log('method');
return this.firstName + ' ' + this.lastName;
}
},
})
</script>
</body>
</html>
1. 5 事件监听
在前端开发中,我们需要经常和用户交互。
- 这个时候,我们就必须监听产生的事件,比如点击、拖拽、键盘事件等
- 在 Vue 中如何监听事件呢?使用
v-on
指令- 作用:绑定事件监听器
- 缩写:
@
基本使用
这里,我们用一个监听按钮的点击事件,来查看v-on
的使用
- 下面的代码中,我们使用了
v-on:click="counter++"
- 另外,我们可以将事件指向一个在
methods
中定义的函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>{{ counter }}</h2>
<button v-on:click="counter++">+</button>
<!-- v-on:click可缩写为 @click -->
<button @click="decrement">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increment() {
this.counter++;
},
decrement() {
this.counter--;
}
}
})
</script>
</body>
</html>
参数
当通过methods
中定义方法时,以供@click
调用时,需要注意参数问题。
- 如果该方法不需要额外参数,那么方法后的
()
可以不添加。但是注意:如果方法本身中有一个参数,那么默认将原生事件event
参数传递进行。 - 如果需要同时传入某个参数,同时需要
event
时,可以通过$event
传入事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 事件调用的方法没有参数 -->
<button @click="btn1Click()">按钮1</button>
<button @click="btn1Click">按钮1</button>
<!--
在事件定义时,写方法时省略了小括号,但是方法本身是需要一个函数的时候,
Vue 会默认将浏览器产生的 event 事件对象作为参数传入到方法
-->
<button @click="btn2Click">按钮2</button>
<!--
方法定义时,我们需要 event 对象,同时又需要其他参数,
在调用方法时,如何手动获取到浏览器参数 event 对象:$event
-->
<button @click="btn3Click(111, $event)">按钮3</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
},
methods: {
btn1Click() {
console.log('btn1Click');
},
btn2Click(val) {
console.log(val);
},
btn3Click(val1, event) {
console.log(val1);
console.log(event);
}
}
})
</script>
</body>
</html>
修饰符
- 在某些情况下,我们拿到
event
的目的可能是进行一些事件处理 - Vue 提供了修饰符来帮助我们方便的处理一些事件:
.stop
- 调用event.stopPropagation()
.prevent
- 调用event.preventDefault()
.{keyCode | keyAlias}
- 只当事件是从特带你键触发时才触发回调。.navtive
- 监听组件根元素的原生事件.once
- 只触发一次回调。
<!-- 停止冒泡 -->
<button @click.stop=""></button>
<!-- 阻止默认行为 -->
<button @click.prevent=""></button>
<!-- 阻止默认行为,没有表达式 -->
<form @submit.prevent></form>
<!-- 串联修饰符 -->
<button @click.stop.prevent=""></button>
<!-- 键修饰符,键别名 -->
<input @keyup.enter="">
<!-- 键修饰符,键代码 -->
<input @keyup.13="">
<!-- 点击回调只会触发一次 -->
<button @click.once=""></button>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div @click="divClick">
<button @click.stop="btnClick">按钮</button>
</div>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
},
methods: {
btnClick() {
console.log("btnClick");
},
divClick() {
console.log("divClick");
}
}
})
</script>
</body>
</html>
1.6 条件判断
v-if
、v-else-if
、v-else
- 这三个指令与
JavaScript
的条件语句if
、else if
、else
类型 - Vue 的条件指令可以根据表达式的值在 DOM 中渲染或销毁元素或组件。
v-if
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2 v-if="isShow">{{ message }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'Hello',
isShow: true
},
})
</script>
</body>
</html>
当条件为false
时,效果如下:
v-if
的原理:
v-if
后面的条件为 false 时,对应的元素以及其子元素不会渲染- 也就是根本不会有对应的标签出现在 DOM 中
v-else
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2 v-if="isShow">Hello</h2>
<h2 v-else>World</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
isShow: false
}
})
</script>
</body>
</html>
将条件修改为true
,效果如下:
v-else-if
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
当前成绩:{{ score }}
<h2 v-if="score >= 90">有秀</h2>
<h2 v-else-if="score >= 70">良好</h2>
<h2 v-else-if="score >= 60">及格</h2>
<h2 v-else>较差</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
score: 100
}
})
</script>
</body>
</html>
v-show
v-show
的用法和v-if
非常类似,也用于决定一个元素是否渲染。
v-if
和v-show
对比:
v-if
当条件为false
时,压根不会有对应的元素在DOM
中v-show
当条件为false
时,仅仅是将元素的display
属性设置为none
而已。
开发中如何选择?
- 当需要在显示与隐藏之间切换很频繁时,使用
v-show
- 当只有一次切换时,使用
v-if
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!--
v-if:当条件为 false 时,包含 v-if 指令的元素,根本就步步i存在 dom 中
v-show:当条件为 false 时,v-show 只是给我们的元素添加一个行内样式:display: none
-->
<h2 v-show="isShow">Hello</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
isShow: false
}
})
</script>
</body>
</html>
将v-show
条件改为true
时,效果如下:
1.6 循环遍历
当我们有一组数据需要进行渲染时,可以使用v-for
来完成
v-for
v-for
的语法类似于JavaScript
中的for
循环- 格式如下:
item in items
的形式
如果在遍历的过程中,我们需要拿到元素在数组中的索引值
- 语法格式:
(item, index) in tems
- 其中的
index
就代表了取出的item
在数组中的索引值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 遍历的过程中,没有使用索引值 -->
<ul>
<li v-for="item in names">{{ item }}</li>
</ul>
<!-- 遍历的过程中,获取索引值 -->
<ul>
<li v-for="(item,index) in names">{{ index }}.{{ item }}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
names: ['aaa', 'bbb', 'ccc']
}
})
</script>
</body>
</html>
v-for 遍历对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<ul>
<!-- 1.在遍历对象的过程中,如果只是获取一个值,那么获取到的是 value -->
<li v-for="item in info">{{ item }}</li>
</ul>
<ul>
<!-- 2. 获取 key、value 格式:(value, key) -->
<li v-for="(value, key) in info">{{ key }} : {{ value }}</li>
</ul>
<ul>
<!-- 3. 获取 key、value\index 格式:(value, key, index) -->
<li v-for="(value, key, index) in info">{{ key }} : {{ value }} : {{ index }}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
info: {
name: '王曌',
age: 22,
height: 1.72
}
}
})
</script>
</body>
</html>
key
官方推荐我们在使用v-for
时,给对应的元素或组件添加上一个:key
属性
为什么需要这个key
属性呢?
如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key
attribute:
<div v-for="item in items" v-bind:key="item.id">
<!-- 内容 -->
</div>
建议尽可能在使用 v-for
时提供key
attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
数组更新检测
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
但是,我们如果通过数组索引的方式修改数组,这个改变并不会被加入到响应式系统。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in array">{{ item }}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
array: ['a', 'b', 'c']
}
})
</script>
</body>
</html>
1.7 双向绑定
表单控件在实际开发中是非常常见的,特别是对于用户信息的提交,需要大量的表单。
v-model
Vue 中使用v-model
指令来实现表单元素和数据的双向绑定。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="message">
{{ message }}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'Hello'
}
})
</script>
</body>
</html>
-
当我们在输入框输入内容时
- 因为
input
中的v-model
绑定了message
,所以会试试将输入的内容传递给message
,message
发上了改变 - 当
message
发生改变时,因为上面我们使用Mustache
语法,将message
的值插入到DOM
中,所以DOM
会发生响应的改变。 - 由此,我们便实现了双向绑定通过
v-model
- 因为
-
v-model
其实是一个语法糖,它的本质上是包含两个操作:v-bind
绑定一个value
属性v-on
指令给当前元素绑定input
事件
<input type="text" v-model="message">
等同于
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
修饰符
lazy
修饰符:- 默认情况下,
v-model
默认是在input
事件中同步输入框的数据的。 - 也就是说,—旦有数据发生改变对应的
data
中的数据就会闫动发生改变。 lazy
修饰符可以让数据在失去焦点或者回车时才会更新
- 默认情况下,
number
修饰符:- 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。
- 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。
number
修饰符可以让在输入框中输入的内容自动转成数字类型
trim
修饰符:- 如果输入的内容首尾有很多空格,通常我们希望将其去除
trim
修饰符可以过滤内容左右两边的空格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 1、修饰符:lazy -->
<input type="text" v-model.lazy="message">
<h2>{{message}}</h2>
<!-- 2、修饰符:number -->
<input type="text" v-model.number="age">
<h2>{{typeof age}}</h2>
<!-- 3、修饰符:trim -->
<input type="text" v-model="name">
<h2>{{name}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '',
age: '',
name: ''
}
})
</script>
</body>
</html>