vue系统指令二
v-model:双向数据绑定
重点:双向数据绑定,只能用于表单元素,或者用于自定义组件。
之前的文章里,我们通过v-bind,给<input>
标签绑定了data
对象里的name
属性。当data
里的name
的值发生改变时,<input>
标签里的内容会自动更新。
可我现在要做的是:我在<input>
标签里修改内容,要求data
里的name
的值自动更新。从而实现双向数据绑定。该怎么做呢?这就可以利用v-model
这个属性。
区别:
- v-bind:只能实现数据的单向绑定,从 M 自动绑定到 V。
- v-model:只有
v-model
才能实现双向数据绑定。注意,v-model 后面不需要跟冒号,
注意:v-model 只能运用在表单元素中,或者用于自定义组件。常见的表单元素包括:input(radio, text, address, email…) 、select、checkbox 、textarea。
代码举例如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<style>
.father {
height: 300px;
width: 300px;
background: pink;
}
.child {
width: 200px;
height: 200px;
background: green;
}
</style>
</head>
<body>
<div id="test">
<form v-bind:action="url" >
<input type="text" v-bind:value="url" >
<input type="text" id="username" v-model="myAccount.username">
<input type="password" id="pwd" v-model="myAccount.userpwd">
<input type="submit" v-on:click="submit1" value="submit1">
</form>
</div>
<script>
var vm = new Vue({
el: '#test',
data: {
url: "http://www.baidu.com",
name: "dany",
myAccount: {userName: "wenqun", "pwd": 123456}
},
methods: {
submit1: function () {
alert(this.myAccount.userName + " pwd=" + this.myAccount.pwd);
}
}
})
</script>
</body>
</html>
v-model实现计算器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<style>
.father {
height: 300px;
width: 300px;
background: pink;
}
.child {
width: 200px;
height: 200px;
background: green;
}
</style>
</head>
<body>
<div id="test">
<input type="text" v-model="n1">
<select v-model="opt">
<option value="+"> + </option>
<option value="-"> - </option>
<option value="*"> * </option>
<option value="/"> / </option>
</select>
<input type="text" v-model="n2">
<input type="button" value="=" @click="calc">
<input type="text" v-model="result">
</div>
<script>
var vm = new Vue({
el: '#test',
data: {
n1: 0,
n2: 0,
result: 0,
opt: "+"
},
methods: {
// calc: function () {
// switch(this.opt){
// case "+":
// this.result = parseInt(this.n1) + parseInt(this.n2)
// break;
// case "-":
// this.result = parseInt(this.n1) - parseInt(this.n2)
// break;
// case "*":
// this.result = parseInt(this.n1) * parseInt(this.n2)
// break;
// case "/":
// this.result = parseInt(this.n1) / parseInt(this.n2)
// break;
// }
// }
calc(){
this.result = eval( 'parseInt(this.n1)' + this.opt + 'parseInt(this.n2)');
}
}
})
</script>
</body>
</html>
v-bind 绑定属性
设置CSS样式
传统我们给元素添加样式的方式如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.my-red {
color: red;
}
.my-thin {
/* 设置字体的粗细 */
font-weight: 200;
}
.my-italic {
font-style: italic;
}
.my-active {
/* 设置字符之间的间距 */
letter-spacing: 0.5em;
}
</style>
</head>
<body>
<h1 class="my-red my-thin">我是千古壹号,qianguyihao</h1>
</body>
</html>
上面的效果,我们还可以用Vue来写。这就引入了本段要讲的方式。
方式1: 数组
直接传递一个数组。注意:这里的 class 需要使用 v-bind 做数据绑定。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue2.5.16.js"></script>
<style>
.my-red {
color: red;
}
.my-thin {
/* 设置字体的粗细 */
font-weight: 200;
}
.my-italic {
font-style: italic;
}
.my-active {
/* 设置字符之间的间距 */
letter-spacing: 0.5em;
}
</style>
</head>
<body>
<div id="app">
<!-- 普通写法 -->
<h1 class="my-red my-thin">我是千古壹号,qianguyihao</h1>
<!-- vue的写法1:数组的形式 -->
<h1 :class="['my-red', 'my-thin']">我是qianguyihao,千古壹号</h1>
</div>
<script>
var vm = new Vue({
el: '#app'
});
</script>
</body>
</html>
上方代码中,注意,数组里写的是字符串;如果不加单引号,就不是字符串了,而是变量。
方式2: 三元表达式
<div id="test">
<h1 class="my-red my-thin">common mathod </h1>
<br>
<h1 v-bind:class="['my-red', 'my-thin']">vue method</h1>.
<br>
# 三元表达式
<h1 :class="[flag ? 'my-active':'']">sanyuan</h1>
</div>
<script>
var vm = new Vue({
el: '#test',
data:{
flag: false
}
});
</script>
方式三:在数组中使用 对象 来代替 三元表达式(提高代码的可读性)
上面的写法二,可读性较差。于是有了写法三。
写法三:在数组中使用对象来代替三元表达式。
代码如下:
<body>
<div id="app">
<!-- vue的写法3:在数组中使用对象来代替三元表达式。-->
<h1 :class="[ {'my-active':flag} ]">我是qianguyihao,千古壹号</h1>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
flag: true
}
});
</script>
</body>
方式四:直接使用对象
<!-- vue的写法4:直接使用对象-->
<!-- 在为 class 使用 v-bind 绑定 对象的时候,对象的属性是类名。由于 对象的属性名可带引号,也可不带引号,所以 这里我没写引号; 属性的值 是一个标识符 -->
<h1 :class="{style1:true, style2:false}">我是qianguyihao,千古壹号</h1>
上方代码的意思是,给<h1>
标签使用样式style1
,不使用样式style2
。注意:
1、既然class样式名是放在对象中的,这个样式名不能有中划线,比如说,写成:class="{my-red:true, my-active:false}
,是会报错的。
2、我们也可以对象通过存放在 data 的变量中。也就是说,上方代码可以写成:
<body>
<div id="app">
<!-- vue的写法4:直接使用对象-->
<!-- 在为 class 使用 v-bind 绑定 对象的时候,对象的属性是类名。由于 对象的属性名可带引号,也可不带引号,所以 这里我没写引号; 属性的值 是一个标识符 -->
<h1 :class="classObj">我是qianguyihao,千古壹号</h1>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
classObj:{style1:true, style2:false}
}
});
</script>
</body>
设置style行内样式
方式1:直接在元素上通过 :style
的形式,书写样式对象。
<h1 :style="{color: 'red', 'font-size': '20px'}">我是千古壹号,qianguyihao</h1>
方式2:将样式对象,定义到 data
中,并直接引用到 :style
中。
<body>
<div id="app">
<h1 :style="styleObj">我是千古壹号,qianguyihao</h1>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
styleObj: { color: 'red', 'font-size': '20px' }
}
});
</script>
</body>
方式3:写法二只用到了一组样式。如果想定义多组样式,可以用写法三。
<body>
<div id="app">
<h1 :style="[ styleObj1, styleObj2 ]">我是千古壹号,qianguyihao</h1>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
styleObj1: { color: 'red', 'font-size': '20px' },
styleObj2: { 'font-style': 'italic' }
}
});
</script>
</body>
v-for使用的几种方式
作用:
根据数组中的元素遍历指定模板内容生成内容。
比如说,如果我想给一个ul
中的多个li
分别赋值1、2、3…。如果不用循环,就要挨个赋值:
<body>
<div id="app">
<ul>
<li>{{list[0]}}</li>
<li>{{list[1]}}</li>
<li>{{list[2]}}</li>
</ul>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
list: [1, 2, 3]
}
});
</script>
为了实现上面的效果,如果我用v-for
进行赋值,代码就简洁很多了:
<div id="test">
<ul>
<li v-for="item in name">{{item}}</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#test',
data:{
name: ['dany','wenqun','tianzeng','larissa','wancy']
}
});
</script>
使用方式
方式1:普通数组的遍历
针对如下类型的数组:
<script>
new Vue({
el: '#app',
data: {
arr1: [2, 5, 3, 1, 1],
}
});
</script>
将数组中的值赋给li:
<div id="test">
<ul>
<li v-for="(item, indx) in name">{{item}} -----{{indx}}</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#test',
data:{
name: ['dany','wenqun','tianzeng','larissa','wancy']
}
});
</script>
效果如下
方式2:对象数组的遍历
如下数组形式
<script>
var vm = new Vue({
el: '#app',
data: {
//对象数组
dataList: [
{ name: 'smyh', age: '26' },
{ name: 'vae', age: '32' },
{ name: 'xiaoming', age: '20' }
]
}
});
</script>
遍历代码如下:
<div id="test">
<ul>
<li v-for="(item, indx) in dataList">{{item}}-------{{item.name}} ---{{item.age}}--{{indx}}</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#test',
data:{
dataList: [
{ name: 'smyh', age: '26' },
{ name: 'vae', age: '32' },
{ name: 'xiaoming', age: '20' }
]
}
});
</script>
方式3:对象的遍历
针对如下数组
<script>
new Vue({
el: '#app',
data: {
obj1: {
name: 'qianguyihao',
age: '26',
gender: '男'
}
}
});
</script>
<div id="test">
<ul>
<li v-for="(value, key, indx) in obj1">{{key}} ---{{value}}--{{indx}}</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#test',
data:{
obj1: {
name: 'qianguyihao',
age: '26',
gender: 'femal'
}
}
});
方式4:遍历数字、字符串
<div id="test">
<ul>
<li v-for="(value, key, indx) in obj1">{{key}} ---{{value}}--{{indx}}</li>
</ul>
<ul>
<!-- ??????? -->
<!-- ??:???? v-for ??????,??? myCount ?? 1 ???? -->
<li v-for="myCount in 10">{{myCount}}</li>
<li v-for="myCount in obj1.name">{{myCount}}</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#test',
data:{
obj1: {
name: 'qianguyihao',
age: '26',
gender: 'femal'
}
}
});
</script>
注意事项
注意:在 Vue 2.2.0+ 版本里,当在组件中使用 v-for 时,key 属性是必须要加上的。
这样做是因为:每次 for 循环的时候,通过指定 key 来标示当前循环这一项的唯一身份。
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。
key的类型只能是:string/number,而且要通过 v-bind 来指定。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue2.5.16.js"></script>
</head>
<body>
<div id="app">
<div>
<label>Id:
<input type="text" v-model="id">
</label>
<label>Name:
<input type="text" v-model="name">
</label>
<input type="button" value="添加" @click="add">
</div>
<!-- 注意: v-for 循环的时候,key 属性只能使用 number 或者 string -->
<!-- 注意: key 在使用的时候,必须使用 v-bind 属性绑定的形式,指定 key 的值 -->
<!-- 在组件中,使用v-for循环的时候,或者在一些特殊情况中,如果 v-for 有问题,必须 在使用 v-for 的同时,指定 唯一的 字符串/数字 类型 :key 值 -->
<p v-for="item in list" :key="item.id">
<input type="checkbox">{{item.id}} --- {{item.name}}
</p>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
id: '',
name: '',
list: [
{ id: 1, name: 'smyh' },
{ id: 2, name: 'vae' },
{ id: 3, name: 'qianguyihao' },
{ id: 4, name: 'xiaoming' },
{ id: 5, name: 'xiaohong' }
]
},
methods: {
add() { // 添加方法
this.list.unshift({ id: this.id, name: this.name })
}
}
});
</script>
</body>
</html>
v-if 设置元素的显示和隐藏
作用:
根据表达式的值的真假条件,来决定是否渲染元素,如果为false则不渲染(达到隐藏元素的目的),如果为true则渲染。
在切换时,元素和它的数据绑定会被销毁并重建。
举例:
举例如下:(点击按钮时,切换和隐藏盒子)
<div id="test">
<button v-on:click="toggle">show/hide</button>
<div v-if="flag">I'm a police</div>
</div>
<script>
var vm = new Vue({
el: '#test',
data:{
flag:true
},
methods: {
toggle() {
this.flag = !this.flag
}
}
});
</script>
点击button页面上的字会来回切换
v-show 设置元素的显示和隐藏(在元素上添加/移除style="display:none"
属性)
作用:
根据表达式的真假条件,来切换元素的 display 属性。如果为false,则在元素上添加 display:none
属性;否则移除display:none
属性。
举例
如下:(点击按钮时,切换和隐藏盒子)我们直接把上一段代码中的v-if
改成v-show
就可以了:
<div id="test">
<button v-on:click="toggle">show/hide</button>
<div v-show="flag">I'm a police</div>
</div>
<script>
var vm = new Vue({
el: '#test',
data:{
flag:true
},
methods: {
toggle() {
this.flag = !this.flag
}
}
});
</script>
与v-if的区别
- v-if:每次都会重新添加/删除DOM元素
- v-show:每次不会重新进行DOM的添加/删除操作,只是在这个元素上添加/移除
style="display:none"
属性,表示节点的显示和隐藏。
优缺点
- v-if:有较高的切换性能消耗。这个很好理解,毕竟每次都要进行dom的添加/删除操作
- v-show:有较高的初始渲染消耗。也就是说,即使一开始
v-show="false"
,该节点也会被创建,只是隐藏起来了。而v-if="false"
的节点,根本就不会被创建。 - 如果元素涉及到频繁的切换,最好不要使用 v-if, 而是推荐使用 v-show
- 如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if