一、什么是指令
指令的本质就是 HTML 自定义属性。
HTML有两种属性,一种是固有属性,一种是自定义属性。固有属性指id、class、title这些支持HTML自身功能的属性,自定义属性通常用来存储一些与当前元素有关的数据内容。指令也是自定义属性,但指令的作用并不仅仅是存储数据,指令这种自定义属性设置给元素后,当前元素在被框架处理时,框架就会知道当前元素需要一些特殊功能去执行,所以指令本身是给框架进行识别的一种标记,这种标记所采用的形式叫做自定义属性,可以用来快速的对当前元素进行功能处理,以减少DOM操作。
Vue.js 的指令就是以 v- 开头的自定义属性。
二、内容处理
v-once指令:用来进行内容中的插值表达式的相关设置
v-text指令:用来对当前元素的纯文本内容进行设置
v-html指令:用来设置当前元素内部html文本内容
1. v-once指令
v-once指令作用
作用:使元素内部的插值表达式只生效一次。
我们知道,元素内部是可以使用插值表达式的,插值表达式内部如果采用了实例中data的数据,这个数据如果发生变化会自动地触发数据驱动视图效果,意味着数据更新会导致视图更新。如果仅希望元素内部的内容只能生效一次,而不再随着内部数据变化而变化的话,就可以通过v-once指令进行设置。
v-once指令示例
<body>
<div id="app">
<p>此内容会随数据变化自动更新:{{ content}}</p>
<p v-once>此内容不会随数据变化自动更新:{{ content }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
content: '内容文本'
}
});
</script>
</body>
第一个p标签中的content会随数据变化自动更新,而第二个p标签中内容中的content只会在第一次执行时读取一次内容,以后content变化不会自动更新。
2. v-text指令
v-text指令作用
作用:元素内容整体替换为指定纯文本数据
注意v-text与插值表达式的区别:插值表达式是用来进行元素动态内容设置的,当然这个设置是可以设置为局部的,即,可以将插值表达式参与到元素内容中的某一部分或整体,也可以插入一个或多个插值表达式来处理一段内容。v-text的作用是直接将当前元素内容设置为指定数据,如果当前元素内部已经存在内容,v-text的新内容会将当前元素的内容覆盖掉。从本质来讲,v-text的底层调用的其实是元素的text-content属性,所以会导致元素的原始内容被覆盖。
注意:v-text指令设置的只能是纯文本,无法生成html结构文本。
v-text指令示例
<body>
<div id="app">
<p v-text="100">这是p标签的原始内容</p>
<!-- 可以设置自定义文本,但一般还是下面这种更常用,注意:只能是数字,汉字英文符号都不行 -->
<p v-text="content">这是p标签的原始内容</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
content: '内容文本'
}
});
</script>
</body>
3. v-html指令
v-html指令作用
作用:元素内容整体替换为指定的 HTML 文本
v-text指令和v-html指令相似,只不过v-text指令只能设置纯文本内容,标签文本不会生成;而v-html指令可以生成纯文本,或标签文本组成的html文本内容。相似点在于,v-html指令设置以后,同样会覆盖当前标签的原始内容。
v-html指令示例
<body>
<div id="app">
<p v-html="content">这是p标签的原始内容</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
// content: '新的内容文本'
// 可以设置纯文本
content: '<span>span标签的内容</span>'
}
});
</script>
</body>
三、属性绑定
v-bind指令:用来进行属性绑定的相关处理操作
Class绑定:Class类,可能有多个,v-bind对Class绑定处理会有特殊使用方式
Style绑定:Style样式,用来进行行的样式设置,通过v-bind绑定时同样可以进行多个值的绑定操作,Vue.js中同样提供了特殊处理方式
1. v-bind指令
v-bind指令作用
前面的v-once,v-text,v-html指令只能用于处理当前元素的内容,如果希望对属性进行处理,就需要依赖v-bind指令进行操作。
作用:v-bind 指令用于动态绑定 HTML 属性。
v-bind指令示例
<body>
<div id="app">
<p :title="myTitle">这是p标签的内容</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
myTitle: '这是title属性内容'
}
});
</script>
</body>
v-bind冒号后边为要绑定的属性名称,等号后面的值为要绑定的具体数据,这里演示的是title属性的绑定操作,绑定的值是myTitle,myTitle指的是在data中声明的数据。
注意:v-bind:title="title"中冒号前后都不要有空格,否则无法正常显示
运行结果:网页中显示 这是p标签的内容 ,鼠标移上出现 这是title属性内容
v-bind指令简写方式
<body>
<div id="app">
<p :title="myTitle">这是p标签的内容</p>
<!-- 省略v-bind -->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
myTitle: '这是title属性内容'
}
});
</script>
</body>
后续使用简写方式即可。
v-bind中允许使用表达式
与插值表达式类似,v-bind 中也允许使用表达式。
<body>
<div id="app">
<p :title="myTitle">这是p标签的内容</p>
<p :class="'num' + 1 + 2 + 3">字符串拼接1</p>
<p :class="prefix + num">字符串拼接2</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
myTitle: '这是title属性内容',
prefix: 'demo',
num: 10
}
});
</script>
</body>
注意:v-bind中可以使用表达式,但是不可以使用语句,比如<p :class="var a = 1">是不可以的。
v-bind指令一次绑定多个属性——绑定对象
如果需要一次绑定多个属性,还可以绑定对象。
<body>
<div id="app">
<p v-bind="attrObj">这是p标签的内容</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
attrObj: {
id: 'box',
class: '类',
title: 'ttitle属性内容',
// 除了可以绑定上面的固有属性外,还可以绑定自定义属性,注意用单引号包裹
'data-title':'自定义属性data-title属性内容'
}
}
});
</script>
</body>
运行结果:(设置的类,id属性可以在Elements找到元素鼠标移上后在网页中查看)
2. Class绑定
class 是 HTML 属性,用来进行元素的类名设置,可以通过 v-bind 进行绑定。
通过v-bind绑定的class可以与普通的 class 属性共存。
Class绑定示例
<body>
<div id="app">
<p :class="cls">绑定class</p><!-- 可以随data中cls值的变化动态改变p标签的类名 -->
<p class="a" :class="cls">可以共存</p>
<!-- x是动态绑定的,a是固定类名,二者可以共存 -->
<!-- 运行显示p.a.x,不论class="a"和:class="cls"的书写顺序是什么,a都在x前 -->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
cls: 'x'
}
});
</script>
</body>
第一个p标签:p标签绑定的类名为x,由于data的数据会进行数据驱动视图设置,所以当cls变化时,p标签的类名会随之改变,达到动态绑定类名的目的。
第二个p标签:设置了两部分类名,左侧部分是普通的class属性,用来设置类名a,是固定的,无法修改;右侧部分通过v-bind绑定类名,这个部分类名为x,由于普通class可以与绑定的class共存,所当前元素具有两个类名,一个是a一个是x,但其中只有x是动态绑定的,a是固定类名。
多个类名绑定
一个元素是可以设置多个类名的,例如<p clsaa="a b c"></p>,这是基础方式。
如果data中cls1:'x',cls2:'y',cls3:'z',注意,通过v-bind方式绑定的class是不能与普通class一样直接并排以空格连接书写多个值的,这样<p clsaa="cls1 cls2 cls3"></p>这是错误的。
多个类名绑定提供一种思路:
<body>
<div id="app">
<p :class="cls">绑定class</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
cls: 'x y z'
}
});
</script>
</body>
运行结果显示的是p.x.y.z说明成功了,但是注意,这种方式并不常用,因为这种方式灵活度不强,cls中的x y z是由三部分进行的字符串拼接,如果后续要改,达不到只更改某一部分的目的,例如只想更改x,这种方法就必须cls都改,灵活度不高。
需要进行条件判断的类名设置
情况一:单个类名
需求:用户输入了内容,若输入内容符合输入规则,则采用cls1,否则采用cls2
<body>
<div id="app">
<p :class="bool?cls1:cls2">绑定class</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
bool:true,
cls1: 'x',
cls2: 'y'
}
});
</script>
</body>
将最终处理结果放在一个布尔值中,数据设为bool,值的默认值为true。v-bind绑定时可以采用三元运算符,bool?cls1:cls2。
注意:这种方法不常用。
情况二:当前元素具有多个类名
这就要用到Vue.js中Class绑定的特殊处理方式。
Vue.js中允许在进行Class绑定时设置对象结构,对象有键和值两部分,b:isB,键代表要设置的类名即最终生效类名为b,冒号后面的值为一个布尔值,对应B类名是否生效,所以键与值的关系代表了类名与是否生效的对应关系,书写方便,且可同时书写多个类名。
第四个演示'class-d':true,当类名为横线-连接方式时,JavaScript的键不支持这种方式,所以可以通过引号包裹,这也就意味着,多种类名书写方式,都是可以支持的。
<body>
<div id="app">
<p :class="{ x:true, y:false, z:true, 'class-d':true }">绑定class</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
}
});
</script>
</body>
上述代码中,x,y,z,class-d代表即将生效的类名,冒号后面的true和false代表是否生效,上述示例运行结果p.x.z.class-d意味着x和z和class-d生效,y不生效因为值为false。
当设置当前类名是否生效时,冒号后面的值不仅可以写成固定值,还可以通过data中的数据进行操控,这是最常见的的形式:
<body>
<div id="app">
<p :class="{ x:isX, y:isY, z:isZ }">绑定class</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
isX: true,
isY: false,
isZ: true
}
});
</script>
</body>
多个类名+条件判断——数组设置方式
Vue.js在进行类名绑定时,除了提供上述对象处理方式外,还允许我们进行数组的设置方式。数组绑定处理是对对象设置方式的进一步扩展。
<p :class="['a', { b:isB }, 'c' ">绑定class</p>中,将class的值绑定为了一个数组,数组内部a和c为静态的固定的类名部分,中间的大括号表示动态绑定的区域,表示当前类名显示或不显示。这种方式允许同时设置多个类名,并且允许给某些需要条件控制类名进行条件设置,像a和c这种无需条件设置的值单独书写即可,不再需要书写true。
<body>
<div id="app">
<p :class="['a', { b:isB }, 'c', ClassD ]">绑定class</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
isB: true,
ClassD: 'D'
}
});
</script>
</body>
运行结果p.a.b.c.D
v-bind绑定Class总结
Class绑定共三种写法,第一种是直接绑定单个数据,如果需要进行多个数据的绑定,可以视情况而定,一种采用对象写法,一种采用数组写法。对象写法的键代表当前类名,值代表当前类名是否显示。如果当前元素中存在着一些无需条件的类名和有条件的类名,这时可以通过数组方式来设置,将需要条件的部分在对象中书写,不需要条件的部分直接书写在数组元素中即可。
3. Style绑定
style 是 HTML 属性,是用来进行HTML行内样式设置的属性,可以通过 v-bind 进行绑定。
Style绑定示例
注意,通过v-bind绑定style时,不能像以前一样直接写普通字符串,因为样式都是具有键和值两个部分的,所以需要传入的基本形式是对象,对象中的键指要设置的样式名称,对象中的值指要设置的样式值。
<body>
<div id="app">
<!-- 方式一:直接行内书写对象,但是这种方式书写非常复杂且不易于维护,不常用 -->
<p v-bind:style="{ width: '300px', height:'100px'}">直接行内书写对象,不常用</p>
<!-- 方式二:在data中设置数据,更常用 -->
<p v-bind:style="styleObj">在data中设置数据,常用方式</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
styleObj: {
width: '500px',
height: '200px',
backgroundColor: 'red',
'font-size': '30px'
}
}
});
</script>
</body>
注意两点:
- 设置宽度高度这种带有单位的属性时,单位是不可以省略的,如写成width:'100'是没有效果的。
- 当设置style中的background-color及font-size这类带横线的样式时,在data中可以用驼峰命名法backgroundColor: 'red',也可以使用引号包裹的方式,如'font-size': '30px',两种方式都可以,但是更加推荐驼峰命名法方式,因为更加接近传统写法。
通过v-bind绑定的属性可以与 普通的style 属性共存。
<body>
<div id="app">
<p style="width: 100px;" :style="styleObj">可以共存</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
styleObj: {
width: '200px',
height: '200px',
backgroundColor: 'red',
'font-size': '30px'
}
}
});
</script>
</body>
前面设定width为100px是固定的值,后面通过v-bind绑定Style时也可以设置width,如果不设置就会采用100px,如果设置会以新设置的值为准,所以最终元素显示的宽度应为200px。
绑定多个样式对象——样式绑定的数组写法
当我们希望给元素绑定多个样式对象时,可以设置为数组。
应用:当有多个元素有相同属性时,可以将相同属性存储在一个styleObj,更改一次StyleObj即可更改所有元素样式。
<body>
<div id="app">
<p :style="[baseStyle, styleObj1]">第一个 p 标签</p>
<p :style="[baseStyle, styleObj2]">第二个 p 标签</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
baseStyle: {
//公共样式
width: '200px',
height: '200px',
},
styleObj1: {
backgroundColor: 'red'
},
styleObj2: {
backgroundColor: 'blue'
}
}
});
</script>
</body>
四、渲染指令
v-for指令:用于进行数据的遍历,并根据遍历数据的内容进行对应的结构创建操作
v-show指令:用于控制元素显示隐藏的切换操作
v-if指令:用于在多个元素中通过条件判断进行指定元素的创建或移除处理
1. v-for指令
v-for指令是Vue.js中最常用的指令之一,用于遍历数据渲染结构,常用的数组与对象均可遍历。
v-for指令用于数组
数组遍历
<body>
<div id="app">
<ul>
<li v-for="item in arr">数组元素内容为:{{ item }}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
arr: ['数组内容1', '数组内容2', '数组内容3']
}
});
</script>
</body>
ul中设置了li标签,li标签上设置了v-for指令,表示当前li标签是根据数据遍历并进行渲染操作的,最终li会根据数据的实际个数进行对应的创建操作。
item是内部数据的标识符名称,in arr表示要遍历的是arr这个数组。
带有索引的数组遍历
获取索引值,可以在item部分用括号包裹,后面加index,这样就可以声明两个标志符,第一个代表值,第二个代表索引。
<body>
<div id="app">
<ul>
<li v-for="(item, index) in arr">
数组元素内容为:{{ item }},元素索引为:{{ index }}
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
arr: ['数组内容1', '数组内容2', '数组内容3']
}
});
</script>
</body>
v-for指令用于对象
遍历对象
value是内部数据的标识符名称,in obj表示要遍历的是obj这个对象结构。
<body>
<div id="app">
<ul>
<li v-for="value in obj">
对象元素内容为:{{ value }}
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
obj: {
content1: '对象内容1',
content2: '对象内容2',
content3: '对象内容3'
}
}
});
</script>
</body>
遍历对象时打印键
将value部分改为(value, key)即可。
<body>
<div id="app">
<ul>
<li v-for="(value, key) in obj">
对象元素内容为:{{ value }},元素键为:{{ key }}
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
obj: {
content1: '对象内容1',
content2: '对象内容2',
content3: '对象内容3'
}
}
});
</script>
</body>
遍历对象时打印索引
如果遍历对象时也希望进行索引的获取,v-for允许我们在第三个位置上进行标记,即(value, key, index),其中index代表索引值,标记当前这个键的索引,但是在传统操作中这个值是不存在的,v-for为我们提供了这个值。
<body>
<div id="app">
<ul>
<li v-for="(value, key,index) in obj">
对象元素内容为:{{ value }},元素键为:{{ key }},索引值为:{{ index }}
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
obj: {
content1: '对象内容1',
content2: '对象内容2',
content3: '对象内容3'
}
}
});
</script>
</body>
运行结果:
注意:(value, key, index)这三个是可以根据具体情况选择组合使用的。
v-for用于无数组或对象结构的数值
Vue.js中,v-for指令不仅可以遍历数组和对象,还可以进行数值的遍历处理。如果希望在 ul 中进行 li 标签创建,创建5个,如果有数组或对象等数据结构,那直接遍历即可。但如果没有数据基础,仅仅想凭空创建出5个li元素,传统方式可以用for 循环 for(int i=0;i<5;i++)来实现,v-for同样具有这个功能,示例如下:
<body>
<div id="app">
<ul>
<li v-for="(item, index) in 5">
这是第 {{ item }}个元素,索引值为:{{ index }}
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
}
});
</script>
</body>
运行结果:
使用v-for时应始终指定唯一key属性
使用 v-for 的同时,应始终指定唯一的 key 属性,可以提高渲 染性能并避免出现问题。
如果不设置key,在输入框1,输入框2,输入框3中依次输入1,2,3后,控制台执行vm.arr.reverse()即数组翻转,想得到的结果是输入框1:1,输入框2:2,输入框3:3,然而不设置key时得到的结果是:
出现这种问题的原因在于,当Vue.js进行结构渲染时,会尽可能提高执行效率,当通过v-for进行遍历设置时,应当是类似结构的,比如这三个输入框,当进行数据变更后,Vue.js会尝试着尽可能提高效率,可能会在当前元素的基础上修改视图结构,例如将输入框1变成输入框3,但仅限于结构部分,而输入的内容属于用户的操作而不属于视图功能,所以会导致这种问题的出现。
为了避免上述问题的出现,在当前通过v-for设置的元素上用v-bind设置key,key属性是在Vue内部指定的名称,要求我们通过指定名称来操作,设置好后这个值必须是唯一值。在这里,唯一值有两种,第一个是索引,第二个是元素,索引值是不被推荐使用的,例如设置(item, index) in arr,翻转后结果和上面一样,index并不能完全避免这种问题,因为位置变化后,索引值对应的元素也会自动发生改变,所以通过index的设置方式是不合理的,因为index不是唯一的。所以,应当给每个元素设置自身独特的唯一的key值,可以采用item进行设置:
<body>
<div id="app">
<ul>
<li v-for="item in arr" :key="item">
输入框{{ item }}:<input type="text">
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
arr: [1, 2,3]
}
});
</script>
</body>
运行结果:
可以看到,设置唯一key后翻转成功,元素进行了翻转,同时输入框输入的内容也进行了翻转,因为Vue.js发现,当前的元素都设置了key,所以需要在渲染时确定每个元素移动到了哪个位置,而不再是基于当前的旧元素修补成新的元素,就不会出现输入框内容不对应的问题了。
如果数据有相同的,例如 arr[2, 3, 3],那就不推荐使用item来设置了。可以将每部分值都设置为对象,并用不同的id标记,用value标识数据,在 li 中将item.id设置为key属性,将item.value作为内容。
<body>
<div id="app">
<ul>
<li v-for="item in itemList" :key="item.id">
输入框{{ item.value }}:<input type="text">
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
itemList: [
{
id: 1,
value: 2
},
{
id: 2,
value: 3
},
{
id: 3,
value: 3
}
]
}
});
</script>
</body>
可以看到翻转成功的运行结果:
强调:以后,凡是使用了v-for的地方,都一定要给元素设置唯一的key值。
<template>标签设置模板占位符
通过<template>标签设置模板占位符,可以将部分元素或内容作为整体进行操作。
<template>标签执行完毕后并不会呈现为标签,它只是一个占位符,只是一块区域,表示内部的内容是一个整体。在<template>标签内部可以书写任意的标签或者内容的组合,即可实现当前元素的多次生成。比如希望两个<span>重复生成3次,正常来说需要在外面包一个<div>并对<div>设置v-for以达到重复执行的目的,但如果外部不希望有多余元素包裹而仅仅让两个标签本身重复的话是做不到的,所以可以ton过一个不存在的标签<template>这种模板占位符来处理。这样,纯文本内容的重复设置,以及多组标签的重复设置,都是非常方便的。
<body>
<div id="app">
<template v-for="item in obj">
<!-- 将span和br看做一个整体进行重复,每输出一个item换行一次 -->
<span> {{ item }}</span>
<br>
</template>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
obj: {
content1: '内容1',
content2: '内容2',
content3: '内容3'
}
}
});
</script>
</body>
注意:因为<template>本身并不是一个真实的元素,所以没办法给它设置key属性,所以即使给<template>设置了v-for,也无需给<template>设置key属性,否则会报错。
2. v-show指令
作用:用于控制元素显示与隐藏,适用于显示隐藏频繁切换时使用。
示例:
true和false直接书写在v-show内部
<body>
<div id="app">
<p v-show="true">这个元素显示1</p>
<p v-show="false">这个元素隐藏2</p>
<!-- 除了true和false,还可以用条件表达式 -->
<p v-show="2>11">这个元素隐藏3</p>
<p v-show="22>11">这个元素显示4</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
}
});
</script>
</body>
语句 <p v-show="true">这个元素显示</p>中的true和false除了直接书写在v-show内部以外,还可以通过data中的数据进行绑定,当操作时,修改绑定的数据就可以达到元素的显示隐藏切换的目的。
将data中数据绑定给v-show
通常用data中的数据进行操作,方便后续处理。
<body>
<div id="app">
<p v-show="bool">这个元素显示1</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
bool: true
}
});
</script>
</body>
<template>无法使用v-show指令
注意:<template>无法使用v-show指令,因为v-show指令其实是通过元素的display属性来控制显示隐藏的,display是一个真实的元素属性,元素样式,而<template>并不是真实的元素,所以<template>无法设置v-show指令。
在<template>中设置v-show指令,不论是true还是false,都会显示。所以,不要给<template>这种不是真实元素的标签设置v-show指令。
3. v-if指令
作用:用于根据条件控制元素的创建与移除。
v-if基础示例
<body>
<div id="app">
<p v-if="bool">这个元素不会被创建</p> <!-- 一般采用data绑定的方式 -->
<p v-else-if="true">这个元素会被创建</p>
<p v-else>这个元素不会被创建</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
bool: false
}
});
</script>
</body>
v-if为true会创建,为false不会创建。所以第一句 <p v-if="false">这个元素不会被创建</p> 不会被创建,第二句 <p v-else-if="true">这个元素会被创建</p> 因为为true所以会被创建,第三句,由于第二局中v-else-if已经创建成功了,所以最后的v-else不会被创建。v-else会在前面内容都不满足时进行最终展示,即若前面都为false则v-else进行最终展示。
注意,v-if的false是没有创建或移除了,而v-show的flase是存在的只是被隐藏了。
注意:不要频繁创建或移除,会消耗性能,如果有频繁切换可以用v-show控制显示隐藏
给使用 v-if 的同类型元素绑定不同的 key
假设有两个输入框等待是否被创建,初始时v-if创建,若不设置key,第一个输入框创建并输入元素后,改为移除第一个输入框创建第二个输入框,输入内容会变到第二个输入框中。
当用户登录时,可能采用账号登录或手机号登录或邮箱登录,当用户选择时就是不同功能的元素进行切换,但无论是哪种方式,所需要采用的结构总是类似的,只不过内部判断逻辑可能是手机号规则可能是邮箱规则,这种情况下进行切换就会导致问题,先在手机号输入框输入,切换到邮箱登录后,手机号输入框中的内容会自动到邮箱输入框中,出现问题。原因和前面的v-for指令设置key一样。
<body>
<div id="app">
<div v-if="type==='username'" :key="'username'">
手机号输入框:<input type="text">
</div>
<div v-else :key="'email'">
邮箱输入框:<input type="text">
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
type: 'username'
}
});
</script>
</body>
运行结果:
避免将 v-if 与 v-for 应用于同一标签
出于性能考虑,应避免将 v-if 与 v-for 应 用于同一标签。
根据Vue.js的内部实现规则,如果将v-if和v-for同时应用于同一标签,v-for的优先级会更高,即,v-for会先执行,执行完毕才会判断v-if。如果需求中v-if是false的话就不应该进行创建,但是先执行v-for会创建,此时的创建就是毫无意义的,消耗很多不必要的性能。所以,不能将v-for与v-if用于同一标签,应分开使用。
例如创建列表时,在<li>标签进行v-for的绑定,如果要进行显示隐藏的控制,可以将v-if设置给外部的父元素。
<body>
<div id="app">
<ul v-if="false">
<li v-for="item in items"> {{ item }} </li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
items: {
content1: '内容1',
content2: '内容2',
content3: '内容3'
}
}
});
</script>
</body>