0%

Vue监视数据原理

1 Vue会监视data中所有层次的数据(递归)

2 如何监视对象中的数据?

通过setter实现监视,且要在new Vue的时候就传入要监测的数据。

(1)对象中后追加的属性,Vue默认不做响应式处理

(2)如需给后续添加的属性左响应式,请使用下面的API:

​ Vue.set(target,propertyName/index,value):target不允许是Vue实例或者vm中的data对象

vm.$set(target,propertyName/index,value)

3 如何监测数组中的数据?

通过包裹数组更新元素的方法实现,本质做了两件事:

(1) 调用原生对应的方法对数组进行更新

(2) 重新解析模板,进而更新页面

4 在Vue中修改数组中的某个元素一定要用如下方法:

(1)使用这些API:push(),shift(),unshift(),splice(),sort(),reverse()

(2)Vue.set()或vm.$set()

非变更方法,例如 filter()concat()slice()。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组:

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是没有问题的

id_key

index_key

条件渲染

1 v-if:

写法:

(1). v-if=”表达式”

(2) v-else-if=”表达式”

(3) v-else

适用于:切换频率较低的情景

特点:不展示的DOM元素直接被移除

注意:v-if和v-else-if,v-else一起使用时要求结构不能被打断

2 v-show

写法: v-show=”表达式”

适用于:切换频率较高的场景

特点:不展示的DOM元素未被移除,使用display=none隐藏掉

PS:

1 使用v-if时,元素可能无法获取到,而使用v-show一定可以获取到

2 v-if可以和template配合使用

绑定class样式

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
 <div id="demo">
<!-- 绑定class样式--字符串写法,适用于样式类名不确定。需要动态确定 -->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
<!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定,名字也不确定 -->
<div class="basic" :class="classArr">{{name}}</div>
<!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定,名字也确定,但要动态决定用不用 -->
<div class="basic" :class="classObj">{{name}}</div>

</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.config.productionTip = false
Vue.createApp({
data(){
return{
name:'Ann',
mood:'normal',
classArr:['c1','c2','c3'],
classObj:{
'c1':false,
'c2':false,
}

}
},
methods:{
changeMood(){
const arr=['happy','sad','normal']
this.mood=arr[Math.floor(Math.random()*3)]
}
}

}).mount('#demo')
</script>

绑定style样式

1 :style=”{fontSize: xxx}”,其中xxx是动态值

computed和watch的区别:

1 computed能完成的功能watch也能完成,computed支持缓存

2 watch能完成的功能computed不一定能完成,例如watch能完成异步操作

PS:

1 所有被Vue管理的函数要写成普通函数,这样new Vue的实例的时候this才能绑定到新创建的vm或组件实例对象

2 所有不被Vue管理的函数比如(定时器的回调函数,ajax的回调函数和Promise的回调函数)最好写成箭头函数,箭头函数的this绑定会继承外层函数的this绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Vue.createApp({
data(){
return {
firstName:"张",
lastName:"三",
fullName:"张三"

}

}
watch:{
firstName(val){
setTimeout(()=>{
this.fullName=val+this.lastName},1000)
},
lastName(val){
setTimeout(()=>{
this.fullName=thia.firstName+val},1000)

}
}
})

总结:

watch和computed都是以Vue的依赖追踪机制为基础,当某一个依赖型数据(简单理解为放在data等对象下的实例数据)发生变化,所有依赖这个数据的相关数据会自动发生变化,即自动调用相关函数,来实现数据的变动

使用场景:

computed:用于处理复杂的逻辑运算,一个数据首一个或多个数据影响,用来处理watch和methods无法处理或者处理起来不方便的情况,例如处理模板中的复杂表达式

watch:用来处理一个属性变化时,需要执行某些具体的业务操作逻辑,或要在数据变化时执行异步或开销较大的操作;例如用来监控路由,input输入值的特殊处理等

计算属性

1 定义: 要用的属性不存在,要通过已有的属性计算得来

2 原理: 底层借助了Object.defineproperty()方法提供的getter和setter。

3 get函数什么时候执行

(1) 初次读取时会执行一次

(2)当依赖的数据发生改变时会被再次调用

4 优势:与methods相比。内部有缓存机制,效率更高,调试方便

5 计算属性最终会出现在vm中,直接读取使用即可

如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变

简写:函数

Vue3中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
setup(){
//计算属性简写
let fullName=computed(()=>{
return person.firstName+"-"+person.lastName
})
//计算属性完整
let fullName=comouted({
get(){
return person.firstName+"-"+person.lastName
}
set(val){
const nameArr=value.split("-")
person.firstName=nameArr[0]
person.lastName=nameArr[1]

}
})

}

事件的基本使用:

  1. 使用v-on:xxx或@xxx绑定事件,其中xxx是事件名

  2. 事件的回调需要配置在methods对象中,最终会在vm上

  3. methods中配置的函数,不要用箭头函数,否则this就不是vm

  4. methods中配置的函数,都是被Vue管理的函数,this的指向是vm或组件实例对象

  5. @click=”demo”和@click=”demo($event)”效果一致,但后者可以传参

事件修饰符

prevent:阻止默认事件

stop:阻止事件冒泡

once:事件只触发一次

键盘事件

1 Vue常用按键别名:

回车:enter

删除:delete

退出:esc

空格:space

换行:tab(特殊,必须配合keydown使用)

上:up

下:down

左:left

右:right

2 Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为keb-case(短横线命名)

3 系统修饰符(用法特殊):ctrl,alt,shift,meta

(1)配合keyup使用:按下修饰键的同时再按下其他键,随后释放其他键,事件才被触发

(2)配合keydown使用:正常触发事件

4 也可以使用keyCode去指定具体的键

5 Vue.config.keyCode自定义键名=键码,可以定制按键别名

  1. Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读或写

  2. Vue中数据代理的好处:更加方便操作data中的数据

  3. 基本原理

    ​ 通过Object.defineProperty()把data对象中的所有属性添加到vm上中,为每一个添加到vm上的属性都指定一个getter()setter()函数,在getter()setter()函数;里面去操作data中对应的数据

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
 const vm=Vue.createApp({
data(){
return{
name:'Ann',
address:'06404'
}
}
})
vm
{
...
_data{
name:(...),
address:(...),
}
name:(...)
address:(...)//Object.defineProperty()
Object.defineProperty(vm,'name',{
value:_data.name.get()
enumerable:
writable:
configurable://默认为false,控制属性是否可以被删除

get(){
return _data.name.get()
}
set(value){
_data.name.set(value)
}
})
Object.defineProperty(vm,'address',{
value:_data.address.get()
enumerable:
writable:
configurable://默认为false,控制属性是否可以被删除
get(){
return _data.address.get()
}
set(value){
_data.address.set(value);
}
})
}

MVVM

  1. M:模型(Model) data中的数据

  2. V:视图(View) 模板代码

  3. VM:视图模型(ViewModel):Vue实例

data中的所有属性最后都出现在vm身上

vm上的所有属性及Vue原型上的所有属性,在Vue模板中都可以直接使用

1
2
3
4
5
6
7
8
9
10
<div>
View
</div>
const vm=Vue.createApp({//vm:VM
data(){
return{
Model
}
}
})

数据绑定

1. 单向绑定

v-bind:数据只能从data流向页面

2.双向绑定

v-model:数据不仅能从data流向页面,还能从页面流向data

v-model:value的value可以简写为v-model,因为v-model默认收集的就是value值