为啥 Zone.js 会改变 AngularJS 评估属性的方式?

Posted

技术标签:

【中文标题】为啥 Zone.js 会改变 AngularJS 评估属性的方式?【英文标题】:Why is Zone.js changing how AngularJS evaluates attributes?为什么 Zone.js 会改变 AngularJS 评估属性的方式? 【发布时间】:2019-01-21 07:22:49 【问题描述】:

我有一个包含 Angular (2+) 和 AngularJS (1.x) 的应用程序。我们正在使用第三方 AngularJS 库,它在链接函数中从其 attrs 数组中读取对象,如下所示:

//3rd party lib code:
module.directive('test', () => (
  template: `Look at the console`,
  link(elt, scope, attrs) 
    console.log('link attrs.props', attrs.props);
  
)) 

模板:

<!-- someObject = name: 'foo' -->
<test props="someObject"></test>

我们刚刚升级到最新版本的 AngularJS,我们发现了一个问题。通常, attrs.props 评估为对象的字符串表示形式。我们没有得到一个字符串化的对象,而是得到“[object Object]”

我尝试了最小的复制,但我无法复制问题,直到我尝试导入 Zone.js,正如您在这个 stackblitz 上看到的那样: https://stackblitz.com/edit/angularjs-attrs-test?file=app.js

如果 Zone.js 被导入(Angular 2+ 需要它),那么attrs.props 就是"[object Object]"。没有它,attrs.props 就是 name: 'foo'

这是一个已知问题吗?有解决办法吗?

【问题讨论】:

【参考方案1】:

最好总是先加载 ZoneJS,否则可能会发生一些奇怪的问题。在你的例子中,如果你简单地将 ZoneJS 导入移动到第一行,它就解决了问题。

【讨论】:

【参考方案2】:

ZoneJS 覆盖 Object.prototype.toString 方法,这会导致 AngularJS stringify 函数出现意外行为:

function stringify(value) 
  if (value == null)  // null || undefined
    return '';
  
  switch (typeof value) 
    case 'string':
      break;
    case 'number':
      value = '' + value;
      break;
    default:
      if (hasCustomToString(value) && !isArray(value) && !isDate(value)) 
                     \/
                    true
        value = value.toString(); // will be called since zone js overrided this method
       else 
        value = toJson(value); // will be called without zonejs
      
  

  return value;

为了解决这个问题,您可以禁用此补丁:

window.__Zone_disable_toString = false; 
import 'zone.js/dist/zone';

Forked Stackblitz

【讨论】:

以上是关于为啥 Zone.js 会改变 AngularJS 评估属性的方式?的主要内容,如果未能解决你的问题,请参考以下文章

为啥输入不改变颜色?

Angular中的变更检测

AngularJS:为啥即使显示正确,我也会得到 NaN?

为啥我在 AngularJS 中的日期输入字段会抛出类型错误?

将BootstrapJS和AngularJS结合使用以及为啥不用jQuery

angular2 zone.js 进行自动 sock.js 调用