vue监测数据的原理

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>

​ 当我触发点击事件时,可以发现前后的对比

image-20220509093135509

​ 虽然我们修改了数据,但是vue并没有监测到,就不会渲染到页面上。同时我们发现,通过我们直接赋值的这种方式,将第一个的对象属性的get和set方法没有了。

image-20220509093820584

​ 那我们通过下面这种方式操作对象的属性在进行一次数据的修改

image-20220509094120752

image-20220509094501817

​ 我们可以看到数据成功的渲染到了页面上,同时我们可以看到对象的方法并没有被删除,其背后的原理就是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>

image-20220509100550859

3、vue.set方法

​ 当我们的data已经写好,但后续需要添加一个对象时,vue给我们提供了一个set方法,给我们使用。达到重新渲染的效果。

  • 例子:Vue.set(this.student,‘sex’,‘男’) 或者 this.$Vue(this.student,‘sex’,‘男’)
    • 注意事项
      • 不允许修改vue的根数据或者vue实例
      • 只能给data里面的对象追加属性

image-20220509102346753

​ 如图所示,我们需要向红色框添加一个性别属性

    <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中给我们提供了方法

image-20220509105411737

​ 也就是说我们需要变更数组的属性值时,需要用到上面的七个方法或者利用Vue.set去修改

 this.persons.splice(0,1,{ id: '01', name: 'zy', age: '30', sex: 'man' }) 

3446

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周粥粥ya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值