【问题标题】:Vue JS Watching deep nested objectVue JS 观察深层嵌套对象
【发布时间】:2025-12-19 00:35:06
【问题描述】:

免责声明:这是我第一次尝试构建 MVVM 应用程序,我之前也没有使用过 vue.js,所以很可能我的问题是由更基本的问题引起的。


在我看来,我有两种带复选框的块:

  • 类型 1:块/复选框
  • 类型 2:块/标题/复选框

底层对象的结构如下:

{
  "someTopLevelSetting": "someValue",
  "blocks": [
    {
      "name": "someBlockName",
      "categryLevel": "false",
      "variables": [
        {
          "name": "someVarName",
          "value": "someVarValue",
          "selected": false,
          "disabled": false
        }
      ]
    },
    {
      "name": "someOtherBlockName",
      "categryLevel": "true",
      "variables": [
        {
          "name": "someVarName",
          "value": "someVarValue",
          "categories": [
            {
              "name": "SomeCatName",
              "value": "someCatValue",
              "selected": false,
              "disabled": false
            }
          ]
        }
      ]
    }
  ]
}

我的目标

选中复选框:

  1. 用户点击复选框,复选框被选中 (selected=true)
  2. 触发一个方法来检查是否需要禁用任何其他复选框 (disabled=true)。 (如果此方法确实禁用了任何东西,它还会再次调用自身,因为其他项目可能反过来依赖于禁用的项目)
  3. 另一种方法更新一些其他内容,例如图标等

清除复选框

用户可以单击“清除”按钮,取消选中列表中的所有复选框 (selected=false)。此操作还应触发可选择禁用复选框和更新图标等的方法。

我目前的方法 (看起来不太正确)

  • 数据模型的选定属性绑定到选中的 复选框元素的状态通过v-model 指令。
  • 禁用属性(来自模型)绑定到元素的类和禁用属性。该状态由上述方法设置。
  • 为了初始化禁用复选框和更改某些图标的方法,我使用了v-on="change: checkboxChange(this)" 指令。 我认为我需要以不同的方式完成这部分
  • clearList 方法通过v-on="click: clearList(this)" 调用

我当前设置的问题是当以编程方式清除复选框时(即不是通过用户交互),更改事件没有触发。

我想要什么
对我来说,最合乎逻辑的做法是使用 this.$watch 并跟踪模型的变化,而不是监听 DOM 事件。

一旦发生变化,我就需要确定哪个确切的项目发生了变化,然后采取行动。我试图创建一个观察blocks 数组的$watch 函数。这似乎很好地适应了变化,但它返回的是完整的对象,而不是已更改的单个属性。此对象还缺少一些方便的辅助属性,例如$parent

我可以想出一些让应用程序正常工作的 hacky 方法(比如在我的 clearList 方法中手动触发更改事件等),但我的用例似乎很标准,所以我希望可能有一种更优雅的方式来处理这个。

【问题讨论】:

    标签: javascript mvvm vue.js


    【解决方案1】:

    您可以使用 'watch' 方法.. 例如,如果您的数据是:

    data: {
        block: {
            checkbox: {
                active:false
            },
            someotherprop: {
                changeme: 0
            }
        }
    }
    

    你可以这样做:

    data: {...},
    watch: {
       'block.checkbox.active': function() {
            // checkbox active state has changed
            this.block.someotherprop.changeme = 5;
        } 
    }
    

    【讨论】:

    • .selected 和 .disabled 是属于变量数组的匿名变量对象的属性。您的示例有效,因为它只是一个对象而不是数组。
    • 我做了类似 block.checkbox.active 的操作,但在我将它们添加到“”中之前它不起作用,就像你上面提到的那样。谢谢。现在可以了。
    【解决方案2】:

    如果您想观察对象作为一个整体及其所有属性,而不仅仅是一个属性,您可以这样做:

     data() {
        return {
           object: {
              prop1: "a",
              prop2: "b",
           }    
        }
     },
     watch: {
        object: {
            handler(newVal, oldVal) {
                // do something with the object
            },
            deep: true,
        },
    },
    

    注意handlerdeep: true

    如果你只想看prop1你可以这样做:

    watch: { 
        'object.prop1' : function(newVal, oldVal) { 
            // do something here 
         }
    }
    

    【讨论】:

    • 谢谢。但是,由于我的问题已经超过两年了,并且从那时起我就没有使用过 Vue,所以我无法验证这是否有效。
    • @Hendrik 不用担心,我希望这可以帮助遇到同样问题的人
    • 我只想看prop1你知道我该怎么做吗?
    • @SylvainAttoumani 是的:在我的例子中:watch: { 'object.prop1' : function(newVal, oldVal) { // do something here }}
    • @peerbolte 我认为评论应该是答案的一部分。你会得到更多的支持。
    【解决方案3】:

    此处未提及的其他解决方案: 使用deep 选项。

    watch:{
      block: {
        handler: function () {console.log("changed") },
        deep: true
      }
    }
    

    【讨论】:

      【解决方案4】:

      由于没有人回复并且我现在已经解决/解决了这个问题,我认为发布我的解决方案可能会很有用。请注意,我不确定我的解决方案是如何处理这些类型的事情,但它确实有效。

      我现在使用自定义指令而不是使用此事件侦听器v-on="change: checkboxChange(this)",它同时侦听选定和禁用的模型属性,如下所示:v-on-filter-change="selected, disabled"

      指令如下所示:

      directives: {
          'on-filter-change': function(newVal, oldVal) {
              // When the input elements are first rendered, the on-filter-change directive is called as well, 
              // but I only want stuff to happen when a user does someting, so I return when there is no valid old value
              if (typeof oldVal === 'undefined') {
                  return false;
              }
              // Do stuff here
              // this.vm is a handy attribute that contains some vue instance information as well as the current object
              // this.expression is another useful attribute with which you can assess which event has taken place
          }
      },
      

      if 子句似乎有点老套,但我找不到其他方法。至少这一切都有效。

      也许这对将来的某人有用。

      【讨论】: