【问题标题】:MV* in Polymer, models and services as polymer-elements?MV* 在聚合物、模型和服务中作为聚合物元素?
【发布时间】: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>

我喜欢这种方法,因为它是一种定义依赖项的声明方式,并且它与 &lt;core-ajax&gt; 和其他“开箱即用”的 Polymer 元素的工作原理基本相同。

通过这种方式,我需要等待domReady 生命周期回调,然后才能与模板中声明的任何元素进行交互,所以这就是我现在保存初始化逻辑的地方。问题是每个声明的&lt;my-model&gt; 元素都会调用一次此回调(因此在此示例中&lt;my-model&gt; 将被初始化两次,因为它同时出现在&lt;view1&gt;&lt;view2&gt; 中)。为了确保我的模型遵循单例模式,我必须将状态移动到元素实例之外,如下所示:

 <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>

所以它有效,但对我来说看起来不对。使用&lt;polymer-element&gt; 通常与单例模式不兼容吗?我应该离开 Polymer 以获取模型和服务吗? Polymer 核心元素如何摆脱它?

[EDIT] 我在上面的初始化代码中添加了一些事件监听器。它们只在一个实例中注册,以避免侦听器在多个实例中多次触发。如果声明事件处理程序的实例被删除会发生什么?这不会破坏异步逻辑吗?

【问题讨论】:

  • 这或多或少是我们推荐的模式,用于需要跨多个实例共享状态的元素。 polymer-project.org/docs/polymer/polymer.html#global
  • 当事件侦听器在一个特定实例中注册并且该实例随后被删除时会发生什么?其他实例不会被切断吗?

标签: javascript angularjs design-patterns singleton polymer


【解决方案1】:

我会这样:
在主页上定义您的模型并从您的视图中调用它。

如果它被删除,您可以:
1 - 监听“分离的”生命周期回调并在其中强制注册它或
2 - 将内容存储在更高级别对象中的原型构建中,并以您最喜欢的方式访问它。
3 - 如果一切都失败了,(我不确定它会不会,但我想因为我还没有使用这种实现,到目前为止我与 php 交谈并传递我需要持久的对象)你可以使用“prepareForRemoval”,知道您将离开实例,本地存储您的东西并执行第 1 项,然后“recoverFromRemoval”如果您知道我所说的骆驼外壳原型建议是什么意思

反正我不是很喜欢单身。 Polymer 是强大的前端工具,但我不确定它是否是最好的方法。

在 API 文档中,他们没有提到切断它的可能性 (as you can see) 但老实说,我认为你是对的,你会失去你的东西。
这只是我的 2 美分实际上只是我此时想出的一个不雅的解决方案,也许@ebidel、@DocDude 或 @dodson 可以在这方面帮助我们,但你不能在这里标记他们所以我会为我们在 G+ 上标记他们,你先生让我很感兴趣。
顺便说一句,你为什么要离开你的主页?在聚合物中没有意义,您应该动态更改内容而不是摆脱它。使用场景是什么?


ps.:抱歉,我讨厌专有名词大写。克服它

编辑(不适合 cmets):

我表达错了。无论如何,我强烈认为我不明白你想要什么。
好吧,如果我这次做对了,是的,它会触发多次(他们应该如此),但是一旦删除了特定视图,它就不应该将其他人排除在外。

至于您的初始化逻辑,我将着手向窗口或文档添加一个侦听器(我认为窗口更可取)本身等待“聚合物就绪”事件。

“为了确保我的模型遵循单例模式,我必须 将状态移到元素实例之外”

是的,没错。但不要等待它的原型中的 domready,而是使用构造或类似构造并将其称为上述事件侦听器的回调。当我回到家时,我会编辑我的答案以使其更清楚(如果不是,请告诉我)。
我希望你明白我的意思。

如果你不这样做,我很快就会回来。

【讨论】:

  • 我并没有离开我的主页,我所说的视图是指聚合物元素。这些元素通常共存于主页中,其中一些可能是隐藏的,但仅此而已。至于直接在主页中定义模型,这将创建循环依赖,因为主页需要导入视图,而视图需要导入主页作为回报。否则如何从视图中获取模型的句柄?
  • 编辑了我的答案,因为它不适合评论。让我知道你是否得到了我所做的
【解决方案2】:

在浏览器中,window == 定义为单例对象。 简单使用:

var window.instances = []; 
var window.registered;
var window.foo;

改为。

另一种方法是使用 Polymer core-meta 元素:

  <core-meta id="x-foo" label="foo"></core-meta>
  <core-meta id="x-bar" label="bar"></core-meta>
  <core-meta id="x-zot" label="zot"></core-meta>

  <core-meta id="apple" label="apple" type="fruit"></core-meta>
  <core-meta id="orange" label="orange" type="fruit"></core-meta>
  <core-meta id="grape" label="grape" type="fruit"></core-meta>

  <h2>meta-data</h2>

  <template id="default" repeat="{{metadata}}">
    <div>{{label}}</div>
  </template>

  <h2>meta-data (type: fruit)</h2>

  <template id="fruit" repeat="{{metadata}}">
    <div>{{label}}</div>
  </template>

  <script>

    document.addEventListener('polymer-ready', function() {
      var meta = document.createElement('core-meta');
      document.querySelector('template#default').model = {
        metadata: meta.list
      };

      var fruitMeta = document.createElement('core-meta');
      fruitMeta.type = 'fruit';
      document.querySelector('template#fruit').model = {
        metadata: fruitMeta.list
      };
    });

  </script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多