01-02.Vue的常用指令(二)
- 前言
- v-model:双向数据绑定
- v-model举例:实现简易计算器
- Vue中通过属性绑定为元素设置class 类样式
- 引入
- 方式一:数组
- 写法二:在数组中使用三元表达式
- 写法三:在数组中使用 对象 来代替 三元表达式(提高代码的可读性)
- Vue中通过属性绑定为元素设置 style 行内样式
- 写法一
- 写法二
- 写法三
- v-for:for循环的四种使用方式
- 引入
- 方式一:普通数组的遍历
- 方式二:对象数组的遍历
- 方式三:对象的遍历
- 方式四:遍历数字
- v-for中key的使用注意事项
- v-if:设置元素的显示和隐藏(添加/删除DOM元素)
- v-show:设置元素的显示和隐藏(在元素上添加/移除`style="display:none"`属性)
- v-if和v-show的区别
前言
我们接着上一篇文章 01-01.Vue的插值表达式和常用指令(一) 来讲。
下一篇文章 01-03.Vue:v-on的事件修饰符
本文主要内容:
重点:双向数据绑定,只能用于表单元素,或者用于自定义组件。
之前的文章里,我们通过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。
代码举例如下:
<template>
<div>
<!-- 将 input 标签中的value值双向绑定到 Vue实例中的data。注意,v-model 后面不需要跟冒号 -->
<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="注册" />
</div>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
name: "HydeLinjr",
myAccount: {
username: "",
userpwd: "",
},
};
},
//在methods里绑定各种方法,根据业务需要进行操作
methods: {
submit1(){
alert(this.myAccount.username + " pwd=" + this.myAccount.userpwd);
},
},
};
</script>
此时,便可实现我们刚刚要求的双向数据绑定的效果。
v-model举例:实现简易计算器
题目:现在两个输入框,用来做加减乘除,将运算的结果放在第三个输入框。
实现代码如下:
<template>
<div>
<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>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
n1: 0,
n2: 0,
result: 0,
opt: "+",
};
},
//在methods里绑定各种方法,根据业务需要进行操作
methods: {
calc() {
// 计算器算数的方法
// 逻辑判断:
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;
}
//上面的逻辑判断,可能有点啰嗦,我们还可以采取下面的这种方式进行逻辑判断
// 注意:这是投机取巧的方式,正式开发中,尽量少用
// var codeStr = 'parseInt(this.n1) ' + this.opt + ' parseInt(this.n2)'
// this.result = eval(codeStr)
},
},
};
</script>
注意上方代码中的注释,可以了解下eval()
的用法。
Vue中通过属性绑定为元素设置class 类样式
注意,是类样式。
引入
我们先来看下面这段代码:
<template>
<!--这个div区域就是MVVM中的 View-->
<div id="div1">
<h1 class="my-red my-thin">我是海德小林,HydeLinjr</h1>
</div>
</template>
<script>
export default {
};
</script>
<style>
.my-red {
color: red;
}
.my-thin {
/* 设置字体的粗细 */
font-weight: 200;
}
.my-italic {
font-style: italic;
}
.my-active {
/* 设置字符之间的间距 */
letter-spacing: 0.5em;
}
</style>
上面的代码中,我们直接通过正常的方式,给<h1>
标签设置了两个 class 类的样式。代码抽取如下:
<h1 class="my-red my-thin">我是海德小林,HydeLinjr</h1>
上面的效果,我们还可以用Vue来写。这就引入了本段要讲的方式。
方式一:数组
方式一:直接传递一个数组。注意:这里的 class 需要使用 v-bind 做数据绑定。
代码如下:
<template>
<!--这个div区域就是MVVM中的 View-->
<div id="div1">
<h1 class="my-red my-thin">我是海德小林,HydeLinjr</h1>
<!-- vue的写法1:数组的形式 -->
<h1 :class="['my-red', 'my-thin']">我是海德小林,HydeLinjr</h1>
</div>
</template>
<script>
export default {};
</script>
<style>
.my-red {
color: red;
}
.my-thin {
/* 设置字体的粗细 */
font-weight: 200;
}
.my-italic {
font-style: italic;
}
.my-active {
/* 设置字符之间的间距 */
letter-spacing: 0.5em;
}
</style>
代码抽取如下:
<!-- vue的写法1:数组的形式 -->
<h1 :class="['my-red', 'my-thin']">我是海德小林,HydeLinjr</h1>
上方代码中,注意,数组里写的是字符串;如果不加单引号,就不是字符串了,而是变量。
演示效果如下:
写法二:在数组中使用三元表达式
<template>
<div>
<!-- vue的写法2:在数组中使用三元表达式。注意格式不要写错-->
<!-- 通过data中布尔值 flag 来判断:如果 flag 为 true,就给 h1 标签添加`my-active`样式;否则,就不设置样式。 -->
<h1 :class="[flag ? 'my-active' : '']">我是海德小林,HydeLinjr</h1>
</div>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
flag: true,
};
},
};
</script>
上方代码的意思是,通过data中布尔值 flag 来判断:如果 flag 为 true,就给 h1 标签添加my-active
样式;否则,就不设置样式。
注意,三元表达式的格式不要写错了。
写法三:在数组中使用 对象 来代替 三元表达式(提高代码的可读性)
上面的写法二,可读性较差。于是有了写法三。
写法三:在数组中使用对象来代替三元表达式。
代码如下:
<template>
<div>
<!-- vue的写法3:在数组中使用对象来代替三元表达式。-->
<h1 :class="[ {'my-active':flag} ]">我是海德小林,HydeLinjr</h1>
</div>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
flag: true,
};
},
};
</script>
Vue中通过属性绑定为元素设置 style 行内样式
注意,是行内样式(即内联样式)。
写法一
写法一:直接在元素上通过 :style
的形式,书写样式对象。
例如:
<h1 :style="{color: 'red', 'font-size': '20px'}">我是海德小林,HydeLinjr</h1>
写法二
写法二:将样式对象,定义到 data
中,并直接引用到 :style
中。
也就是说,把写法一的代码改进一下。代码如下:
<template>
<div>
<h1 :style="styleObj">我是海德小林,HydeLinjr</h1>
</div>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
styleObj: { color: 'red', 'font-size': '20px' }
};
},
};
</script>
写法三
写法二只用到了一组样式。如果想定义多组样式,可以用写法三。
写法三:在 :style
中通过数组,引用多个 data
上的样式对象。
代码如下:
<template>
<div>
<h1 :style="[styleObj1, styleObj2]">我是海德小林,HydeLinjr</h1>
</div>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
styleObj1: { color: "red", "font-size": "20px" },
styleObj2: { "font-style": "italic" },
};
},
};
</script>
v-for:for循环的四种使用方式
作用:根据数组中的元素遍历指定模板内容生成内容。
引入
比如说,如果我想给一个ul
中的多个li
分别赋值1、2、3…。如果不用循环,就要挨个赋值:
<template>
<div>
<ul>
<li>{{list[0]}}</li>
<li>{{list[1]}}</li>
<li>{{list[2]}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
list: [1, 2, 3]
};
},
};
</script>
效果:
为了实现上面的效果,如果我用v-for
进行赋值,代码就简洁很多了:
<template>
<div>
<ul>
<!-- 使用v-for对多个li进行遍历赋值 -->
<li v-for="item in list" :key="item">{{ item }}</li>
</ul>
</div>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
list: [1, 2, 3],
};
},
};
</script>
接下来,我们详细讲一下v-for
的用法。需要声明的是,Vue 1.0的写法和Vue 2.0的写法是不一样的。本文全部采用Vue 2.0的写法。
方式一:普通数组的遍历
针对下面这样的数组:
<script>
new Vue({
el: '#app',
data: {
arr1: [2, 5, 3, 1, 1],
}
});
</script>
将数组中的值赋给li:
<li v-for="item in arr1" :key="item">{{item}}</li>
将数组中的值和index赋给li:
<!-- 括号里如果写两个参数:第一个参数代表值,第二个参数代表index 索引 -->
<li v-for="(item,index) in arr1" :key="index">值:{{item}} --- 索引:{{index}}</li>
效果如下:
方式二:对象数组的遍历
<template>
<div>
<ul>
<!-- 对象数组的遍历。括号里如果写两个参数:第一个参数代表数组的单个item,第二个参数代表 index 索引-->
<li v-for="(item, index) in dataList" :key="index">
姓名:{{ item.name }} --- 年龄:{{ item.age }} --- 索引:{{ index }}
</li>
</ul>
</div>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
//对象数组
dataList: [
{ name: "zhangsan", age: "26" },
{ name: "lisi", age: "32" },
{ name: "wangwu", age: "20" },
],
};
},
};
</script>
效果如下:
方式三:对象的遍历
针对下面这样的对象:
<script>
export default {
name: "HomeView",
data() {
return {
obj1: {
name: "hydelinjr",
age: "26",
gender: "男",
},
};
},
};
</script>
将上面的obj1
对象的数据赋值给li,写法如下:
<template>
<div>
<ul>
<!-- 括号里如果写两个参数:则第一个参数代表value,第二个参数代表key -->
<li v-for="(value,key) in obj1" :key="key">值:{{value}} --- 键:{{key}} </li>
<h3>---分隔线---</h3>
<!-- 括号里如果写三个参数:则第一个参数代表value,第二个参数代表key,第三个参数代表index -->
<li v-for="(value,key,index) in obj1" :key="index">值:{{value}} --- 键:{{key}} --- index:{{index}} </li>
</ul>
</div>
</template>
效果如下:
方式四:遍历数字
in
后面还可以直接放数字。举例如下:
<ul>
<!-- 对象数组的遍历 -->
<!-- 注意:如果使用 v-for 遍历数字的话,前面的 myCount 值从 1 开始算起 -->
<li v-for="myCount in 10">这是第 {{myCount}}次循环</li>
</ul>
效果如下:
v-for中key的使用注意事项
注意:在 Vue 2.2.0+ 版本里,当在组件中使用 v-for 时,key 属性是必须要加上的。
这样做是因为:每次 for 循环的时候,通过指定 key 来标示当前循环这一项的唯一身份。
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。
key的类型只能是:string/number,而且要通过 v-bind 来指定。
代码举例:
<template>
<div>
<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>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
id: "",
name: "",
list: [
{ id: 1, name: "hyde" },
{ id: 2, name: "lin" },
{ id: 3, name: "hydelinjr" },
{ id: 4, name: "Hydelinjr" },
{ id: 5, name: "HydeLinjr" },
],
};
},
methods: {
add() {
// 添加方法
this.list.unshift({ id: this.id, name: this.name });
},
},
};
</script>
v-if:设置元素的显示和隐藏(添加/删除DOM元素)
作用:根据表达式的值的真假条件,来决定是否渲染元素,如果为false则不渲染(达到隐藏元素的目的),如果为true则渲染。
在切换时,元素和它的数据绑定会被销毁并重建。
举例如下:(点击按钮时,切换和隐藏盒子)
<template>
<div>
<button v-on:click="toggle">显示/隐藏</button>
<div v-if="isShow">我是盒子</div>
</div>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
isShow: true,
};
},
methods: {
toggle: function () {
this.isShow = !this.isShow;
},
},
};
</script>
效果如下:
v-show:设置元素的显示和隐藏(在元素上添加/移除style="display:none"
属性)
作用:根据表达式的真假条件,来切换元素的 display 属性。如果为false,则在元素上添加 display:none
属性;否则移除display:none
属性。
举例如下:(点击按钮时,切换和隐藏盒子)
我们直接把上一段代码中的v-if
改成v-show
就可以了:
<template>
<div>
<button v-on:click="toggle">显示/隐藏</button>
<div v-show="isShow">我是盒子</div>
</div>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
isShow: true,
};
},
methods: {
toggle: function () {
this.isShow = !this.isShow;
},
},
};
</script>
效果如下:
v-if和v-show的区别
v-if
和v-show
都能够实现对一个元素的隐藏和显示操作。
区别:
-
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