Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Meteor:循环模板的模板级订阅或当所有订阅完成时_Javascript_Jquery_Meteor - Fatal编程技术网

Javascript Meteor:循环模板的模板级订阅或当所有订阅完成时

Javascript Meteor:循环模板的模板级订阅或当所有订阅完成时,javascript,jquery,meteor,Javascript,Jquery,Meteor,这就是我如何生成一篇包含介绍文本和元素列表的文章,这些元素嵌套在多层结构中。主要数据(标题、简介)由模板级订阅加载。加载数据时,将显示一个微调器。到目前为止,这是有效的 现在,我正在使用另一个模板加载一个嵌套列表,该模板将被循环以获取所有需要的数据。数据以带有父引用的模型树结构进行结构化。因此,对于每个循环,都会加载子循环并将其添加到列表中。这意味着如果列表深入三层,模板将被使用三次 我的问题是: 每个“循环”都会导致一个新的subscribe and find()请求获取该级别的元素。是否可以

这就是我如何生成一篇包含介绍文本和元素列表的文章,这些元素嵌套在多层结构中。主要数据(标题、简介)由模板级订阅加载。加载数据时,将显示一个微调器。到目前为止,这是有效的

现在,我正在使用另一个模板加载一个嵌套列表,该模板将被循环以获取所有需要的数据。数据以带有父引用的模型树结构进行结构化。因此,对于每个循环,都会加载子循环并将其添加到列表中。这意味着如果列表深入三层,模板将被使用三次

