Meteor JS:为特定模板实例存储状态的最佳方法是什么?

时间:2014-01-05 22:14:29

标签: javascript meteor

我正在学习Meteor JS中的Session和被动数据源。它们非常适合设置全局UI状态。但是,我无法弄清楚如何将它们范围限定为模板的特定实例。

以下是我正在尝试做的事情

我在页面上有多个满足的元素。每个下面都是一个“编辑”按钮。当用户单击“编辑”按钮时,它应该关注元素并显示“保存”和“取消”按钮。

如果用户点击“取消”,则会消除所有更改,并且模板实例应使用原始内容重新呈现。

这是我到目前为止的代码

// Helper
Template.form.helpers({
  editState: function() {
    return Session.get("editState");
  }
});

// Rendered
Template.form.rendered = function(e){
  var $this = $(this.firstNode);
  var formField = this.find('.form-field');
  if (Session.get("editState")) formField.focus();
};

// Event map
Template.form.events({
  'click .edit-btn' : function (e, template) {
    e.preventDefault();
    Session.set("editState", "is-editing");
  },

  'click .cancel-btn' : function (e, template) {
    e.preventDefault();
    Session.set("editState", null);
  },
});

// Template
<template name="form">
  <div class="{{editState}}">
    <p class="form-field" contenteditable>
      {{descriptionText}}
    </p>
  </div>
  <a href="#" class="edit-btn">Edit</a>
  <a href="#" class="save-btn">Save</a>
  <a href="#" class="cancel-btn">Cancel</a>
</template>


// CSS
.edit-btn
.cancel-btn,
.save-btn {
  display: inline-block;
}

.cancel-btn,
.save-btn {
  display: none;
}

.is-editing .cancel-btn,
.is-editing .save-btn  {
  display: inline-block;
}

问题

如果我有Form个模板的多个实例,那么.form-field会针对每个模板进行关注,而不仅仅是正在编辑的模板。我如何制作,只有被编辑的人才会聚焦?

2 个答案:

答案 0 :(得分:2)

您可以使用data呈现模板,该模板基本上只是插入页面时传递给它的对象。

数据可能只是Session editState中使用的关键。

例如,使用Template.form({editStateKey:'editState-topForm'})

渲染模板

你可以制作一个把手帮手,例如,

Handlebars.registerHelper('formWithOptions', 
  function(editStateKey){
    return Template.form({editStateKey:editStateKey})
});

然后使用

将其插入模板中

{{{formWithOptions 'editState-topForm'}}}(请注意三联{}

接下来,将引用从Session.x('editState')更改为Session.x(this.editStateKey) / Session.x(this.data.editStateKey)

Template.form.helpers({
  editState: function() {
    return Session.get(this.editStateKey);
  }
});

// Rendered
Template.form.rendered = function(e){
  var $this = $(this.firstNode);
  var formField = this.find('.form-field');
  if (Session.get(this.data.editStateKey)) formField.focus();
};

// Event map
Template.form.events({
  'click .edit-btn' : function (e, template) {
    e.preventDefault();
    Session.set(this.editStateKey, "is-editing");
  },

  'click .cancel-btn' : function (e, template) {
    e.preventDefault();
    Session.set(this.editStateKey, null);
  },
});

注意:如果您使用的是iron-router,则还有其他API可以将data传递给模板。

注2:在meteor 1.0中,应该有更好的支持来编写自己的小部件。这应该可以更好地控制这类事情。

答案 1 :(得分:1)

作为一项政策问题,我几乎在所有情况下都避免使用Session。我觉得,随着应用程序的增长,他们的全球范围会导致不良习惯和缺乏关于问题分离的良好纪律。另外,由于它们的全局范围,Session在渲染模板的多个实例时会导致麻烦。出于这些原因,我觉得其他方法更具可扩展性。

替代方法

1 addClass / removeClass

您可以直接执行所需的操作,而不是设置状态然后在其他地方对其做出反应。这里的类根据需要显示和隐藏块:

'click .js-edit-action': function(event, t) {
    var $this = $(event.currentTarget),
    container = $this.parents('.phenom-comment');

    // open and focus
    container.addClass('editing');
    container.find('textarea').focus();
},

'click .js-confirm-delete-action': function(event, t) {
      CardComments.remove(this._id);
},

2 ReactiveVar作用于模板实例

if (Meteor.isClient) {  
  Template.hello.created = function () {
  // counter starts at 0
  this.counter = new ReactiveVar(0);
};

Template.hello.helpers({
  counter: function () {
  return Template.instance().counter.get();
  }
});

Template.hello.events({
  'click button': function (event, template) {
    // increment the counter when button is clicked
    template.counter.set(template.counter.get() + 1);
  }
});
}

http://meteorcapture.com/a-look-at-local-template-state/

3 Iron-Router的状态变量

获取

Router.route('/posts/:_id', {name: 'post'});

PostController = RouteController.extend({
  action: function () {
    // set the reactive state variable "postId" with a value
    // of the id from our url
    this.state.set('postId', this.params._id);
    this.render();
  }
});

Template.Post.helpers({
  postId: function () {
    var controller = Iron.controller();

    // reactively return the value of postId
    return controller.state.get('postId');
  }
});

https://github.com/iron-meteor/iron-router/blob/devel/Guide.md#setting-reactive-state-variables

4收集数据

另一种方法是通过更新集合中的数据来简单说明。有时这很有道理。

5更新数据上下文

在我看来,会话通常是更糟糕的选择。此外,我个人并不使用#3,因为我觉得与铁路的关系更少 - 路由器更好,因为我们想要切换到另一个路由器包,例如“Flow”。