ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

vue3使用watch监听store简单状态管理中reactive对象

2022-07-10 03:31:07  阅读:773  来源: 互联网

标签:reactive watch value newVal vue3 inputVal 监听 store


参考:
Vue3中watch监视reactive定义数据的“坑” - csdn
watch - Vue.js
vue中watch的使用写法 - csdn
【Vue】watch的详细⽤法 - csdn
vue中watch的用法 - 博客园

前言

在项目中,我想用store来全局管理document.body.clientWidth
然而却发现watch无法监听store中的clientWidth

测试复现

我定义的store是这样的:

const store = {
    debug: true,

    // 使用一个 reactive 方法让对象作为响应式对象。
    bodyWidth: reactive({
        value: 0,
    }),

    setBodyWidthAction(newVal) {
        if (this.debug) {
            console.log('setBodyWidthAction triggered with', newVal)
        }

        this.bodyWidth.value = newVal
    },
}

加一个按钮去测试:

<el-button @click="testWatch">testWatch</el-button>

data() {
    return {
      sharedBodyWidth: this.$store.bodyWidth,
    }
},
methods: {
  testWatch() {
      this.$store.setBodyWidthAction(Math.random())
      console.log(this.sharedBodyWidth)
  },
},
watch: {
    sharedBodyWidth: {
      handler(newVal) {
        console.log(`watch sharedBodyWidth=${newVal.value}`)
      },
      immediate: true,
    },
},

发现了如下打印:
image.png

显然我们的set方法执行了,data里的变量也跟随响应式变量bodyWidth改变了
但却没有被watch监听到。

面向百度编程

面向百度编程了半小时,给watch加上了deep参数

普通的watch方法无法监听到对象内部属性的改变,需要deep属性对象进行深度监听。

watch: {
    sharedBodyWidth: {
      handler(newVal) {
        console.log(`watch sharedBodyWidth=${newVal.value}`)
      },
      immediate: true,
      deep: true,
    },
},

这下可以了:
image.png

扩展

还有另外一种方式也可以实现,直接监听reactive变量的一个属性:

watch: {
    'sharedBodyWidth.value': {
      handler(newVal) {
        console.log(`watch sharedBodyWidth=${newVal}`)
      },
      immediate: true,
    },
},

image.png

在我们监听reactive定义的对象时,默认强制开启deep,这也是监听sharedBodyWidth.value生效的原因。此外oldValue无法监听到。

如果我们要监听reactive对象定义的对象属性的子属性,需手动配置deep: true。同样的,oldValue无法监听到。

此外,immediate表示在watch中首次绑定得时候,是否执行handler。默认是false

watch的写法

关于watch的写法,大概有4种:

watch: {
  // 1: a可以是data,也可以是computed
  a(newVal, oldVal) {},
  // 2: 
  a: {
      handler(newVal,oldVal){},
      immediate:false,
      deep:false,
  },
  // 3: 
  'a.v': {
      handler(newVal,oldVal){},
      immediate:false,
      deep:false,
  },
  // 4: 监听store中的状态
  '$store.a.value': {
      handler(newVal,oldVal){},
  }
}

使用store的状态做双向数据绑定

const store = {
    inputVal: reactive({
        value: "inputVal is a string"
    }),

    setInputValAction(newValue) {
        this.inputVal.value = newValue
    },
}
<el-input v-model="inputVal"></el-input>
// ...
  computed: {
    inputVal: {
      get() { // 使用箭头函数this是undefined
        return this.$store.inputVal.value
      },
      set(val) {
        this.$store.setInputValAction(val)
      },
    }
  },
  watch: {
    "$store.inputVal.value": {
      handler(newVal) {
        console.log(`watch $store.inputVal.value=${newVal}`)
      },
      immediate: true,
    },
    inputVal(newVal) {
      console.log(`watch inputVal=${newVal}`)
    },
  },

image.png

image.png

标签:reactive,watch,value,newVal,vue3,inputVal,监听,store
来源: https://www.cnblogs.com/libaiyun/p/16462459.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有