【问题标题】:KnockoutJS: inject template (component) after applyBindingsKnockoutJS:在 applyBindings 之后注入模板(组件)
【发布时间】:2015-08-11 21:19:32
【问题描述】:

假设有一个简单的 HTML 模板:

<div>
    <content-a></content-a>
    <content-b></content-b>
</div>

我使用注册两个组件(例如组件“content-a”):

ko.components.register('content-a', {
    viewModel: { instance: vm }, // ViewModel for that component
    template: template // template of that component
});

然后我将 HTML 模板注入到指定的 HTML 元素中:

var node = document.getElementById('content');
node.innerHTML = template; // here "template" represent just a HTML string (described at the very top)
ko.applyBindings(vm, node); // here vm represents ViewModel instance

但是,当我应用绑定时,所有注册的组件都会被渲染。

有没有办法按需渲染组件?应用 applyBindings 时不会。

换句话说:我想渲染主要内容、applyBindings,然后根据需要添加和渲染新组件。

【问题讨论】:

    标签: javascript knockout.js rendering components


    【解决方案1】:

    我偶然发现了这篇文章,因为它描述了与我遇到的问题类似的内容。我们将视图模型绑定到特定元素,因为它可能存在也可能不存在;为了让组件绑定,我只是背负这个,这是我实现这个的方法:

    有一个集合来存储你需要注意的元素

    var self = this;
    self.modulesToLoad = [];
    self.elements = [];
    

    用小函数检查元素是否存在

    self.checkIfElementExists = function (element, viewModel) {
        if (element != undefined) {
            self.modulesToLoad.push(viewModel);
            self.elements.push(element);
        }
    };
    

    声明你的组件

    ko.components.register("custom-component", {
         template: { require: "text!Components/custom-component/custom-component.html" },
        viewModel: { require: "Components/custom-component/custom-component" }
    });
    

    添加到检查元素是否存在的集合

    self.checkIfElementExists($("custom-component")[0], 
                              "Components/custom-component/custom-component"); // A little bit of repetition here, but do you care?
    

    最后循环遍历集合

    for(var i = 0; i  < elements.length; i++) {
        var viewModel = new arguments[i]();
        var element = elements[i];
        ko.applyBindings(viewModel, element);
    }
    

    【讨论】:

      【解决方案2】:

      默认情况下,所有添加到 DOM 的组件都会显示出来。如果您想隐藏它们直到满足特定条件,您可以这样做 -

      yourView.html -

      <section class="sales" data-bind="visible: isRendered">
          <div data-bind="text: sales"></div>
      </section>
      

      yourViewModel.js -

      define([], function () {
        return { 
          isRendered: ko.observable(false),
          sales: ko.observable()
        }
      });
      

      组件注册-

      ko.components.register('yourComponent', {
          viewModel: { require: 'files/yourViewModel' },
          template: { require: 'text!files/yourView.html' }
      });
      

      然后您可以更改组件的值 isRendered observable 以使其显示 -

      vm.isRendered(true);
      

      当然,这都是伪代码,但如果你为你正在尝试做的事情做了一个工作小提琴,我可以在那里帮助解释更多。我上面的代码展示了如何使用模块加载器构建组件,但希望它应该有意义。

      【讨论】:

      • 是的,使用“可见”绑定是个好主意。这使我朝着正确的方向前进。但是,我正在考虑在需要时将模板注入 DOM。在这种情况下,“组件”不会有太大帮助,因为它们是在应用绑定之后添加到 DOM 中的。
      猜你喜欢
      • 2018-04-07
      • 2012-03-07
      • 2012-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多