javascript - 如何以编程方式加载 KnockoutJS 组件

标签 javascript knockout.js knockout-3.0

我开始为 select2 创建一个名为“select-two”的 ko 组件,但我很快意识到我有时需要在注册绑定(bind)后加载组件以编程方式创建组件。

我试过附加一个新元素,但当然它不起作用,我猜它必须重新绑定(bind)。

var sel2 = $("<select-two></select-two>") ;
$("#selectList").append(sel2) ; 

有很多关于如何重新绑定(bind)整个 View 模型的引用,但只是组件?我认为这个人有同样的问题: Load knockoutjs component using javascript

仅供引用,这是组件代码:

define([
'knockout',
'text!./select-two.html',
'select2'
], function (ko,  templateMarkup, select2) {
ko.components.register('select-two', {
    viewModel: function(params) {

        var placeholder = params.placeholder;
        var value = params.value;

        ko.bindingHandlers.select2 = {
            init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
                $(element).select2({
                        placeholder: placeholder,
                        minimumInputLength: 1,
                        ajax: {
                            url: function (term, page) {
                                return '/models/autores/busqueda/' + term['term']
                            },
                            dataType: 'json',
                            quietMillis: 200,
                            processResults: function (data) {
                                return data;
                            }
                        },
                        dropdownCssClass: "bigdrop", // apply css that makes the dropdown taller
                    }
                ).on('change', function(event){
                        ds = $(element).select2('data')[0] ;

                        value['id'](ds['id']) ;
                        value['text'](ds['text']) ;
                    });
            }
        };
        return{
        }
    },
    template: templateMarkup
});
});

我的模板:

<link rel="stylesheet" href="/assets/js/vendor/select2/dist/css/select2.css" />
<select class="form-control" data-bind="select2"></select>

以及我如何加载它:

<select-two id="authorSelect" params="placeholder: 'Pick an Author', value: autorSelectData" ></select-two>

ko.bindingHandlers.select2 = {
   init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
      var params = ko.unwrap(valueAccessor());
      $(element).select2({
         placeholder: params.placeholder,
         minimumInputLength: 1,
         data: params.data
       }).on('select2:select', function(e) { 
        params.value(e.params.data.text);
       });
      $(element).select2('val', params.value); // set initial value
   }
};

ko.components.register('select-two', {
  viewModel: function(params) {
    this.value = params.value;
    this.data = params.data;
  },
  template: '<select class="form-control" style="width: 200px;" data-bind="select2: ' + 
            '{placeholder: \'Pick a fruit\', value: value, data: data}">' +
            '</select>'
});

var app = {
  newSelect: function(){
    var cont = $("<p></p>") ; 
    var sel2 = $("<select-two></select-two>") ; 
    ko.applyBindings({}, sel2[0]) ;
    cont.append(sel2) ; 
    $("#select-list").append(cont) ; 
    
  },
  autorSelectData: ko.observable(null), 
  options: ['apple','pear','peach','mango','grape']
};

ko.applyBindings(app);
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
Just the binding: <select class="form-control" style="width: 200px;"
        data-bind="select2: {placeholder: 'Pick a fruit', value: autorSelectData, data: options}">
</select><br>
With component: <select-two params="value: autorSelectData, data: options"></select-two>

<p>Adding Selects</p>
<div id="select-list">
  
</div>

<input type="button" data-bind="click: newSelect()" value="New Select" id="new-select" />

最佳答案

I'm guessing it has to be rebinded.

请记住,当您将重新绑定(bind)视为一种解决方案时,在 99% 的情况下您应该重新考虑您的方法。

creating the component programmatically.

如果您遵循 MVVM/MVC 准则,则永远不必这样做。所有数据模型/ View 的结构都是预定义的;只有他们的内容可以改变。

你不应该做什么?

  • 在组件内注册自定义绑定(bind),这意味着每次创建组件实例时都会重新注册。
  • 在组件模板中链接样式表,这意味着每次创建组件实例时都会加载样式表(而不是一次)。
  • select2 docs 时使用 change 事件显示您必须使用 select2:select

下面是您的代码的精简版本(例如,数据数组而不是 AJAX),展示了它如何与 (1) 仅绑定(bind)以及 (2) 封装组件一起工作。它仍然不起作用吗?如果是,是什么不起作用?

ko.bindingHandlers.select2 = {
   init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
      var params = ko.unwrap(valueAccessor());
      $(element).select2({
         placeholder: params.placeholder,
         minimumInputLength: 1,
         data: params.data
       }).on('select2:select', function(e) { 
        params.value(e.params.data.text);
       });
      $(element).select2('val', params.value); // set initial value
   }
};

ko.components.register('select-two', {
  viewModel: function(params) {
    this.value = params.value;
    this.data = params.data;
  },
  template: '<select class="form-control" style="width: 200px;" data-bind="select2: ' + 
            '{placeholder: \'Pick a fruit\', value: value, data: data}">' +
            '</select>'
});

var app = {
  autorSelectData: ko.observable(null), 
  options: ['apple','pear','peach','mango','grape']
};

ko.applyBindings(app);
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
Just the binding: <select class="form-control" style="width: 200px;"
        data-bind="select2: {placeholder: 'Pick a fruit', value: autorSelectData, data: options}">
</select><br>
With component: <select-two params="value: autorSelectData, data: options"></select-two>

关于javascript - 如何以编程方式加载 KnockoutJS 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31636776/

相关文章:

knockout.js - KnockoutJS : computed vs. 纯计算

javascript - 如何使用另一页面的 Knockout JS 将一个 viewModel 数据传递到其他 ViewModel 函数

javascript - 当图像尺寸大于最小标准时拖动图像

javascript - 在另一个上下文中使用计算可观察量的实际示例

javascript - 引用 API 请求的 JSON 数据结果 - Javascript

javascript - MM/DD 验证。它没有 YYYY 也应该验证 02/30 我也不能

javascript - 有没有办法控制 Chrome GC?

javascript - 带 knockout 的 jqxDropDownList 无法绑定(bind) selectedvalue

javascript - Select2 - 通过 ajax 调用传回附加数据

javascript - MongoDB:如何确保 Javascript 正在等待进程?