KnockoutJS:在applyBindings之后注入模板(组件)

KnockoutJS: inject template (component) after applyBindings

本文关键字:组件 注入 applyBindings 之后 KnockoutJS      更新时间:2023-09-26

假设有一个简单的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,然后稍后根据需要添加和呈现新组件。

我偶然发现了这篇文章,因为它描述了类似于我遇到的问题。我们将视图模型绑定到特定元素,因为它可能存在也可能不存在;为了使组件绑定,我只需要背上它,以下是我如何实现的:

有一个集合来存储你介意的元素

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);
}
默认情况下,会显示添加到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);

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