我的问题是:

  • 每个“循环”都会导致一个新的subscribe and find()请求获取该级别的元素。是否可以用另一种方法来防止多个find()-请求
  • 现在列表是按顺序加载的。但是我想显示一个微调器,直到加载完整的列表。但是我不能使用与主数据相同的模板级别订阅,因为模板将被循环多次
  • 因为我想在生成完整页面后使用一些函数,所以我需要在完成所有操作时获得点(=删除微调器)。例如,如果我想将
    autosize()
    添加到该列表中显示的所有文本区域中,那么如果我添加
    Template.elements.onRendered(function(){$('textarea').autosize();}),则它不起作用因为最后的元素不受影响。我不明白为什么
  • 模板

    <template name="article">
        {{#if Template.subscriptionsReady}}
    
            <h1>{{article.title}}</h1>
            <p>{{article.intro}}</p>
    
            {{ > elements article._id }}
    
        {{else}}
            <div class="loading">{{ > spinner }}</div>
        {{/if}}
    </template>
    
    <template name="elements">
        <ul>
        {{#each elements}}
            <li>
                <textarea>{{title}}</textarea>
                {{ > elements _id }}
            </li
        {{/each}}
        </ul>
    </template>
    
    Template.article.helpers({
        article: function() { return Template.instance().article(); }
    });
    
    Template.elements.helpers({
        children: function(parentId) {
            Meteor.subscribe('elements', parentId); 
            return Collection.find({ parent: parentId }, { sort: { order: 1 } });
        }
    });
    
    一旦创建

    Template.article.onCreated(function() {
        var instance = this;
    
        instance.autorun(function () {
            var subscription = instance.subscribe('article', Session.get('docId'));
        });
    
        instance.article = function() { return Collection.findOne({ _id: Session.get('docId') }); };
    
    });
    
    Template.elements.onRendered(function() {
        $('textarea').autosize();
    });
    
    onRendered

    Template.article.onCreated(function() {
        var instance = this;
    
        instance.autorun(function () {
            var subscription = instance.subscribe('article', Session.get('docId'));
        });
    
        instance.article = function() { return Collection.findOne({ _id: Session.get('docId') }); };
    
    });
    
    Template.elements.onRendered(function() {
        $('textarea').autosize();
    });
    
    以下是数据库中数据的结构:

    {
        "_id" : "YezvuyCowZdo2ZLgX",
        "title" : "Article title",
        "intro" : "Some text",
        "type" : "section",
    }
    {
        "_id" : "eYkxs8rW3dKH5SfoE",
        "title" : "element 1",
        "order" : 1,
        "type" : "element",
        "parent" : "YezvuyCowZdo2ZLgX"
    }
    {
        "_id" : "siaRPzaTgDrfWZ7kn",
        "title" : "subelement 1",
        "order" : 1,
        "type" : "element",
        "parent" : "ASkJZSkPAj8mhb7An"
    }
    {
        "_id" : "DrfWZ7knsiaRPzaTg",
        "title" : "subelement 2",
        "order" : 2,
        "type" : "element",
        "parent" : "ASkJZSkPAj8mhb7An"
    }
    {
        "_id" : "XZF9hpW8ZqTnRdkEg",
        "title" : "element 2",
        "order" : 3,
        "type" : "element",
        "parent" : "YezvuyCowZdo2ZLgX"
    }
    {
        "_id" : "ASkJZSkPAj8mhb7An",
        "title" : "group 1",
        "type" : "group",
        "parent" : "YezvuyCowZdo2ZLgX",
        "order" : 2
    }
    

    您可以在页面上的任何位置订阅出版物,因此可以在创建或呈现时将订阅放在父模板中

    您将
    article.\u id
    传递给您的子模板,然后在元素模板中使用该
    parentId

    您知道文章模板中的文章。\u id,因此您可以在创建或呈现时订阅该模板中的子模板数据

    如果这不是您正在做的,请澄清您的问题:在您的模板
    元素中
    是嵌套在
    文章中的模板


    如果您想要
    元素的完整列表
    ,可以订阅此列表,您将获得所有
    元素
    。然后集合已经加载,因此在
    文章
    模板中查找单个
    元素
    很便宜,因为它将仅在客户端上完成。

    好的,下表:

  • 每个“循环”都会导致一个新的subscribe and find()请求获取该级别的元素。是否可以用另一种方法来防止多个find()-请求
  • 对。我将对您的数据模式进行轻微修改,并在每个子文档中包含顶级父ID:

    {
        "_id" : "YezvuyCowZdo2ZLgX",
        "title" : "Article title",
        "intro" : "Some text",
        "type" : "section",
    }
    {
        "_id" : "eYkxs8rW3dKH5SfoE",
        "title" : "element 1",
        "order" : 1,
        "type" : "element",
        "immediateParent" : "YezvuyCowZdo2ZLgX",
        "topLevelParent": "YezvuyCowZdo2ZLgX"
    }
    {
        "_id" : "siaRPzaTgDrfWZ7kn",
        "title" : "subelement 1",
        "order" : 1,
        "type" : "element",
        "immediateParent" : "ASkJZSkPAj8mhb7An",
        "topLevelParent": "YezvuyCowZdo2ZLgX"
    }
    {
        "_id" : "DrfWZ7knsiaRPzaTg",
        "title" : "subelement 2",
        "order" : 2,
        "type" : "element",
        "immediateParent" : "ASkJZSkPAj8mhb7An",
        "topLevelParent": "YezvuyCowZdo2ZLgX"
    }
    {
        "_id" : "XZF9hpW8ZqTnRdkEg",
        "title" : "element 2",
        "order" : 3,
        "type" : "element",
        "immediateParent" : "YezvuyCowZdo2ZLgX",
        "topLevelParent": "YezvuyCowZdo2ZLgX"
    }
    {
        "_id" : "ASkJZSkPAj8mhb7An",
        "title" : "group 1",
        "type" : "group",
        "order" : 2,
        "immediateParent" : "YezvuyCowZdo2ZLgX",
        "topLevelParent": "YezvuyCowZdo2ZLgX"
    }
    
    现在,每个文档都可以访问其顶级父元素。您的发布功能将是:

    Meteor.publish( 'articles', function( articleId ) {
      return Collection.find({ $or: [ {_id: articleId }, { topLevelParent: articleId }] };
    });
    
    而您的文章onCreated函数将如下所示:

    Template.article.onCreated(function() {
        var instance = this;
    
        instance.autorun(function () {
            var subscription = instance.subscribe('articles', Session.get('docId'));
        });
        instance.article = function() { return Collection.findOne({ _id: Session.get('docId') }); };
    });
    
    您的模板将稍作修改:

    <template name="article">
        {{#if Template.subscriptionsReady}}
    
            <h1>{{article.title}}</h1>
            <p>{{article.intro}}</p>
    
            {{> elements articleId=article._id }}
    
        {{else}}
            <div class="loading">{{ > spinner }}</div>
        {{/if}}
    </template>
    
    <template name="elements">
        <ul>
        {{#each elements articleId}}
            <li>
                <textarea>{{title}}</textarea>
                {{> elements articleId=_id }}
            </li
        {{/each}}
        </ul>
    </template>
    
    现在,您应该可以在一个发布和订阅中获得所需的所有数据。你的第二个问题:

  • 现在列表是按顺序加载的。但是我想显示一个微调器,直到加载完整的列表。但是我不能使用与主数据相同的模板级别订阅,因为模板将被循环多次
  • 由于第一个Template.subscriptionsReady上提供了所有子模板的所有数据,我想您会发现这不再是一个问题

  • 因为我想在生成完整页面后使用一些函数,所以我需要在完成所有操作时获得点(=删除微调器)。例如,如果我想将autosize()添加到该列表中显示的所有textarea,那么如果我执行Template.elements.onRendered(函数(){$('textarea').autosize();}),它将不起作用;因为最后的元素不受影响。我不明白为什么
  • 这一个有点糟糕,因为元素正在动态加载到DOM中。丑陋,但我可能会修改您的订阅调用,以便在超时后执行自动调整大小:

    var subscription = instance.subscribe('articles', Session.get('docId'), function() {
      Meteor.setTimeout( function() { $('textarea').autosize(); }, 500); // Adjust down to a lower amount if possible.
    });
    

    希望能成功

    但是我不能这样做,因为我在循环之前不知道元素的ID。编辑我的答案。或者你应该编辑你的问题,因为在我的理解中,你可以这样做。如果你需要帮助,不要否决那些试图回答你问题的人。我在问题中添加了数据结构。所以我认为我不能得到所有元素的完整列表,因为它们只是由父元素引用的…所以,在“部分”部分中有父元素ID。因此,在父模板中,您可以订阅具有该父模板的所有“元素”。不知道你为什么说不行。你试过用两个集合来代替吗?您可以存储主集合ID并使用该ID查找子集合&show微调器,直到主文档的订阅准备就绪,然后它可以显示子文档的微调器,直到它们准备就绪。您将进行两次发布/订阅,但这两次将分开。我不知道这是不是你想要的…听起来很棒。如何获得一个小函数,将toplevelparent信息添加到现有数据中?我想我必须对每个元素做一个each循环,对吗?是的,你需要循环每个项目,然后迭代该项目的父项,直到找到顶级项目,然后设置它。