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

时间:2015-04-25 09:17:49

标签: dart dart-polymer shadow-dom

我阅读了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>

问题:

  • 如何在Dart中实现此代码?
  • 阅读有关Dart Polymer使用的不同Q&amp; A的代码,我遇到了@observable注释,toObserve()函数和class CustomElement extends PolymerElement with Observable {..}。我知道他们以某种方式与数据绑定有关,但我不确切知道如何。

2 个答案:

答案 0 :(得分:3)

<强> 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 (您的my-component)

<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

import&#39;包装:polymer / polymer.dart&#39 ;;

@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。 PolymerElement包括Observable,因此在课程级别上没有什么特别的事情要做。扩展DOM元素时,看起来有点不同,请参阅https://stackoverflow.com/a/20383102/217408

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

答案 1 :(得分:1)

我找到了另一个适合我的解决方案:
只需为您的全局变量定义一个类。使用工厂构造函数,以便该类的每个表示形式都是同一个实例。该类必须使用Observable扩展Object:
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();

}

现在,您可以在所有自定义元素中使用此类。只需要导入globals.dart并创建它的对象:
inside: 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}}

这适用于我,它似乎是使用聚合物自定义元素的全局变量的最简单方法。