【问题标题】:Subscribing to changes in a Collection but not in a template订阅集合中的更改但不在模板中
【发布时间】:2012-04-29 09:00:48
【问题描述】:

我对流星很陌生,如果我在这里遗漏了一些非常基本的东西,请道歉。

我认为创建一个非常简单的文本板样式应用程序来检查流星会很有趣。我使用了 todo 应用程序并将数据结构更改为“文件夹”和“文档”而不是“列表”和“待办事项”,所以我有一个文件夹列表,当你点击文件夹时,你会得到一个文档列表在那个文件夹中。

然后,我添加了一些代码以在单击列表中的一个文档时显示单个“文档”的“内容”属性。

我正在使用 ace 为文档 (https://github.com/ajaxorg/ace) 的内容添加一些漂亮的打印。我已经设置了 ace 来处理包含我的文档的纯文本版本的隐藏文本区域,并且编辑器对象获取此文本并漂亮地打印它。

ace 的问题是我不希望每次 doc 的内容更改时都替换包含 ace 编辑器的模板(因为重新初始化需要半秒钟,这是一个糟糕的体验打字!)。相反,我想更新 textarea 模板,然后使用 ace API 告诉编辑器根据 textarea 中的内容更新其输入。

现在,这可能是解决问题的错误方法,但我最终使用了两个模板。第一个包含一个包含 doc.contents 的 textarea,它对底层模型是反应性的:

<template name="doc_content">
  <textarea name="editor">{{content}}</textarea>
</template>

第二个包含 ace 用来显示漂亮打印文本的“编辑器”div。

<template name="doc_init">
  <div id="editor"></div>
</template> 

这个想法是第一个模板将在每次用户键入时更新(在所有客户端上),第二个模板只会在我们加载的每个新文档时重新加载。

Template.doc_content.content = function() {
  var doc_id = Session.get('viewing_itemname');
  if (!doc_id) {
    return {}; 
  }

  var doc = Docs.findOne({_id:doc_id});
  if (doc && doc.content) {
    // #1 Later
    var editor = Session.get('editor');
    if (editor) {
      editor.getSession().setValue(doc.content);
    }   

    return doc.content;
  } else {
    return ''; 
  }
};

当您在编辑器 div 中输入文本时,我会调用 Docs.update(doc_id, {$set: {content: text}});,它会更新每个客户端上 textarea 中的值。到目前为止一切顺利。

editor.getSession().on('change', function(){
    var text = editor.getSession().getValue();
    Docs.update(doc_id, {$set: {content: text}});
});

对于除进行更改的客户端之外的所有客户端,我想要做的是订阅该文档的更改并使用刚刚更改的文本调用 editor.getSession().setContent(),从 textarea 中获取文本并使用它来填充编辑器。

我尝试通过从包含 textarea 的模板进行调用来做到这一点(因为每当更新文档时它都会改变 - 参见上面的 #1)。但是,这会使客户端陷入无限循环,因为更改编辑器中的值会导致再次调用 Docs.update

显然,当您渲染模板时不会发生这种情况,所以我假设流星中有一些魔法可以防止这种情况发生,但我不确定如何。

有什么想法吗?

TIA!

【问题讨论】:

    标签: meteor


    【解决方案1】:

    你的问题有很多要吸收的东西,但如果我理解正确,你可能只是在Deps.autorun之后:

    Deps.autorun(function () {
        var doc_id = Session.get('viewing_itemname');
        if (!doc_id) {
            return {};
        }
    
        var doc = Docs.findOne({_id:doc_id});
    
        // do stuff with doc
    });
    

    Deps.autorun 真的很有用,如果它的任何一个它都会重新运行 依赖改变。这些依赖关系仅限于那些“反应性”的 例如 Collections 和 Sessions,或者任何实现响应式 API 的东西。

    在您的情况下,Session.getfindOne 都是反应式的,因此如果它们的值 完全改变,Deps.autorun 将再次运行该函数。

    【讨论】:

    • Meteor.autorun 更适合我上面给出的例子
    • 现在是 Deps.autorun
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    • 1970-01-01
    • 2013-08-01
    • 1970-01-01
    • 2021-01-14
    • 2016-11-25
    • 2016-02-25
    相关资源
    最近更新 更多