vue监测数据的原理
-
原理
-
vue会监视data中所有层次的数据
-
如何监测对象中的数据?
-
通过setter事件监视,且要在newVue时就传入要监测的数据
-
在对象后追加的属性,Vue默认不做响应式处理
-
如需给后添加的属性做响应式,需要使用以下API:
Vue.set(target,propertyName/index,value)
vm.$ser(target,propertyName/index,value)
-
-
如何监测数组中的数据?
- 通过包裹数组更新元素的方法实现,本质就是做了两件事:
- 调用原生对应的方法对数组进行更新
- 重新解析模板,进而更新页面
-
在Vue修改数组中的某个元素需要用到以下方法:
- 使用这些API:push(),pop(),shift(),unshift(),splice(),sort(),erverse()
- Vue.set()或vm.$set
-
1、例子 更新一个人的信息
<!-- html -->
<div id="root">
<h1>更新信息的一个问题</h1>
<ul>
<li v-for="(p,index) in persons" :key="p.id">
{{p.name}}-{{p.age}}
</li>
</ul>
<!-- 只能更新第一条的信息 -->
<button @click="upData">点我更新一条信息</button>
</div>
<!-- vue -->
<script>
const vm = new Vue({
el:'#root',
data:{
persons: [
{ id: '01', name: '周冬雨', age: '20', sex: 'woman' },
{ id: '02', name: '马冬梅', age: '30', sex: 'woman' },
{ id: '03', name: '周杰伦', age: '21', sex: 'man' },
{ id: '04', name: '马东伦', age: '40', sex: 'man' },
],
},
methods:{
//更新第一条信息
upData(){
this.persons[0]= { id: '01', name: 'zy', age: '30', sex: 'man' }
}
}
})
</script>
当我触发点击事件时,可以发现前后的对比
虽然我们修改了数据,但是vue并没有监测到,就不会渲染到页面上。同时我们发现,通过我们直接赋值的这种方式,将第一个的对象属性的get和set方法没有了。
那我们通过下面这种方式操作对象的属性在进行一次数据的修改
我们可以看到数据成功的渲染到了页面上,同时我们可以看到对象的方法并没有被删除,其背后的原理就是Vue底层利用了Object.defineProperty 做数据代理
,通过get和set函数进行修改和解析,封装成Observer方法遍历data的属性,并对属性添加getter和setter。
而我们用的persons[0].name是对象中的属性,所以会触发监听重新渲染页面。
2、简单实现一个vue监测数据的原理
<script>
let data = {
name:'zy',
age:18
}
const obs = new Observer(data)
console.log(obs);
//new 一个vm实例对象
let vm ={}
vm._data = data = obs
function Observer(obj) {
//汇总对象中的所有属性,形成一个数组
const keys = Object.keys(obj)
console.log(keys);
//遍历
keys.forEach((item)=>{
//这里this指向的是Observer的实例对象
Object.defineProperty(this,item,{
get(){
//返回对应属性身上的值
return obj[item]
},
set(val){
//修改对应属性身上的值
obj[item]=val
}
})
})
}
</script>
3、vue.set方法
当我们的data已经写好,但后续需要添加一个对象时,vue给我们提供了一个set方法,给我们使用。达到重新渲染的效果。
- 例子:Vue.set(this.student,‘sex’,‘男’) 或者 this.$Vue(this.student,‘sex’,‘男’)
- 注意事项
- 不允许修改vue的根数据或者vue实例
- 只能给data里面的对象追加属性
- 注意事项
如图所示,我们需要向红色框添加一个性别属性
<div id="root">
<button @click="addSex">添加一个性别:默认值为男</button>
<h2>姓名:{{student.name}}</h2>
<h2>年龄:{{student.age}}</h2>
<!-- 这里要注意 如果值为undefind vue不会渲染,也就是开始data.student中没有sex这个属性 -->
<h2>性别:{{student.sex}}</h2>
</div>
<script>
new Vue({
el:'#root',
data:{
student:{
name:'zy',
age:'1'
}
},
methods:{
addSex(){
Vue.set(this.student,'sex','男')
}
}
})
</script>
4、利用vue提供的方法做例1 -更新一个人的信息
在开头我们直接利用
this.persons[0]= { id: '01', name: 'zy', age: '30', sex: 'man' }
修改数组不会奏效,同时页面也不会渲染。在vue中给我们提供了方法
也就是说我们需要变更数组的属性值时,需要用到上面的七个方法或者利用Vue.set去修改
this.persons.splice(0,1,{ id: '01', name: 'zy', age: '30', sex: 'man' })