P31—列表过滤
补充知识(公众号内后台回复vue获取更多笔记):
1. arr.filter()
数组过滤
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>test</title>
</head>
<body>
<script>
const arr = [20, 21, 22, 23, 24, 25];
const arrNew = arr.filter((a) => {
return a >= 23;
});
console.log(arrNew)
</script>
</body>
</html>
代码语言:javascript复制const arrNew = arr.filter(()=>{
return 过滤条件
}) , 这个函数一定要有return值,return返回的值交给了arrNew
2. str.indexOf() 字符串出现的第一个位置
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>test</title>
</head>
<body>
<script>
const str = 'Dapan';
const num1 = str.indexOf('p'); //字符串str第一次出现'p'的位置
const num2 = str.indexOf('d'); //indexOf()方法区分大小写
const num3 = str.indexOf('a', 2); //从2这个位置(从0开始),出现'a'的第一个位置
console.log(num1, num2, num3);
</script>
</body>
</html>
- str.indexOf('') = 0; 注意: indexOf(空字符)串等于0,不等于-1
- 课堂笔记: 实现列表过滤功能:
- 1. 用watch实现列表过滤:
<div id="root">
<h1>人员列表</h1>
<input type="text" placeholder="请输入" v-model="keyWord" />
<ul>
<li v-for="(p,index) in filPersons">
{{p.name}}--{{p.age}}--{{p.sex}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
persons: [
{ id: 001, name: '马冬梅', age: 18, sex: '女' },
{ id: 002, name: '周冬雨', age: 19, sex: '女' },
{ id: 003, name: '周杰伦', age: 20, sex: '男' },
{ id: 004, name: '郭艾伦', age: 21, sex: '男' },
],
keyWord: '',
filPersons: [],
},
watch: {
keyWord: {
immediate: true, // 这里要利用代码刚开始时用搜索空字符的方式把persons里面的全部元素(对象调出来)
handler(value) {
// 过滤persons,并把过滤掉的persons赋值给filPersons:
this.filPersons = this.persons.filter((p) => {
return p.name.indexOf(value) != -1;
});
},
},
},
});
</script>
2. 用computed实现列表过滤
代码语言:javascript复制<div id="root">
<h1>人员列表</h1>
<input type="text" placeholder="请输入" v-model="keyWord" />
<ul>
<li v-for="(p,index) in filPersons">
{{p.name}}--{{p.age}}--{{p.sex}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
persons: [
{ id: 001, name: '马冬梅', age: 18, sex: '女' },
{ id: 002, name: '周冬雨', age: 19, sex: '女' },
{ id: 003, name: '周杰伦', age: 20, sex: '男' },
{ id: 004, name: '郭艾伦', age: 21, sex: '男' },
],
keyWord: '',
},
computed: {
//计算属性在模板初次读取的时候就会执行一次,相当于watch实现中的 immediate:true
filPersons() {
const filterPersons = this.persons.filter((person) => {
return person.name.indexOf(this.keyWord) != -1;
});
return filterPersons;
},
},
});
</script>
总结: 当watch和computed都能实现同一功能的时候,优先使用computed
P32 列表排序
- 补充知识:
arr.sort()
方法
- //按升序将数组进行排列: const points = [40, 100, 1, 5, 25, 10]; points.sort(function(a, b){return a-b}); //按降序将数组进行排列: const points = [40, 100, 1, 5, 25, 10]; points.sort(function(a, b){return b-a}); 注意: sort()方法会改变原始数组
- 课堂笔记: 1. 列表排序
<div id="root">
<h1>人员列表</h1>
<input type="text" placeholder="请输入" v-model="keyWord" />
<ul>
<li v-for="(p,index) in filPersons" :key="p.id">
{{p.name}}--{{p.age}}--{{p.sex}}
</li>
</ul>
<button @click="sortType = 1">年龄升序</button>
<button @click="sortType = 2">年龄降序</button>
<button @click="sortType = 0">原始循序</button>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
persons: [
{ id: 001, name: '马冬梅', age: 28, sex: '女' },
{ id: 002, name: '周冬雨', age: 19, sex: '女' },
{ id: 003, name: '周杰伦', age: 30, sex: '男' },
{ id: 004, name: '郭艾伦', age: 51, sex: '男' },
],
keyWord: '',
sortType: 0,
},
computed: {
filPersons() {
const filterPersons = this.persons.filter((person) => {
return person.name.indexOf(this.keyWord) != -1;
});
if (this.sortType != 0) {
// 这里是filterPersons.sort(),而不是filterPersons.age.sort(),是在后边再p1.age,p2.age
filterPersons.sort((p1, p2) => {
// 能用三元表达式就不用原始的if,else
return this.sortType == 1 ? p1.age - p2.age : p2.age - p1.age;
});
}
return filterPersons;
},
},
});
</script>
- 注意: 在computed中 , 其中的任何属性的变化都会让模板(M)重新解析一遍
P33 更新时的一个问题
修改data中的数据Vue检测不到的问题:
代码语言:javascript复制<div id="root">
<h1>人员列表</h1>
<ul>
<li v-for="(p,index) in persons">{{p.name}}--{{p.age}}--{{p.sex}}</li>
</ul>
<button @click="changeMei">点击修改persons[0]</button>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
persons: [
{ id: 001, name: '马冬梅', age: 18, sex: '女' },
{ id: 002, name: '周冬雨', age: 19, sex: '女' },
{ id: 003, name: '周杰伦', age: 20, sex: '男' },
{ id: 004, name: '郭艾伦', age: 21, sex: '男' },
],
},
methods: {
changeMei() {
// this.persons[0].name = '马老师'; //奏效
// this.persons[0].age = 50; //奏效
// this.persons[0].sex = '男'; //奏效
this.persons[0] = { id: 001, name: '马老师', age: 50, sex: '男' }; //不奏效
},
},
});
</script>
第二种直接修改整个元素的时候:
P34 Vue检测数据的原理_对象
data中的数据传入到vm._data中的过程:
因为Vue做了数据代理,所以vm.name == vm._data.name:
data中只要有对象,Vue就会一直给对象里的属性匹配一个getter和setter(不管有多少层,Vue会无限递归地找下去):
总结:
只要改Vue中data中的对象中的属性(调用setter) , Vue都会重新解析模板→……→更新页面
P35 Vue.set()方法
Vue中如果一个值是undefined,它不会显示到页面中
假如已经写好了data,想后期在data中的一个对象中新添加一个属性,这种方法行不通(反映不到页面上):
使用Vue.set()方法添加属性就可以反映到页面上,而且有添加属性自己的setter和getter:
另外一个方法同样可以实现与上一样的结果:
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>模拟一个数据监测</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>{{undefined}}</h1>
<h1>{{age}}</h1>
<h1 v-if="persons[0].sex">{{persons[0].sex}}</h1>
<h1>placeholder</h1>
<button @click="addSex">添加一个性别属性</button>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
name: 'Dapan',
age: 24,
persons: [
{
name: 'dapan',
age: 23,
},
],
},
methods: {
addSex() {
// methods中的this就是vm,不用再在methods中写vm (vm均被this替代)
this.$set(this.persons[0], 'sex', '女'); //这不需要在写成this._data.persons[0],因为已经做了数据代理,vm身上已经有了persons
},
},
});
</script>
</body>
</html>
注意: Vue.set()
和vm.$set()
只能给data中的某一个对象添加属性,而不能直接给data添加属性。解决办法:给你想添加的属性套上一个对象。