代码之家  ›  专栏  ›  技术社区  ›  PhiLho

AngularJS:当为缺少的属性提供默认值时,如何避免非指定错误?

  •  0
  • PhiLho  · 技术社区  · 6 年前

    这是一个问题&回答这个问题,因为我在这个问题上有点挣扎,所以我希望跟踪它和它的解决方案。
    希望它能帮助某些人,也许其他人也能提供其他解决方案。

    我的情况是:我必须处理一个大型AngularJS 1.4.6项目(我将其命名为prj),它是用TypeScript编写的,定义了许多具有各种属性(prj aaa)的指令(prj ddd),其中一些是布尔值。
    他们通过字符串绑定实现了这些布尔属性: prjEnabled: "@" prjRequired: "@" .
    所以他们测试了如下值: if ($scope.prjEnabled === "false") ,或在模板中: <div ng-show="prjRequired === 'true'"> (是的,也没有使用controllerAs…)。
    这些属性是可选的:显然,在这里, prjEnabled 默认为 "true" prjRequired 默认为 "false" ,等等,因为测试是 false 当这些值 undefined .

    这是冗长的、不雅的(IMO),容易出错(大量原始字符串、隐式默认值),而且效率不高(尽管可能不是以可感知的方式)。

    所以我开始用表达式/双向绑定替换这些绑定: prjEnabled: "=" prjRequired: "=" .
    因此,当AngularJS看到 <prj-component prj-enabled="false"> ,它直接在指令的范围内提供布尔值。
    触感很好:有了这样的文字值,它不会创建绑定,因此不会影响性能。
    我必须应付缺席属性,所以我加入了 link 指令的功能类似于:

    if (scope.prjEnabled === undefined) {
        scope.prjEnabled = true;
    }
    

    用法变成: if (!$scope.prjEnabled) ,或在模板中: <div ng-show="prjRequired"> .

    到目前为止,一切顺利。但我们也有显式绑定: <prj-component prj-enabled="{{someScopeValue}}"> 甚至 <prj-component prj-enabled="{{foo.canEdit && bar.valid}}"> .
    因为我们有双向绑定,所以我将它们替换为: <prj-component prj-enabled="someScopeValue"> <prj-component prj-enabled="foo.canEdit && bar.valid"> .
    如果 someScopeValue 未定义 ,该指令将检测并提供默认值,该值将上升到父范围。恼人,但在大多数情况下,可能是无害的。实际值通常在以后提供(例如,在网络请求之后)。
    但有时,我在控制台中出现以下错误:

    https://code.angularjs.org/1.4.6/docs/error/$compile/nonassign?p0=foo.canEdit%20%26%26%20bar.valid&p1=prjComponent

    我遵循了相应页面中给出的建议,将绑定替换为 "=?" ,但我仍然有错误。

    理想情况下,我会将这些绑定替换为 "<?" ,避免了第一个问题(覆盖父级范围中的值)和第二个问题(不为表达式赋值)。
    但这需要AngularJS 1.5+,我无法在当前项目中升级该版本。

    那么我该如何解决这个问题呢?

    2 回复  |  直到 6 年前
        1
  •  0
  •   PhiLho    6 年前

    这很棘手,我不得不尝试各种各样的解决方案,直到我看到了曙光,并记住了这一点 "=?" 绑定时,有一种方法可以区分缺少的属性和具有 undefined 价值
    我重写了默认值赋值:
    if (!("prjEnabled" in scope)) { scope.prjEnabled = true; }
    如果你不熟悉 in 运算符,它大致相当于 scope.hasOwnProperty("prjEnabled") ,但它也会检查原型层次结构。我使用它主要是因为它比函数调用更好/更简洁。。。

    我制作了一个Plunkr应用程序(来自官方的AngularJS应用程序)来重现错误,查看错误发生的时间,并探索各种情况: http://plnkr.co/edit/Z2AIag?p=preview

    这表明 "=" 绑定并指定默认值如果未定义,则当属性为空(不太可能是这种情况)或AngularJS以静默方式捕获异常(此处为 wrong.scopeValue && wrong.unknown 哪里 $scope.wrong 不存在,导致ReferenceError异常)并提供 未定义 作为价值。
    具有 "=?" ,我们还有第二个问题(空属性值大小写不会抛出)。
    如果我们用 "x" is scope 方法,我们摆脱了这种恼人的情况,很常见的时候 wrong 是以后填充的变量(网络更新等)。 唯一仍然可能发生错误的情况是,如果我们为绑定属性赋值,并且只在 错误的 案例

        2
  •  0
  •   Community CDub    5 年前

    如何使用默认值手动创建单向绑定:

    app.directive("myDirective", function() {
        return {
            scope: {
                //oneWay: "<?"
            },
            link: postLink
        };
        function postLink (scope, elem, attrs) {
            if (!attrs.oneWay) {
                scope.oneWay = defaultValue;
            } else {
                scope.$watch(attrs.oneWay, function(value) {
                    scope.oneWay = value;
                });
            };
        }       
    })
    

    对于没有单向绑定的AngularJS(<1.5)版本,它可以通过观察者实现。

    推荐文章