Polymer Dart、全局变量和数据绑定(可观察)

Polymer Dart, global variables and data bindings (observable)

我阅读了 Polymer API 开发人员指南,但不幸的是,它只有针对 JavaScript 开发人员的示例。我尝试将一些示例移植到 Dart 中,但在这种情况下我失败了。请转至 https://www.polymer-project.org/0.5/docs/polymer/polymer.html#global(第 支持全局变量 部分)。这是文档中的一个片段:

elements.html

<polymer-element name="app-globals">
  <script>
    (function() {
      var values = {};

      Polymer({
       ready: function() {
         this.values = values;
         for (var i = 0; i < this.attributes.length; ++i) {
           var attr = this.attributes[i];
           values[attr.nodeName] = attr.value;
         }
       }
      });
    })();
  </script>
</polymer-element>

<polymer-element name="my-component">
  <template>
    <app-globals id="globals"></app-globals>
    <div id="firstname">{{$.globals.values.firstName}}</div>
    <div id="lastname">{{$.globals.values.lastName}}</div>
  </template>
  <script>
    Polymer({
      ready: function() {
        console.log('Last name: ' + this.$.globals.values.lastName);
      }
    });
  </script>
</polymer-element>

index.html

<app-globals id="globals" firstname="Addy" lastname="Osmani"></app-globals>

问题:

app_gobals.html

<link rel="import" href="packages/polymer/polymer.html">

<polymer-element name="app-globals">
  <template>
    <style>
      :host {
        display: none;
      }
    </style>
  </template>
  <script type="application/dart" src="app_globals.dart"></script>
</polymer-element>

app_gobals.dart

import 'package:polymer/polymer.dart';
import 'dart:async' show Timer;

@CustomTag('app-globals')
class AppGlobals extends PolymerElement {
  static final ObservableMap _staticValues = toObservable({});

  Map get values => _staticValues;

  AppGlobals.created() : super.created();

  ready() {
    attributes.keys.forEach((k) {
      values[k] = attributes[k];
    });

    // just to demonstrate that value changes are reflected
    // in the view
    new Timer.periodic(new Duration(seconds: 2),
        (_) => values['periodic'] = new DateTime.now());
  }
}

app_element.html(你的组件)

<link rel="import" href="packages/polymer/polymer.html">
<link rel="import" href="app_globals.html">
<polymer-element name="app-element">
  <template>
    <style>
      :host {
        display: block;
      }
    </style>
    <app-globals id="globals"></app-globals>
    <div>{{$["globals"].values["firstname"]}}</div>
    <div>{{$["globals"].values["lastname"]}}</div>
    <div>{{$["globals"].values["periodic"]}}</div>
  </template>
  <script type="application/dart" src="app_element.dart"></script>
</polymer-element>

app_element.dart

导入'package:polymer/polymer.dart';

@CustomTag('app-element')
class AppElement extends PolymerElement {
  AppElement.created() : super.created();

  ready() {
    print('Last name: ${$["globals"].values["lastName"]}');
  }
}

@observable 表示当值更改时应通知 Polymer,以便它可以更新视图。 如果您有一个集合,这还不够,因为 Polymer 只会在字段更改时收到通知(另一个集合或 null 已分配)。 toObservable(list|map) 确保 Polymer 在集合中的元素发生更改时得到通知 (removed/added/replaced)。 PolymerElement 包括 Observable 因此在 class 级别上没有什么特别的事情要做。当您扩展 DOM 元素时,这看起来有点不同,请参阅 .

更新
这是很多问题。我使用 static final ObservableMap _staticValues = toObservable({}); 来确保所有值都存储在一个地方,无论您的应用程序包含多少 <app-globals> 元素。静态存储在 class 而不是实例中,因此存在多少个实例并不重要。 @ComputedProperty(expression) var someField; 监视 expression 的值更改并通知 Polymer 更新绑定到 someField@observable 是更简单的版本,但仅适用于字段。 @published 类似于 @observable 但另外允许从元素外部绑定到字段。 @PublishedProperty()@published 相同,但此注释形式允许传递参数。 @PublishedProperty(reflect: true) 类似于 @published 但另外更新了实际的 DOM 属性以使绑定值不仅可用于其他要绑定的 Polymer 元素,而且可用于 CSS 或其他框架不知道如何绑定到 Polymer 字段。

我找到了另一个适合我的解决方案:
只需为您的全局变量定义一个 class。使用工厂构造函数,以便 class 的每个表示都是相同的实例。 class 必须使用 Observable 扩展对象:
globals.dart:

library globals;
import 'package:polymer/polymer.dart';

class Globals extends Object with Observable {

  static Globals oneAndOnlyInstance;
  @observable String text; // a "global" variable
  @observable int integer; // another "global" variable

  factory Globals() {
    if (oneAndOnlyInstance==null) {
      oneAndOnlyInstance=new Globals.init();
    } 
    return oneAndOnlyInstance;    
  }

  Globals.init();

}

现在您可以在所有自定义元素中使用此 class。只需要导入globals.dart并创建它的一个对象:
里面:main_app.dart:

import 'dart:html';

import 'package:polymer/polymer.dart';   
import 'package:abundan/classes/globals.dart';

/// A Polymer `<main-app>` element.
@CustomTag('main-app')
class MainApp extends PolymerElement {      
  Globals globals=new Globals();    

  /// Constructor used to create instance of MainApp.
  MainApp.created() : super.created();

attached() {
  super.attached();
  globals.text="HELLO!";
}

main_app.html内部:

{{globals.text}}

这对我有用,而且它似乎是使用聚合物自定义元素实现类似全局变量的最简单方法。