arrays - 本地数组更改时如何重新渲染 meteor blaze 模板?

标签 arrays templates meteor reactive-programming meteor-blaze

在过去 2 年多的时间里,我大量使用 AngularJS,现在开始使用 MeteorJS 1.2,blaze 模板层的某些方面对我来说感觉很不直观,但可能有一个简单的解决方案。

我想要一个包含以下字段的“创建投票”表单:

  • 问题,文本字段
  • 投票选项,文本字段
  • 添加选项、按钮
  • 选项列表,<li> 的转发器s 基于本地 options数组
  • 列表项有一个删除按钮

本质上,我希望能够填充投票选项字段,单击“添加选项”,并以只读方式(纯文本)在投票选项文本字段下方的列表转发器中呈现此选项。

我目前的问题是,如果不使用 ReactiveArray 之类的东西,当我将项目推送到本地数组变量 options 中时,blaze 模板不会重新呈现。 .

解决这个问题的正确方法是什么?

代码如下:

poll.create.html模板:

<template name="pollCreate">
    <form class="form form--create">
        <section class="form__section">
            <!-- Question Field -->
            <input class="form__field" type="text" name="question" required>

            <!-- Poll Options -->
            <ul class="form__list">

                <!-- Poll option form field -->
                <li class="form__list-item form__list-item--creator">
                    <input class="form__field" type="text" name="pollOption">
                    <button class="form__button--add" type="button">&plus;</button>
                </li>

                <!-- Render the options added above -->
                {{#each option in optionList}}
                <li class="form__list-item--option" data-index="{{option.index}}">
                    <span class="form__list-item-value">{{option.label}}</span>
                    <button type="button" class="form__button--delete">&times;</button>
                </li>
                {{/each}}
            </ul>
        </section>

        <button class="form__button--submit" type="submit">Create Poll</button>
        <button class="form__button--reset" type="reset">Clear Fields</button>
    </form>
</template>

poll.create.client.js (Polls = new Mongo.Collection("polls") 在服务器文件中)

// Setup
Template.pollCreate.onCreated(function () {

    // Local poll variable to capture the options in.
    this.options = [
        { index: 0, label: 'BurgerBurger' },
        { index: 1, label: 'BetterBurger' }
    ];

});

// Events
Template.pollCreate.events({
    /**
     * Adds an option to the local array for saving as part of the submit in the Posts.insert call.
     * @param event
     * @param instance
     */
    'click .form__button--add': function ( event, instance ) {
        event.preventDefault();

        // Get current option element
        var option = instance.find('[name="pollOption"]');

        // Store in a local array
        instance.options.push({
            index: instance.options.length,
            label: option.value
        });

        // Clear field so it's ready for another option
        option.value = '';
    },
    /**
     * Delete an existing option.
     * @param event
     * @param instance Template.instance
     */
    'click .form__button--delete': function ( event, instance ) {
        event.preventDefault();

        var listItemElement = event.target.parentNode;
        var itemIndex = instance.$(listItemElement).data('index');

        // Delete option from reactive source array
        instance.options.splice(itemIndex, 1);
    },
    /**
     * Submit the Poll Create form which will run Polls.insert with the question and options
     * @param event
     * @param instance
     */
    'submit .form--create': function ( event, instance ) {
        event.preventDefault();

        var question = instance.find('[name="question"]');
        var options = instance.options;

        var poll = {
            question: question.value,
            options: options
        };

        Polls.insert(poll);
    }
});

// Helpers
Template.pollCreate.helpers({
    optionList: function () {
        const instance = Template.instance();
        return instance.options;
    }
});

我可以看到 instance.options数组值随着我将选项插入或拼接而改变,但它似乎没有重新呈现模板,并且选项列表永远不会改变。

我在这里做错了什么?

最佳答案

每当您希望 ui 响应式更新时,您需要有两件事,(1) 响应式数据源和 (2) 响应式上下文。

现在您已经获得了响应式上下文 - 这是模板助手 optionList,它将在它引用的响应式数据源发生更改时重新呈现。问题是选项列表不是 react 性数据源,它只是一个原始数组。因此,当 Templace.instance().options 数组更改时,助手不知道要重新呈现它。

修复非常简单 - 只需使用 Meteor 的内置 react 结构 ReactiveVarReactiveDict< 使 Template.instance.options 成为 react 数据源 或使用 MiniMongo。您提到的 ReactiveArray 也可以工作 - 我相信这是社区维护的而不是核心包,但它是相同的想法。

这里最快最简单的解决方案是将整个数组保存到一个ReactiveVar:

Template.pollCreate.onCreated(function(){
  this.options = new ReactiveVar([
    { index: 0, label: 'BurgerBurger' },
    { index: 1, label: 'BetterBurger' }
  ]);
});

Template.pollCreate.helpers({
  optionList({
    return Template.instance().options.get();
  })
});

应该可以了。

关于arrays - 本地数组更改时如何重新渲染 meteor blaze 模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35664472/

相关文章:

javascript - 过滤和显示嵌套对象数据

templates - Mediawiki 模板和生成标准化页面

meteor - 铁路由器 : How do I send data to the layout?

csv - 如何使用meteor将存储在DB中的json转换为csv

node.js - 如何在 Node Js 中使用 Mongodb Bulk 和多文档事务?

python - 将制表符分隔的 csv 读入具有不同数据类型的 numpy 数组

c - 计算偶数或奇数然后将它们相加的 for 循环

javascript - 如何获取NodeList中的Node位置?

html - Rockettheme 模板侧边栏出现故障

ruby - 仅当在模板中定义变量时 Puppet 3 循环执行