• 浅析如何保证vuex中的state动态添加属性的响应式及解决deep watch / computed监听vuex state对象属性变化不生效的问题


    一、vuex 的 state 如何保证其响应式

      vuex 的 store对象的 state 是响应式的,凡是预先在 state 中定义的状态,都会被加入到响应式系统中,当状态发生了变化,所有引用状态的 vue 文件的 template 都会随之发生变化,做到响应式的功能。

      但是其前提是:提前定义好的会被加入到响应式系统中,那后面追加的属性或对象能不能加入到响应式系统中呢?

      答案是:不能,但是,如果按照指定的方式来添加和删除属性,是可以做到响应式的。

      比如现在我要添加一个新属性 height,用两种方式添加,如下:

    1、方式1:此种方式能添加 state 中对象的属性,但无法加入到响应式系统中,即页面上不会显示出来,实际上确实存在了这个属性

    mutations: {
      addheight(state){
        state.stus[0]['height'] = 168
      }
    }

    2、方式2:此方式可以让属性加入到响应式系统中

    mutations: {
      addheight(state){
        Vue.set(state.stus[1],'height',178) //参数一为对象,参数二为key,参数为value
      }
    }

    3、方式3:用新对象给旧对象重新赋值(下面会介绍到)

    4、说完添加属性,再说下删除吧,想要删除属性并加入响应式系统,如下方式:

    mutations: {
      delheight(state){
        Vue.delete(state.stus[1],'height') //参数一为对象,参数二是key
      }
    }

    5、总结:

    (1)Vuex 的 store 对象中的 state 是响应式的,当 state 中的数据发生改变时,vue 组件会自动更新。

    (2)但是它有一个前提条件,与我们之前了解的响应式前提是一致的,就是需要:提前在 state 中定义好所需的初始化属性。动态添加的属性是不能响应式的。

    (3)如何保证动态添加的属性的响应式呢 - 有一下两种方式

      方式一:使用 Vue.set(obj, key, value)

      方式二:使用新对象给旧对象重新赋值

    (4)在state删除已经存在的属性,使用 delete + 属性满足不了响应式,必须这样使用:Vue.delete(obj, 属性名)

    二、解决 computed 监听 vuex 中 state 对象属性不生效的问题

      首先我们需要了解一个前提基础:

    computed 属性监听对象时候,若对象的引用地址未改变,那么computed将不会检测到。

    比如object中的某个key对应的value发生了变化,computed检测不出来

    // 原写法
    export default {
        namespaced: true,
        state: {
            info:{
                 other: {}
            }
        },
        mutations: {
            addInformation(state,info){
                let data = Object.assign(state.info, info);
                //此时 state.info 的值改变了,但是引用地址没变
                state.shareInformation = data;
            },
        }
    }

      使用 Object.assign() 的目标对象仍然是 state.info ,所以虽然其值变了,但是引用地址是没变的,所以 computed 检测不到。

    // 正确写法
    addInformation(state,info){
      //创建一个新的对象,将state.info,Info 对象复制到新对象中
      let data = Object.assign({},state.info,info);
      //将 state.info 指向新对象的引用地址
      state.info = data;
    },

      使用 Object.assign() 的目标对象是个空对象,将 2 个源对象 state.info、info 的内容复制到新对象上 ,所以其值变了,引用地址也变了。这样 computed 才可以检测到。

    三、vue 关于 deep watch 监听不到 vuex state 对象变化的的问题

      简而言之,如果 vuex state 中是一个空对象 {},那么监听就会有问题,必须得有提前定义好的初始化属性才可以保证监听。那么如果无法确定动态添加属性的 key 是啥,怎么办呢?先给出解决方案:

    // 简易拷贝
    let _reply = JSON.parse(JSON.stringify(state.reply))
    // 加入动态属性 orderId 是变化的
    _reply[orderId] = data.orderId
    // 更新,只能这样一波骚操作才能让computed和watch监听到。 state.reply = _reply

      具体原因其实跟第二章一样,要保证其引用地址变了才行。

  • 相关阅读:
    VS2008无法切换到视图设计器
    Log4net使用笔记
    VS2008无法切换到视图设计器
    openstack(Pike 版)集群部署(五)--- Neutron 部署
    openstack(Pike 版)集群部署(四)--- Nova 部署
    Centos 7 MariaDB Galera cluster 部署
    Centos 7 RabbitMQ + Haproxy 集群高可用部署
    openstack(Pike 版)集群部署(三)--- Glance 部署
    openstack(Pike 版)集群部署(二)--- Keystone 部署
    openstack(pike 版)集群部署(一)----基础环境部署
  • 原文地址:https://www.cnblogs.com/goloving/p/15544157.html
Copyright © 2020-2023  润新知