初学者彻底搞懂何时给Vue中添加数据和修改数据能做成响应式的,而何时又不能。

带着一点个人理解,我们来聊聊这个初学者很容易遇到的问题,本人也作为一个初学者,看到这里,思路理清了,记录下这个文章,以防止遗忘。

首先我们来聊聊,响应式。

Vue底层的响应式实现原理来自于Object内置的一个方法

Object.defineProperty()

在搞懂之前,我们必须搞懂这个方法。

这个方法有三个参数。

第一个参数: obj 即你想要操作的对象

第二个参数: 你想要定义的属性名

第三个参数:

一个配置对象(知道什么是配置对象的这个括号可以不用看,配置对象,就是属性名固定,根据你的需要进行配置。)

这个配置对象常用的有三个

第一个是
value属性,用于你来定义你的属性名的值(第二个参数的值)

第二个是

get(){}
或者说
get:function(){}

第三个是

set(){}
或者说
set:funtion(){}

get用于当访问了你定义的属性的时候要干什么(自动执行)
set用于当更改了你定义的属性的时候要干什么(自动执行)

ok这个方法我们就介绍到这里。

接下来看看,响应式,

总的来说,能不能添加成响应式的,就要看你有没有用Vue/vm来添加用Vue封装的几个能改变数组的方法也算。
我们来看几个例子

例子一

  <div id="root"></div>
    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                student: {
                    name: 'tom',
                    age: 18,
                    hobby: ['抽烟', '喝酒', '烫头'],
                    friends: [
                        { name: 'jerry', age: 35 },
                        { name: 'tony', age: 36 },
                    ]
                }
            }
        })
        vm.$set(vm.student, 'gender', '男');
    </script>

我们通过谁添加的?
vm

通过vm添加的,就会有响应式,vm就能看到他的变化,原理就是用我们刚才介绍的方法实现的,底层逻辑是👇来做的。用这个就会为我们的属性添加getter和setter方法

 Object.defineProperty()

在这里插入图片描述

所以我们检测到变化,Vue就能在你变化的时候,解析Vue模板,生成虚拟DOM,对比真实DOM,该复用的复用,然后产生页面。

ok,再看一个例子

例子二

<div id="root"></div>
    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                student: {
                    name: 'tom',
                    age: 18,
                    hobby: ['抽烟', '喝酒', '烫头'],
                    friends: [
                        { name: 'jerry', age: 35 },
                        { name: 'tony', age: 36 },
                    ]
                }
            }
        })
        vm._data.student.gender = "男"
        //也可以写成vm.student.gender="男"
        //原理就是数据代理。
    </script>

请问我们是利用vm添加的吗?
不是,换句话说,我们不是让vm帮我们添加的,
我们是把vm当成个靶子,往他的身上的student对象身上插了一个属性。

so,没有用vm添加,那就没有用底层的👇方法

 Object.defineProperty()

自然不会有getter和setter,自然我们不能检测到变化,自然不会产生响应式,所以,你对他修改,Vue也就看不到。
在这里插入图片描述
在这里插入图片描述
尽管你有但是你是强插的,不是通过Vue/vm 依据我们说的 Object.defineProperty()添加,那你不可能有getter和setter,你没有Vue就拿不到,拿不到,就不会有虚拟DOM生成,更不会生成真实DOM,也就没有页面了。
在这里插入图片描述
例子三

 <div id="root">
        <h2>{{student.gender}}</h2>
    </div>
    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                student: {
                    name: 'tom',
                    age: 18,
                    gender: '女',
                    hobby: ['抽烟', '喝酒', '烫头'],
                    friends: [
                        { name: 'jerry', age: 35 },
                        { name: 'tony', age: 36 },
                    ]
                }
            }
        })
        vm._data.student.gender = "男"
    </script>

在这里插入图片描述

和例子二很像,我们只不过是给内部写了一个gender数据,请问,这个gender:女 是不是根据Vue添加的?

答案是yes 我们写在Vue里面,最终当然是由Vue添加的。
而为什么可以修改这个值了呢?
因为Vue帮我们配置好getter和setter。

我们是写在Vue里的啊别忘了!

所以最终值可以修改。

例子三
是个判断题,

  <div id="root">
        <h2>习惯</h2>
        <ul>
            <li v-for="(h,index) in student.hobby" :key="index">
                {{h}}
            </li>
        </ul>
    </div>
    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                student: {
                    name: 'tom',
                    age: 18,
                    gender: '女',
                    hobby: ['抽烟', '喝酒', '烫头'],
                    friends: [
                        { name: 'jerry', age: 35 },
                        { name: 'tony', age: 36 },
                    ]
                }
            }
        })
        vm.student.hobby[0] = '学习'
    </script>

请问,这样写,页面产生的是
抽烟喝酒烫头
还是
学习喝酒烫头?

结果是抽烟喝酒烫头。

为啥?
在这里插入图片描述

原理很简单,再让我们去回忆一下那句话
Vue检测数据变化的底层逻辑是一个方法

 Object.defineProperty()

请问,这个方法是干嘛的?
是不是对对象的属性做监测的啊?
是不是对象的属性做检测的啊?
检测的一定是对象的属性,
那么请问!

一个数组的数组单元,是对象的属性吗?
不是。

那么,你去修改它会有setter或者getter为你服务吗?
不会。

既然不会,那Vue能检测到它的变化吗?
不能

所以,检测不到变化,你改变它就毫无意义,Vue无法根据你的变化生成虚拟DOM,对比真实DOM做出页面的调整。

接下来我们看一个数组的例子。

 <div id="root">
        <h2>习惯</h2>
        <ul>
            <li v-for="(h,index) in student.hobby" :key="index">
                {{h}}
            </li>
        </ul>
    </div>
    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                student: {
                    name: 'tom',
                    age: 18,
                    gender: '女',
                    hobby: ['抽烟', '喝酒', '烫头'],
                    friends: [
                        { name: 'jerry', age: 35 },
                        { name: 'tony', age: 36 },
                    ]
                }
            }
        })
        // vm.student.hobby[0] = '学习'
        vm.student.hobby.push('开车');
    </script>

请问这样能添加上,并且响应到页面上吗?
可以

为啥?因为我们用的是vm为我们包装的7个能改变数组自身的方法之一做的。在这里插入图片描述
这是7个能改变数组自身的方法,他们被Vue包装过了,Vue所以能检测到变化,生成虚拟DOM等操作,下图可以证明,push已经被封装,修改过了。添加的功能就是可以被Vue检测到等一系列操作。在这里插入图片描述

所以,总结一下。

总的来说,能不能加成响应式的,要看你没有用Vue/vm来加(指向vm强插不算,因为那时vm根本没发挥它的作用,只不过是当个靶子在往vm身上插属性罢了,)

添加的方式,三种1. Vue.set() 2. vm.$set() 3. 数组自带的7种被Vue包装的方法(都可以影响数组自身变化的那7种)。

判断属性改了会不会有效果: 要取决于你这个属性到底是不是响应式的,即 有没有getter或setter。

数组里的单元,具体到某个单元,是没有getter或settr的!!!!

为啥没有getter和settr?
回忆回忆 object.defineproperty(obj,属性名,),这是getter和setter的起源,getter和setter的起源就在object.defineproperty。而起源的时候,这个方法就是为了对象的属性名而生。

如果数组单元是个对象,对象里的属性,如果是通过vm/Vue或者数组自带的7种被Vue包装的方法添加的。是有getter和setter的!!!

Thanks for watching💕

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值