【问题标题】:watch depth and content of complex object hierarchy in angular以角度观察复杂对象层次结构的深度和内容
【发布时间】:2016-11-02 22:59:26
【问题描述】:

我正在尝试编写一些代码来检测对复杂嵌套分层对象的更改。我希望 $watch$watchCollection 表达式就足够了,但事实证明这很难实现。

有人可以提出解决问题的好方法吗?

我要查看的数据结构的一个示例是(在 json 中):

{
    "$type":"<>f__AnonymousType7`2[[System.String, mscorlib],[System.Object, mscorlib]], VM.ConfigurationServer",
    "Name":"DevelopmentEnvironment",
    "Descendents":{
        "$type":"<>f__AnonymousType7`2[[System.String, mscorlib],[System.Object, mscorlib]][], VM.ConfigurationServer",
        "$values":[{
            "$type":"<>f__AnonymousType7`2[[System.String, mscorlib],[System.Object, mscorlib]], VM.ConfigurationServer",
            "Name":"MoreSpecificEnvironment",
            "Descendents":{
                "$type":"<>f__AnonymousType7`2[[System.String, mscorlib],[System.Object, mscorlib]][], VM.ConfigurationServer",
                "$values":[{
                    "$type":"<>f__AnonymousType7`2[[System.String, mscorlib],[System.Object, mscorlib]], VM.ConfigurationServer",
                    "Name":"level3",
                    "Descendents":null
                }]
            }
        }]
    }
}

如您所见,Json Serializer 的 TypeNameHandling 设置为 All,这对于系统的其他部分是必需的。

我需要注意的是对任何嵌套对象上的Name 属性的任何更改,以及添加或删除Descendent

我都试过了

scope.$watch(&lt;objectname&gt;, function(){...}, true);

scope.watchCollection(&lt;objectname&gt;, function(){...}, true);

两者都检测到顶级 NameDescendents 属性的更改,但没有检测到进一步嵌套的对象。

根据我的理解,这表明angular.equals 函数没有注意到顶层以下的变化。

有没有办法注入自定义相等比较器?

有没有办法动态更改watchExpression?因此对层次结构中的每个对象应用监视,并且随着层次结构的变化改变watchExpression

【问题讨论】:

    标签: javascript angularjs json


    【解决方案1】:

    问题在于 angular.equals() 忽略以 $ 符号开头的键,即在您的情况下,$type$values 在比较期间被忽略。

    不要在你的 Angular 代码中使用以 $ 符号开头的属性,除了 Angular 自己的服务/指令等!

    Check out this fiddle 并尝试将 $values 数组重命名为 values

    【讨论】:

    • 鉴于数据是由 webapi 服务器提供的,是否有一种简单的方法可以在数据到达时更改属性名称(并在将修改发布到服务器之前将其改回)
    • 非常感谢@michael-rose,这很有效,我添加了一项服务来根据一系列替换更改属性名称:请参阅我的“答案”(没有足够的空间发布服务作为评论)
    【解决方案2】:

    除了来自@michael-rose 的回答之外,我还添加了一个服务来转换来自 webapi 的接收数据:

    var DataClenseService = function () {
    "use strict";
    this.renameFields = function (data, fieldRenames) {
        if (data == null) {
            return null;
        }
    
        if (typeof data !== 'object') {
            return data;
        }
        var service = this;
        Object.keys(data).forEach(function (propertyName) {
            var matchingRenames = fieldRenames.filter(function (rename) { return rename.old === propertyName; });
            var currentValue = data[propertyName];
            if (matchingRenames.length == 1) {
                delete data[propertyName];
                data[matchingRenames[0].new] = service.renameFields(currentValue, fieldRenames);
            } else {
                data[propertyName] = service.renameFields(currentValue, fieldRenames);
            }
        });
        return data;
    };
    

    };

    然后简单地这样称呼它:

    var cleanedData = DataClenseService.renameFields(data, [{ old: '$values', new: 'values' }, { old: '$type', new: 'type' }]);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-30
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 2023-04-02
      • 2019-03-04
      相关资源
      最近更新 更多