12

一般问题:在 Meteor 中,实现在模型更新时触发的业务逻辑的最佳方式是什么——例如,用于更新依赖字段或验证或......

具体示例:我想在Meteor todos 示例中的 Lists 集合中添加一个“slug”字段。每当列表的名称更改时,slug 需要自动更新。

这就是我所拥有的......我正在观察列表的每一个变化,看看是否需要创建/更新它的 slug。这是在共享的models.js 中(运行服务器和客户端,以获得延迟补偿的好处):

// Lists -- {name: String}
Lists = new Meteor.Collection("lists");

var listsObserver = Lists.find().observe({
    added: updateSlug,
    changed: updateSlug
});

function updateSlug(doc, idx) {
    var slug = (doc.name || '').replace(/\W+/g, '-').toLowerCase();
    if (slug !== doc.slug) {
        console.log("Updating slug for '" + doc.name + "' to " + slug);
        Lists.update(doc._id, {$set: {slug: slug}});
    }
}

(就像在原始的 todos 示例中一样,server/publish.js 将所有内容发布Lists.find()为“列表”,而 client/todos.js 订阅该集合。)

上面的代码似乎可以工作,但对我来说似乎不太合适。问题:

  1. 像这样观察 Lists 集合是一种合理的方法吗?看起来它可能效率低下——对 Lists 文档的任何更改都会触发此代码。
  2. 我应该在客户端进行不同的(模拟的)更新,还是让相同的 Mongo/Minimongo 更新在两者上运行?
  3. 我是否需要listsObserver.stop()在某个时候打电话来处置观察者?如果是这样,什么时候?

(我刚刚开始使用 Meteor,所以也许我对其他环境的偏见正在泄漏。这里隐含的元问题是,我是否以正确的方式思考这个问题?)

4

3 回答 3

12

我建议使用 Collection-Hooks 包。它使用 before 和 after 钩子扩展了收集操作。这比拥有大量的 collection Observes 或 ObserveChanges 要好,尤其是在收集观察的开销会变得非常大的服务器上。

这适用于客户端和服务器。如果您在客户端上实现它,您将获得更新本地集合(延迟补偿)的好处,并且更改将被推送到服务器,因此无需再次执行此操作。

您还可以获得只执行一个 MongoDB 操作而不是像使用观察或观察更改那样执行两个或更多操作的好处。

你可以像这样使用它:

var beforeInsertSlug = function(userId, doc) {
    var slug = (doc.name || '').replace(/\W+/g, '-').toLowerCase();
    if (slug !== doc.slug) {
        console.log("Updating slug for '" + doc.name + "' to " + slug);
        doc.slug = slug;
    }
};

var beforeUpdateSlug = function(userId, doc, fieldNames, modifier, options){
    if(modifier && modifier.$set && modifier.$set.doc && _.isString(modifier.$set.doc.name)){
        var slug = (modifier.$set.doc.name || '').replace(/\W+/g, '-').toLowerCase();
        if (slug !== doc.slug) {
            console.log("Updating slug for '" + modifier.$set.doc.name + "' to " + slug);
            modifier.$set.doc.slug = slug;
        }
    }

};

Lists.before.insert(beforeInsertSlug);

Lists.before.update(beforeUpdateSlug);

你可以在这里找到包:https ://atmospherejs.com/matb33/collection-hooks

于 2014-01-23T06:33:43.017 回答
1

我在服务器代码中做了类似的事情。基本上将此代码与您想要对 Lists 集合进行的任何其他检查和更新一起放在 Meteor.methods() 中。

虽然下面的代码看起来有点凌乱,而且以 var slug 开头的行肯定很难理解:

Meteor.methods({
   myupdate: function (doc) {

     var slug = (doc.name || '').replace(/\W+/g, '-').toLowerCase();

     if (slug !== doc.slug) {
        console.log("Updating slug for '" + doc.name + "' to " + slug);
        Lists.update(doc._id, {$set: {slug: slug}});
     }
   }
});
于 2013-12-19T18:02:33.743 回答
0

实现这一点的一种方法是定义自定义模板函数并在正在更改的模板中触发它。例如:

在 client.js 中

Template.myTemplate.custom_function_to_update = function() {
    // do my update code.  i.e. MyCollections.Update(...);
}

在带有模板的 html 文件中

<template name="myTemplate">
    <!-- Normal template code -->
    {{ custom_function_to_update }}
</template>

每次模板“myTemplate”更新时,它都会调用你的方法。

于 2012-09-21T21:14:21.700 回答