目录
一、列表渲染
1.1 列表渲染指令
v-for指令:
- 用于展示列表数据
- 语法:v-for= “(item, index) in xxx” :key = “yyy”
- 可遍历:数组、对象、字符串(较少使用)、指定次数(较少使用)
1.2 简单案例练习 – 列表渲染指令使用
<body>
<div class="root">
<!-- 遍历数组 -->
<h2>人员列表(遍历数组)</h2>
<ul>
<li v-for="(p,index) of persons" :key="index">
{{p.name}} - {{p.age}}
</li>
</ul>
<!-- 遍历对象 -->
<h2>游戏信息(遍历对象)</h2>
<ul>
<li v-for="(value,key) of game" :key="key">{{key}} -- {{value}}</li>
</ul>
<!-- 遍历字符串 -->
<h2>测试遍历字符串(较少使用)</h2>
<ul>
<li v-for="(char,index) of str" :key="index">{{index}} -- {{char}}</li>
</ul>
<!-- 遍历指定次数 -->
<h2>测试遍历指定次数(较少使用)</h2>
<ul>
<li v-for="(number,index) of 5" :key="index">
{{index}} -- {{number}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip = false;
new Vue({
el: ".root",
data: {
persons: [
{ id: "001", name: "张三", age: "20" },
{ id: "002", name: "李四", age: "21" },
{ id: "003", name: "王五", age: "22" },
],
game: {
name: "艾尔登法环",
price: "¥298",
creater: "宫崎英高",
},
str: "hello",
},
});
</script>
1.3 key作用与原理(重要)
vue中key有什么作用?(key的内部原理)
1. 虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
2. 对比规则:
(1)旧虚拟DOM中找到了与新虚拟DOM相同的key:
①. 若虚拟DOM中内容没变,直接使用之前的真实DOM!
②. 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
(2)旧虚拟DOM中未找到与新虚拟DOM相同的key:
创建新的真实DOM,随后渲染到页面
3. 用index作为key可能引发的问题:
(1)若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低
(2)如果解构中还包含输入类的DOM:
会产生错误DOM更新 ==> 界面出现问题
4. 开发中如何选择key?
(1)最好使用每条数据的唯一标识作为key,比如id、手机号、学号、身份证等唯一值
(2)如果不存在对数据的逆序添加、逆序删除等破坏顺序解构操作,仅用于渲染列表用于展示,使用index作为key是没有问题的
1.4 列表过滤和列表排序
1.4.1 列表过滤
采用计算属性computed实现
<body>
<div class="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord" />
<ul>
<li v-for="(p,index) of filPerson" :key="index">
{{p.name}} - {{p.age}} - {{p.sex}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip = false;
new Vue({
el: ".root",
data: {
keyWord: "",
persons: [
{ id: "001", name: "马冬梅", age: "20", sex: "女" },
{ id: "002", name: "周冬雨", age: "21", sex: "女" },
{ id: "003", name: "周杰伦", age: "22", sex: "男" },
{ id: "004", name: "温兆伦", age: "23", sex: "男" },
],
},
computed: {
filPerson() {
return this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1;
});
},
},
});
</script>
采用数据侦听watch实现
// watch写法
new Vue({
el: ".root",
data: {
keyWord: "",
persons: [
{ id: "001", name: "马冬梅", age: "20", sex: "女" },
{ id: "002", name: "周冬雨", age: "21", sex: "女" },
{ id: "003", name: "周杰伦", age: "22", sex: "男" },
{ id: "004", name: "温兆伦", age: "23", sex: "男" },
],
filPerson: [],
},
watch: {
keyWord: {
immediate: true,
handler(val) {
this.filPerson = this.persons.filter((p) => {
return p.name.indexOf(val) !== -1;
});
},
},
},
});
1.4.2 列表排序
<body>
<div class="root">
<h2>人员列表</h2>
<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) of filPerson" :key="index">
{{p.name}} - {{p.age}} - {{p.sex}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip = false;
// computed实现
new Vue({
el: ".root",
data: {
keyWord: "",
sortType: 0, //0原顺序,1降序,2升序
persons: [
{ id: "001", name: "马冬梅", age: "24", sex: "女" },
{ id: "002", name: "周冬雨", age: "21", sex: "女" },
{ id: "003", name: "周杰伦", age: "20", sex: "男" },
{ id: "004", name: "温兆伦", age: "23", sex: "男" },
],
},
computed: {
filPerson() {
const arr = this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1;
});
// 判断是否需要排序, 可直接判断布尔值,0为false,1和2都为true
if (this.sortType) {
arr.sort((p1, p2) => {
return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age;
});
}
return arr;
},
},
});
二、Vue监视数据
2.1 Vue监视数据的原理
1. vue会监视data中所有层次的数据
2. 如何检测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据。、
(1)对象中后追加的属性,Vue默认不做响应式处理
(2)如需要给后添加的属性做响应式,需要添加如下API:
Vue.set(target, propertyName/index, value) 或
vm.$set(target, propertyName/index, value)
3. 如何检测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
(1)调用原生对应的方法对数组进行更新
(2)重新解析模板,进而更新页面
4. 在Vue修改数组中的某个元素一定要用如下方法:
(1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
(2)Vue.set() 或 vm.$set()
注意:Vue.set() 和vm.$set() 不能给vm 或 vm的根数据对象 添加属性
2.2 案例练习
<body>
<div class="root">
<h2>学生信息</h2>
<button @click="student.age ++">年龄+1</button><br />
<button @click="addSex">添加性别属性,默认值:男</button><br />
<button @click="student.sex = '未知'">修改性别属性:未知</button><br />
<button @click="addFriend">在列表首位添加一个朋友</button><br />
<button @click="updateFirstFriendName">修改第一个朋友的名字为:Tom</button
><br />
<button @click="addHobby">添加一个爱好</button><br />
<button @click="updateHobby">修改第一个爱好为:露营</button><br />
<h3>姓名:{{student.name}}</h3>
<h3>年龄:{{student.age}}</h3>
<h3 v-if="student.sex">性别:{{student.sex}}</h3>
<h3>爱好:</h3>
<ul>
<li v-for="(h,index) in student.hobby" :key="index">{{h}}</li>
</ul>
<h3>好友:</h3>
<ul>
<li v-for="(f,index) in student.friends" :key="index">
{{f.name}} -- {{f.age}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: ".root",
data: {
student: {
name: "王小明",
age: "24",
hobby: ["篮球", "电子游戏", "唱歌"],
friends: [
{ name: "周星星", age: "20" },
{ name: "吴仔", age: "30" },
],
},
},
methods: {
addSex() {
// 两种写法
// Vue.set(this.student, "sex", "男");
vm.$set(this.student, "sex", "男");
},
addFriend() {
this.student.friends.unshift({ name: "张三", age: "18" });
},
updateFirstFriendName() {
this.student.friends[0].name = "Tom";
},
addHobby() {
this.student.hobby.push("拳击");
},
updateHobby() {
// 三种写法
// this.student.hobby.splice(0, 1, "露营");
// Vue.set(this.student.hobby,0,'露营');
vm.$set(this.student.hobby, 0, "露营");
},
},
});
</script>