Javascript Vue JS 观看深层嵌套对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30124538/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Vue JS Watching deep nested object
提问by Hendrik
Disclaimer:This is my first attempt at building an MVVM app I have also not worked with vue.js before, so it could well be that my issue is a result of a more fundamental problem.
免责声明:这是我第一次尝试构建一个 MVVM 应用程序,我之前也没有使用过 vue.js,所以很可能我的问题是一个更基本的问题的结果。
In my view I have two types of blocks with checkboxes:
在我看来,我有两种带有复选框的块:
- Type 1: block/checkboxes
- Type 2: block/headers/checkboxes
- 类型 1:块/复选框
- 类型 2:块/标题/复选框
The underlying object is structured like this:
底层对象的结构如下:
{
"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
}
]
}
]
}
]
}
My objectives
我的目标
Selecting checkboxes:
选择复选框:
- User clicks on checkbox, checkbox is selected (selected=true)
- A method is fired to check if any other checkboxes need to be disabled (disabled=true). (If this method has indeed disabled anything, it also calls itself again, because other items could be in turn dependent on the disabled item)
- Another method updates some other things, like icons etc
- 用户点击复选框,复选框被选中(selected=true)
- 会触发一个方法来检查是否需要禁用任何其他复选框(禁用 = 真)。(如果这个方法确实禁用了任何东西,它也会再次调用自己,因为其他项目可能反过来依赖于禁用的项目)
- 另一种方法更新其他一些东西,比如图标等
Clearing checkboxes
清除复选框
A user can click on a "clear" button, which unchecks all checkboxes in a list (selected=false). This action should also trigger the methods that optionally disables checkboxes and updates icons etc.
用户可以单击“清除”按钮,取消选中列表中的所有复选框(selected=false)。此操作还应触发可选地禁用复选框和更新图标等的方法。
My current method(which doesn't seem quite right)
我目前的方法(似乎不太正确)
- The selected attribute of the data-model is bound to the checked
state of the checkbox element via the
v-modeldirective. - The disabled attribute (from the model) is bound to the element's class and disabled attribute. This state is set by the aforementioned method.
- To initialize the methods that disable checkboxes and change some icons, I am using a
v-on="change: checkboxChange(this)"directive. I think I need to do this part differently - The clearList method is called via
v-on="click: clearList(this)"
- 数据模型的 selected 属性通过
v-model指令绑定到复选框元素的选中状态。 - disabled 属性(来自模型)绑定到元素的 class 和 disabled 属性。该状态通过上述方法设置。
- 为了初始化禁用复选框和更改某些图标的方法,我使用了一个
v-on="change: checkboxChange(this)"指令。 我想我需要以不同的方式做这部分 - clearList 方法通过调用
v-on="click: clearList(this)"
The problems with my current setup is that the change event is not firing when the checkboxes are cleared programatically (i.e. not by user interaction).
我当前设置的问题是当以编程方式清除复选框时(即不是通过用户交互),更改事件不会触发。
What I would like instead
To me the most logical thing to do would be to use this.$watchand keep track of changes in the model, instead of listening for DOM events.
我想要的是
对我来说最合乎逻辑的事情是使用this.$watch并跟踪模型中的更改,而不是监听 DOM 事件。
Once there is a change I would then need to identify which exact item changed, and act on that. I have tried to create a $watchfunction that observes the blocksarray. This seems to pick up on the changes fine, but it is returning the full object, as opposed to the individual attribute that has changed. Also this object lacks some convenient helper attributes, like $parent.
一旦发生变化,我就需要确定哪个确切的项目发生了变化,然后采取行动。我试图创建一个$watch观察blocks数组的函数。这似乎很好地接受了更改,但它返回了完整的对象,而不是已更改的单个属性。这个对象也缺少一些方便的辅助属性,比如$parent.
I can think of some hacky ways to make the app work (like manually firing change events in my clearList method, etc.) but my use case seems pretty standard, so I expect there is probably a much more elegant way to handle this.
我可以想到一些使应用程序正常工作的hacky方法(例如在我的 clearList 方法中手动触发更改事件等),但我的用例似乎很标准,所以我希望可能有一种更优雅的方法来处理这个问题。
回答by webkit
You could use the 'watch' method.. for example if your data is:
您可以使用 'watch' 方法.. 例如,如果您的数据是:
data: {
block: {
checkbox: {
active:false
},
someotherprop: {
changeme: 0
}
}
}
You could do something like this:
你可以这样做:
data: {...},
watch: {
'block.checkbox.active': function() {
// checkbox active state has changed
this.block.someotherprop.changeme = 5;
}
}
回答by peerbolte
If you want to watch the object as a whole with all its properties, and not only just one property, you can do this instead:
如果您想查看整个对象及其所有属性,而不仅仅是一个属性,您可以这样做:
data() {
return {
object: {
prop1: "a",
prop2: "b",
}
}
},
watch: {
object: {
handler(newVal, oldVal) {
// do something with the object
},
deep: true,
},
},
notice handlerand deep: true
通知handler和deep: true
回答by Graham Slick
Other solution not mentioned here:
Use the deepoption.
此处未提及的其他解决方案:使用该deep选项。
watch:{
block: {
handler: function () {console.log("changed") },
deep: true
}
}
回答by Hendrik
Since nobody replied and I have solved/ worked around the issue by now, I thought it migth be useful to post my solution. Please note that I am not sure my solution is how these types of things should be tackled, it works though.
由于没有人回复并且我现在已经解决/解决了这个问题,我认为发布我的解决方案可能很有用。请注意,我不确定我的解决方案是如何解决这些类型的事情,但它确实有效。
Instead of using this event listener v-on="change: checkboxChange(this)"I am now using a custom directive which listens to both the selected and disabled model attribute, like this: v-on-filter-change="selected, disabled".
如果不使用此事件侦听器,v-on="change: checkboxChange(this)"我现在用的,它会监听两个选择并禁用模型属性,像这样的自定义指令:v-on-filter-change="selected, disabled"。
The directive looks like this:
该指令如下所示:
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
}
},
The if clause seems a bit hacky, but I couldn't find another way. At least it all works.
if 子句似乎有点 hacky,但我找不到其他方法。至少这一切都有效。
Perhaps this will be useful to someone in the future.
也许这对将来的某人有用。

