}
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
// 第一种监视属性的写法
// watch:{
// isHot:{
// // immediate的作用是初始化时就调用handler
// immediate:true,
// /*
// handler什么时候调用?当isHot发生改变时,
// 并且调用时会返回修改前的值以及修改后的值
// */
// handler(newValue, oldValue){
// console.log("ishot被监视了",newValue, oldValue)
// }
// }
// }
})
// 第二种监视属性的写法, 通过此方法监视时注意要在监视属性上加上引号
vm.$watch('isHot', {
immediate: true,
handler(newValue, oldValue) {
console.log("ishot被监视了", newValue, oldValue)
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
9.2.3 天气案例–深度监视
天气案例
今天天气很{{info}}
切换天气为a加1 a的值为: {{num.a}}
为b加1 a的值为: {{num.b}}
今天天气很{{info}}
切换天气<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
//正常写法
/* isHot:{
// immediate:true, //初始化时让handler调用一下
// deep:true,//深度监视
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}, */
//简写
/* isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
} */
}
})
//正常写法
/* vm.$watch('isHot',{
immediate:true, //初始化时让handler调用一下
deep:true,//深度监视
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}) */
//简写
/* vm.$watch('isHot',function(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
}) */
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
9.3 watch与computed的比较
姓名案例_watch实现
名:
全名:{{fullName}}
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三',
fullName:'张-三'
},
watch:{
firstName(val){
setTimeout(()=>{
console.log(this)
this.fullName = val + '-' + this.lastName
},1000);
},
lastName(val){
this.fullName = this.firstName + '-' + val
}
}
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
10. class与style绑定
绑定样式
.basic {
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy {
border: 4px solid red;
; background-color: rgba(255, 255, 0, 0.644); background: linear-gradient(30deg, yellow, pink, orange, yellow); }
.sad {
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
.normal {
background-color: skyblue;
}
.atguigu1 {
background-color: yellowgreen;
}
.atguigu2 {
font-size: 30px;
text-shadow: 2px 2px 10px red;
}
.atguigu3 {
border-radius: 20px;
}
</style>
<!-- 绑定class样式 --- 数组写法,适用于:要绑定的样式个数不确定,名字也不确定 -->
<div class="basic" v-bind:class="classArr">{{ name }}</div>
<!-- 绑定class样式 --- 对象写法,适用于:要绑定的样式个数确定,名字不确定,但要动态决定用不用 -->
<div class="basic" :class="classObj">{{ name }}</div>
<!-- 绑定class样式 --- 对象写法: -->
<div class="basic" :style="styleObj">{{ name }}</div>
<!-- 绑定class样式 --- 数组写法: -->
<div class="basic" :style="styleArr">{{ name }}</div>
</div>
<script>
Vue.config.productTip = false;
new Vue({
el: "#root",
data: {
name: "zhangsan",
mood: "normal",
classArr: ['atguigu1', 'atguigu2', 'atguigu13'],
classObj: {
atguigu1: false,
atguigu2: true
},
styleObj: {
backgroundColor: "red"
},
styleObj2: {
fontSize: '40px',
color: 'blue',
},
styleArr: [{
fontSize: '40px',
color: 'blue',
}, {
backgroundColor: "red"
}]
},
methods: {
changeClass() {
this.mood = "sad"
}
}
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
11. 条件渲染
条件渲染
2.v-show
写法:v-show="表达式"
适用于:切换频率较高的场景。
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
-->
<!-- 准备好一个容器-->
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click="n++">点我n+1</button>
<!-- 使用v-show做条件渲染 -->
<!-- <h2 v-show="false">欢迎来到{{name}}</h2> -->
<!-- <h2 v-show="1 === 1">欢迎来到{{name}}</h2> -->
<!-- 使用v-if做条件渲染 -->
<!-- <h2 v-if="false">欢迎来到{{name}}</h2> -->
<!-- <h2 v-if="1 === 1">欢迎来到{{name}}</h2> -->
<!-- v-else和v-else-if -->
<!--
<div v-if="n === 1">Angular</div>
<div v-else-if="n === 2">React</div>
<div v-else-if="n === 3">Vue</div>
<div v-else>哈哈</div>
-->
<!-- v-if与template的配合使用,但是template不能和v-show配合使用 -->
<template v-show="n === 1">
<h2>你好</h2>
<h2>张三</h2>
<h2>北京</h2>
</template>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'张三',
n:0
}
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
12. 列表渲染
12.1 列表渲染简介
列表渲染
- {{s.id}} - {{s.name}} - {{s.age}}
new Vue({
el: '#root',
data: {
persons: [
{ id: '001', name: '张三', age: 18 },
{ id: '002', name: '李四', age: 19 },
{ id: '003', name: '王五', age: 20 }
]
},
methods: {
add() {
const p = { id: '004', name: '老刘', age: 40 }
this.persons.unshift(p)
}
},
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
12.2.1 遍历列表时index作为key
假设初始数据只有三条,分别时张三、李四、王五,然后Vue会根据数据在内存中生成虚拟DOM,虚拟DOM中的节点含有key属性,key属性的值为index,随后会将虚拟DOM转换为真实DOM
当有新数据添加时,比如逆序添加老刘到数据的最上方,那么Vue将改变后的数据形成虚拟DOM时也会将老刘这条数据放置到节点的最上方,Vue存在虚拟节点对比算法,如果有数据改变时就调用此算法让修改后的虚拟DOM与原虚拟DOM进行比较
比较过程:由于老刘位于数据的最上方,因此其key的值为0,diff算法会寻找原虚拟DOM中key为0的节点,发现原DOM中的节点内容与新虚拟节点的DOM中的内容不一样,因此将虚拟节点转换成真实节点时会生成新的DOM,不会使用原来的虚拟DOM,但是input标签对比时发现是一样的,因此会复用原来的input节点,所以老刘后面的输入框内部会有张三的内容填充,当对比新虚拟DOM中的张三节点时,其key值为1,因此将两种key=1的节点对比时发现其内容不一样,因此也会再次新生成内容为张三的节点,在对比张三后面的input输入框时发现与原来的虚拟DOM是一样的,因此也会复用原来的输入框…当对比王五这个节点时发现其key的值为3,原虚拟DOM中没有key值为3的节点,因此会新生成王五节点以及后面的输入框
通过上述分析可知,若使用index作为key的值,原本的虚拟DOM均不会使用,会新生成大量的新节点,造成效率降低
12.2.2 遍历时使用id作为key 当使用id作为key值时,一旦数据有变化,使用diff算法对比新的虚拟DOM以及原来的虚拟DOM时,会根据key的值大量复用原来的虚拟dom,只会重新生成新增数据的节点,因此效率较高,且不会出现页面错乱的情况。
12.3 列表过滤
列表过滤人员列表
- {{p.name}}-{{p.age}}-{{p.sex}}
<script>
// 使用watch监视实现
Vue.config.productionTip = false
// 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函数
// handler(val) {
// this.filterPersons = this.persons.filter((p) => {
// return p.name.indexOf(val) !== -1
// })
// }
// }
// }
// })
// 使用计算属性实现
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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
12.3 列表排序
列表过滤
人员列表
年龄降序 年龄升序 原顺序 <ul>
<li v-for="(p,index) in filterPersons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false