Vue.$set的理解与使用

理解vue数据响应式
响应式 : 当data中的数据发生改变时 , 视图中的数据也会跟着改变

一 抛出问题

在vue中的data中定义一个空对象 , 将来动态给对象添加属性 , 改变这个属性

具体看代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <!-- 添加视图容器 -->
    <div id="app">
        <h3>渲染age属性</h3>
        <div>{{ obj.age }}</div>
        <div><button @click="changeAge">点我修改 age 的值</button></div>
        <h3>渲染 name 属性</h3>
        <div>{{ obj.name }}</div>
        <div>
            <button @click="setName">点我动态添加 name 属性</button>
        </div>
    </div> 
</body>
<script src="../vue.min.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            obj: {
                age: 18
            }
        },
        methods: {
            changeAge() {
                this.obj.age = 20
            },
            setName() {
                // 非响应式  只会给obj添加name属性及属性值 , 但视图没有更新
                // this.obj.name = 'xjj'
                // 响应式
                this.$set(this.obj, 'name', 'xjj')
            }
        }
    })
    // 响应式:
    //     当 data 中的数据发生改变时, 视图中的数据也会跟着改变
    // 什么情况下属性不会有响应式的效果:
    //     在 data 中的数据下动态添加属性是不会有响应式的效果

</script>

</html>

当更改的属性name在data中并没定义 , 这个时候触发更改name , 实质只会给data中添加了该属性和值 , 但视图没有动态更新
这个属性之所以没有在视图响应式渲染出来 , 是因为它是动态添加的
在data中的数据下动态添加属性是不会有响应式的效果

二 引出推论

动态给 data 中对象添加属性,是不会有响应式的效果的

三 解决方案

set可以实现动态为data中的对象添加具有响应式效果的属性

四 $set的具体用法

引述vue文档
向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新

用法:
Vue.set( target, key, value )
调用方法:this.$set( target, key, value )

//参数
target:要更改的数据源(可以是对象或者数组)
key:要更改或者新增属性的具体数据 (对象的key为键,数组的key为下标)
value :重新赋的值

官方解释:向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。

应用场景:
需要为data对象添加一个新属性时或修改某个属性的值时,却没有更新到视图上,这个时候就用$set解决

上述 , 可以简单理解如下

语法
// target: 响应式的对象
// protoName: 属性名(要向响应式对象中添加的属性)
// value: 属性值
Vue.set(target, protoName, value)

// 上例中
this.obj.name = 'xjj'
// target: obj
// protoName: name
// value: xjj

五 总结

<1> vue实例创建之后添加新的属性到实例上,它不会触发视图更新
=> 当生成vue实例后,这时对vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)再次给对象添加新属性并赋值时(向对象中添加新的属性及属性值),并不会自动更新到视图上去

解析:
受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时进行双向数据绑定,使用Object.defineProperty()对属性遍历添加 getter/setter 方法,因此 Vue.js 在初始化实例时将属性转为 getter/setter,
所以属性必须在 data 对象上存在时才能进行上述过程 , 让 Vue.js 转换它,才能让它是响应的。
如果要给对象添加新的属性,此时新属性没有进行过上述过程,它不是响应式的。
此时需要用到$set。

<2> Vue.set()不光能修改数据,还能添加数据
使用$set()方法,既可以为data数据模型这个对象里的属性=>新增属性(并且给这个属性赋值)或修改原有属性的值,同时可以触发视图更新

<3> 因此,$set可以理解为重新给data数据模型中的某个属性(可以是对象或者数组下的某层属性)重新赋值,无论是新增的属性或者原有的属性,都可以给他更改值,达到视图响应式更新的目的

举例
// 给数组中的对象的添加原有属性的值(给group这个数组下的满足find条件的对象的option属性下拉框添加数据,这个是数据为数组AccList)

 this.$set(this.formConfigJson.formItems[0].group.find(item => item.key === 'accPayment'), 'options', this.AccList)


作者:春秋若北
链接:https://www.jianshu.com/p/092e3de6ef0a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值