动态淘汰模板模式潜在陷阱

时间:2016-04-14 16:53:56

标签: javascript templates mvvm knockout.js requirejs

我正在使用require和knockout创建一个类似仪表板的小部件,我想知道是否有人可以看到我使用的方法有任何潜在的缺点。

我有一个带模板的布局和一个自定义绑定(仪表板):

注意:将仪表板绑定视为模板绑定的一个克隆,在dashboardItems可观察集合中添加/删除项目时,可以使用布局相关函数的帮助程序。

<!-- snip -->
    <div>
        <ul data-bind="dashboard: { templateName: 'dashboard-item', items: dashboardItems' }"></ul>
    </div>

    <script id="dashboard-item" type="text/html">
        <li>
            <div data-bind="component: { name: componentName, params: $data }"></div>
        </li>
    </script>

    <script id="dashboard-container" type="text/html">    
        <div class="dashboard-container">

            <!-- other ko templates common to all widgets -->    

            <!-- ko if: configMode -->
                <!-- this section is specific to each widget -->    
                <!-- ko template: configTemplateId --><!-- /ko -->
            <!-- /ko -->

            <!-- ko ifnot: configMode -->
                <!-- this section is specific to each widget -->    
                <!-- ko template: contentTemplateId --><!-- /ko -->
            <!-- /ko -->

            <!-- other ko templates common to all widgets -->    

        </div>
    </script>
<!-- /snip -->

我有一个通过require加载的组件:

<script data-bind="attr: { id: configTemplateId }" type="text/html">
    <!-- layout/content specific to this widget/section -->
</script>

<script data-bind="attr: { id: contentTemplateId }" type="text/html">
    <!-- layout/content specific to this widget/section -->
</script>

<div data-bind="template: 'widget-container'"></div>

所有组件视图模型都继承自基类&#39;:

<!-- snip -->
    function componentBase(config) {

        var self = this;

        self.configTemplateId = ko.observable("config_" + config.uid);
        self.contentTemplateId = ko.observable("content_" + config.uid);

    };
<!-- /snip -->

这就是:

  1. 主页加载包含&#39; dashboard-container&#39;模板。
  2. 组件视图模型添加到dashboardItems observable。
  3. 自定义组件加载器使用require加载并绑定到组件的视图。
  4. 组件viewmodel的configTemplateId和contentTemplateId绑定到其视图中脚本标记的id attr。
  5. KO加载仪表板组件&#39;组件模板中的模板,然后在viewmodel上查找配置和内容模板ID,并将它们加载到“仪表板 - 组件”的相应区域中。模板。
  6. 我这样做的原因是因为所有小部件都共享相同的基本模型,因此我希望在&#中的一个位置(加载模板,配置模板等)中保留常见的方面/模板。 39;插件容器&#39;但为了简洁/清洁而从这篇文章中删除。

    关键是我不想记住要包含的内容以及在每个小部件模板中将这些内容洒在哪里,然后如果需要更改某些内容,则必须对每个小部件进行更改。

    毕竟问题很简单:任何人都可以在以这种方式使用ko模板绑定时看到任何潜在的问题,或者有人能想到更好的方法吗?也许有一种方法可以让tempalte绑定一个对占位符的引用并将其注入其中呢?

    提前致谢!

    麦克

1 个答案:

答案 0 :(得分:0)

如果有许多组件需要访问共享中心资源(例如数据API或中央应用程序状态),那么确实需要提前做好一些计划。

我有自己的格式 - 不是作为概念证明的播种机 - 包括使用需求的单独模块,同一页面上的多个组件,中央资源和组件之间的交互,还包括对babel的支持 - ES2015(新的Javascript)并且被吞咽。

https://github.com/brianlmerritt/knockout-babel-browserify-gulp

示例组件:

const ko = require('knockout')
    , CentralData = require('../../service-providers/central-data')
    , CentralState = require('../../service-providers/central-state')
    , template = require('./template.html');

const viewModel = function (data) {

    //Make service providers accessible to data-bind and templates
    this.CentralData = CentralData;
    this.CentralState = CentralState;

    this.componentName = 'Component One';
    this.foo = ko.observable(`${this.componentName} Foo`);
    this.bar = ko.observableArray(this.componentName.split(' '));
    this.barValue = ko.observable("");
    this.bar.push('bar');
    this.addToBar = (stuffForBar) => {
        if(this.barValue().length >= 1) {
            this.bar.push(this.barValue());
            CentralData.pushMoreData({firstName: this.componentName,secondName:this.barValue()});
        }
    };
    this.CentralState.signIn(this.componentName);
    if (CentralData.dataWeRetrieved().length < 10) {
        var dataToPush = {firstName : this.componentName, secondName : 'Foo-Bar'};
        CentralData.pushMoreData(dataToPush);
    }
};
console.info('Component One Running');
module.exports = {
    name: 'component-one',
    viewModel: viewModel,
    template: template
};

一个示例服务提供商

const ko = require('knockout');

const CentralState = {
    signIn : componentName => signIn(componentName),
    signedInComponents : ko.observableArray([]),
};

const signIn = (componentName) => {
    if (CentralState.signedInComponents().indexOf(componentName) < 0) {
        CentralState.signedInComponents.push(componentName);
    }
};
console.info('Central State Running');
module.exports = CentralState;

您可以添加模型来管理特定数据类型,您可能希望将配置程序作为中央服务提供者。