【发布时间】:2014-12-09 08:58:03
【问题描述】:
假设我想要两个视图(聚合物元素)共享一个模型。
在 Angular 中,模型将存在于注入到视图中的单例服务中,两个视图都从同一个源读取。
我尝试用 Polymer 模拟这种方法,因此我可以执行以下操作:
<polymer-element name="view1">
<template>
<my-model></my-model>
...
</template>
...
</polymer-element>
<polymer-element name="view2">
<template>
<my-model></my-model>
...
</template>
...
</polymer-element>
我喜欢这种方法,因为它是一种定义依赖项的声明方式,并且它与 <core-ajax> 和其他“开箱即用”的 Polymer 元素的工作原理基本相同。
通过这种方式,我需要等待domReady 生命周期回调,然后才能与模板中声明的任何元素进行交互,所以这就是我现在保存初始化逻辑的地方。问题是每个声明的<my-model> 元素都会调用一次此回调(因此在此示例中<my-model> 将被初始化两次,因为它同时出现在<view1> 和<view2> 中)。为了确保我的模型遵循单例模式,我必须将状态移动到元素实例之外,如下所示:
<polymer-element name="my-model">
<script>
(function(){
// private shared state
var instances = [], registered; // pattern variables
var foo; // state, model, whatever
// element init logic
Polymer('my-model', {
// Polymer callbacks
domReady: function(){
if (registered === (registered=true)) return;
// singleton init logic
foo = 'something';
// event handlers
this.addEventListener('foo', function(){ foo += 'baz'; });
},
attached: function() { instances.push(this); },
detached: function(){
instances = instances.filter(function(instance){
return instance !== this;
}.bind(this));
},
// element API
update: doSomething,
get state() { return foo; }
});
// private functions
function doSomething(){ foo += 'bar' }
})();
</script>
</polymer-element>
所以它有效,但对我来说看起来不对。使用<polymer-element> 通常与单例模式不兼容吗?我应该离开 Polymer 以获取模型和服务吗? Polymer 核心元素如何摆脱它?
[EDIT] 我在上面的初始化代码中添加了一些事件监听器。它们只在一个实例中注册,以避免侦听器在多个实例中多次触发。如果声明事件处理程序的实例被删除会发生什么?这不会破坏异步逻辑吗?
【问题讨论】:
-
这或多或少是我们推荐的模式,用于需要跨多个实例共享状态的元素。 polymer-project.org/docs/polymer/polymer.html#global
-
当事件侦听器在一个特定实例中注册并且该实例随后被删除时会发生什么?其他实例不会被切断吗?
标签: javascript angularjs design-patterns singleton polymer