条件渲染
- v-if
- 写法:
- v-if="表达式"
- v-else-if="表达式"
- v-else="表达式"
- 适用于:切换频率较低的场景。
- 特点:不展示的DOM元素直接删除。
- 注意:v-if可以与:v-else-if、v-else一起使用,但要求结构不能被打断。
- v-show
- 写法:v-show='表达式'。
- 适用于:切换频率较高的场景。
- 特点:不展示的DOM元素会被隐藏。
- 备注:使用v-if时,元素可能无法获取到,二使用v-show一定可以获取到。
<div id="root">
<h1>当前值:{{val}}</h1>
<button @click="val++">点击增加值</button>
<!-- v-show条件成立就显示,否则就隐藏 -->
<label v-show="val===1">我是第一个值</label>
<label v-show="val===2">我是第二个值</label>
<label v-show="val===3">我是第三个值</label>
<br/>
<!-- v-if条件成立就显示,否则就从DOM中删除掉,Vue会一行一行判断 -->
<label v-if="val===1">******我是第一个值******</label>
<label v-else-if="val===2">******我是第二个值******</label>
<label v-else-if="val===3">******我是第三个值******</label>
<br/>
<!-- v-else-if条件成立就显示,否则就从DOM中删除掉,语句必须紧挨着一起,如果前面的if成立,Vue就不会看下面的语句了(效率更高) -->
<label v-if="val===1">-------我是第一个值</label>
<label v-else-if="val===2">-------我是第二个值</label>
<label v-else-if="val===3">-------我是第三个值</label>
<br/>
<!-- v-if或者v-else-if条件成立就显示,否则就从DOM中删除掉,语句必须紧挨着一起,如果前面的if都不成立,Vue就会执行v-else中的语句 -->
<label v-if="val===1">#######我是第一个值#######</label>
<label v-else-if="val===2">#######我是第二个值#######</label>
<label v-else>#######我哪个值都不是#######</label>
</div>
<script>
new Vue({
el: "#root",
data: {
val: 0
}
})
</script>
v-if与template配合使用
<div id="root">
<h1>当前值:{{val}}</h1>
<button @click="val++">点击增加值</button>
<!-- v-show条件成立就显示,否则就隐藏 -->
<br/>
<!-- template不影响页面结构,显然的时候会被自动删除,只能配合v-if使用 -->
<template v-if="n===1">
<label>******我是第一个值******</label>
<label>******我是第二个值******</label>
<label>******我是第三个值******</label>
</template>
</div>
<script>
new Vue({
el: "#root",
data: {
val: 0
}
})
</script>
列表渲染
v-for指令:
- 用于展示列表数据。
- 语法:v-for="(item,index) in xxx" :key="yyy",index有添加或者删除的场景下一般不当作key,key一般用数据的id。
- 可遍历:数组,对象,字符串(用的很少),指定次数(用的很少)。
遍历数组
<ul id="root">
<!-- index是下标,key必须是唯一的 -->
<li v-for="(p,index) in persons" :key="p.id">{{p.id}}------------{{p.name}}----------下标:{{index}}</li>
<!--
<li v-for="p in persons" :key="p.id">{{p.id}}------------{{p.name}}</li>
-->
</ul>
<script>
new Vue({
el: "#root",
data: {
persons: [
{ id: 1, name: '李义新' },
{ id: 2, name: '李二新' },
{ id: 3, name: '李三新' },
{ id: 4, name: '李四新' }
]
}
})
</script>
遍历对象
<ul id="root">
<li v-for="(value,key) in obj" :key="key">{{value}}----------{{key}}</li>
</ul>
<script>
new Vue({
el: "#root",
data: {
obj: {
name: "李义新",
sex: "男",
age: 11
}
}
})
</script>
- 虚拟DOM中key的作用:
- key是虚拟DOM对象的标识,当数据发生改变时,Vue会根据【新数据】生成【新的虚拟DOM】,然后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较。
- 比较规则:
- 旧虚拟DOM中找到了与新虚拟DOM相同的key
- 若虚拟DOM中内容没变, 直按使用之前的真实DOM。
- 若虚拟DOM中内容变了,则生成新的真实DOM,然后替换掉页面中之前的真实DOM。
- 旧虚拟DOM中未找到与新虚拟DOM相同的key
- 创建新的真实DOM,随后渲染到到页面。
- 用index作为key可能会引发的问题
- 若对数据进行:逆序添加,逆序删除等破坏顺序的操作,会产生没有必要的真是DOM更新->界面效果没有问题,但效率低。
- 如果结构中还包含输入类的DOM:会产生错误的DOM更新->界面有问题。
- 如何选择key
- 最好使用每条数据的唯一标识作为key,比如id,手机号。
- 如果不存在对数据的逆序操作,逆序删除等破幻顺序的操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
列表渲染
模糊查询功能的实现
模糊查询时优先使用computed。
使用监听器的方式查询
<div id="root">
<h1>人员列表</h1>
<input type="text" placeholder="请输入名字" v-model="keyword">
<ul>
<li v-for="(p,index) in filterPersons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
new Vue({
el: "#root",
data: {
keyword: "",
persons: [
{ id: "001", name: "马冬梅", age: 19, sex: "女" },
{ id: "002", name: "周冬丽", age: 20, sex: "女" },
{ id: "003", name: "周杰伦", age: 21, sex: "男" },
{ id: "004", name: "温兆伦", age: 22, sex: "男" }
],
filterPersons: []
},
watch: {
keyword: {
immediate: true,
handler(newValue) {
this.filterPersons = this.persons.filter((p) => {
return p.name.indexOf(this.keyword) !== -1;
})
}
}
}
})
</script>
使用计算属性的方式查询
<div id="root">
<h1>人员列表</h1>
<input type="text" placeholder="请输入名字" v-model="keyword">
<ul>
<li v-for="(p,index) in filterPersons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
new Vue({
el: "#root",
data: {
keyword: "",
persons: [
{ id: "001", name: "马冬梅", age: 19, sex: "女" },
{ id: "002", name: "周冬丽", age: 20, sex: "女" },
{ id: "003", name: "周杰伦", age: 21, sex: "男" },
{ id: "004", name: "温兆伦", age: 22, sex: "男" }
]
},
computed: {
filterPersons() {
return this.persons.filter((p) => {
return p.name.indexOf(this.keyword) !== -1;
})
}
}
})
</script>
列表排序
<div id="root">
<h1>人员列表</h1>
<input type="text" placeholder="请输入名字" v-model="keyword">
<button @click="sortType=2">年龄升序</button>
<button @click="sortType=1">年龄降序</button>
<button @click="sortType=0">年龄原书序</button>
<ul>
<li v-for="(p,index) in filterPersons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
new Vue({
el: "#root",
data: {
keyword: "",
sortType: 0, //0代表原,1代表降序,2代表升序
persons: [
{ id: "001", name: "马冬梅", age: 23, sex: "女" },
{ id: "002", name: "周冬丽", age: 34, sex: "女" },
{ id: "003", name: "周杰伦", age: 11, sex: "男" },
{ id: "004", name: "温兆伦", age: 45, sex: "男" }
]
},
computed: {
filterPersons() {
const arr = this.persons.filter((p) => {
return p.name.indexOf(this.keyword) !== -1;
});
if (this.sortType) {
arr.sort((p1, p2) => {
return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age;
})
}
return arr;
}
}
})
</script>
关于数组的更改
例如:vm.myArr[0]="xin";这样vue监测不到数据的改变,不会时模板重新解析。
只有调用push(),pop(),shift(),unshift(),splice(),sort(),reverse()这七个方法操作数组时Vue才会监测到数组的改变并重新解析模板。
Vue.ser(vm.myArr,0,"xin"); //设置第一个元素为‘xin’。
vm$.ser(vm.myArr,0,"xin"); //设置第一个元素为‘xin’。
上面两种方式也可以更改数组元素后被Vue监测到并解析模板。
也可以用新的数组替换掉旧的数组,替换后模板也会重新解析。
Vue监视数据的原理(总结)
- vue会监视data中所有层次的数据,
- 如何监视对象中的数据?
- 通过setter实现监视,且要在new Vue时就传入要监测的数据。
- 对象中后期追加的属性,Vue默认不做响应处理
- 如果给后期添加的属性做响应式,请使用如下的API其中之一。
- Vue.set(target,propertyName/index,value)
- Vue.$set(target,propertyName/index,value)
- 也可以用新的数组替换掉旧的数组,替换后模板也会重新解析。
- 如何监视数组中的数据?
- 通过包装数组更新原色的方法实现,本质就是做了两件事:
- 调用原生对应的方法对数组进行更新。
- 从新解析模板,进而更新页面。
- 在Vue修改数组中的某个元素一定要用如下方法:
- push(),pop(),shift(),unshift(),splice(),sort(),reverse()。
- Vue.set()或者vm.$set()。
- 特别注意,Vue.set()和vm.$set()不能给vm或者vm的根数据对性添加属性!!