Kendo 使用 MVVM 和初始化事件的自定义小部件 - 怎么样?

Kendo custom widget with MVVM and init event - how?

我尝试使用 "Init" 事件实现自定义 kendo 小部件。如果使用 JavaScript 初始化小部件,则会触发事件。但是当使用数据属性初始化小部件时 - 它不会。我想念什么?

样本:http://dojo.telerik.com/UQoWi

注意:如您所见,我已尝试根据 KendoUI 的文档处理 "init" 事件:

... data-init="onInit" data-bind="events: { init: onInit }" ...

补充:我想补充一点,我完全理解为什么还没有 init 活页夹。这真的没有意义。由于 ViewModel 可以绑定到 Kendo 中的许多不同事物,因此在 Viewmodel 中为 Widget 进行初始化回调是没有意义的。这就是使用 dataBinding 和 dataBound 的原因。创建小部件时,它会调用 data-init="" 的处理程序,它只需要在范围内即可。这是对小部件的一次性调用。 ViewModel Observable 可以绑定和解除绑定到许多不同的小部件。系统如何知道 Observable ViewModel 应该严格绑定到那个特定的小部件?除非您更新小部件以具有内部数据源和可观察性,否则不会。

如果此 Observable 绑定到您的多个自定义小部件,则将为每个小部件调用 onInit。它不会被任何内置小部件调用,因为它们不会触发(INIT)。这很容易通过重载 fn.init 函数或扩展它们来解决。或者,甚至创建一个在 data-init 元素属性中使用的全局 onInit 函数,因为您可以通过参数访问小部件本身。 $(element).data("kendoWidget") 等等

希望这对您有所帮助!它确实帮助我理解了一切。


我已经能够做你想做的事了。看来我对 data-bind="events: {}" 的用途有很大的误解。该定义中的处理程序似乎是 HTML 事件的处理程序。所以我们可以向 Widget 系统本身添加一个新的 'init' 处理程序。我已经能够让您的示例使用下面的代码。

关键是为名为 'init' 的 Kendo 事件添加一个新的活页夹。

kendo.data.binders.widget.init = 
   kendo.data.Binder.extend({
      function(widget, bindings, options) {
        Binder.fn.init.call(this, widget.element[0], bindings, options);
        this.widget = widget;
      },
      refresh: function () {
         var init = this.bindings.init.get();
      }              
   });

然后我们可以使用 data-bind="init: onInitFromMVVM" 绑定到一次性偶数调用。这只会是一次性调用,因为它只会在 Widget 的初始化中触发。

我一遍又一遍地浏览源代码,events: {} 让我感到困惑,直到我开始阅读文档。然后我意识到 events: {} 中的几乎所有处理程序都是针对 HTML 事件的。诸如 visible、onmouseover、onmouseexit 等之类的东西。然后我创建了一个名为 'init' 的新活页夹,之后您的代码就可以正常工作了。

下面的代码产生以下输出: widget init proof global init proof init mvvm proof

它甚至在全局范围内调用 data-init 的处理程序。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Untitled</title>    
    <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.common.min.css">
    <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.rtl.min.css">
    <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.default.min.css">
    <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.mobile.all.min.css">
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://kendo.cdn.telerik.com/2015.3.930/js/angular.min.js"></script>
    <script src="http://kendo.cdn.telerik.com/2015.3.930/js/jszip.min.js"></script>
    <script src="http://kendo.cdn.telerik.com/2015.3.930/js/kendo.all.min.js"></script>    
    <script>          
      var binders = kendo.data.binders,
                Binder  = kendo.data.Binder,
                proxy   = $.proxy,
                    ui        = kendo.ui,
                    Widget  = ui.Widget,
                    INIT        = 'init';

        (function ($) {

            kendo.data.binders.widget.init = 
              kendo.data.Binder.extend({
                init: function(widget, bindings, options) {
                                        Binder.fn.init.call(this, widget.element[0], bindings, options);
                    this.widget = widget;
                },

                refresh: function () {
                    var init = this.bindings.init.get();
                }              
            });

            var MyWidget = Widget.extend({
                options: {
                    name: 'MyWidget',
                },
                events: [
                    INIT
                ],
                init: function (element, options) {                  
                    var that = this;
                    console.log('widget init proof');  
                    Widget.fn.init.call(this, element, options);                                                             
                    that.trigger(INIT);
                }
            });

            ui.plugin(MyWidget);

        })(jQuery);

        $(document).ready(function () {

            var observableModel = new kendo.data.ObservableObject({
                onInitVM: function (e, opts) {
                    console.log('init mvvm proof');
                }
            });

            kendo.bind($('#myWidgetMVVM'), observableModel);
        });
    </script>
</head>
<body>
    <div>Open console...</div>
    <input type="hidden" id="myWidgetMVVM" data-init="onInit" data-role="mywidget" data-bind="init: onInitVM" />
  <script>
    function onInit(element, options) {
       console.log("global init proof");       
    }
  </script>
</body>
</html>