logo Kendo UI使用教程-2019 我也要发布文档

自定义小部件(三)


Kendo UI for jQuery最新试用版下载

Kendo UI目前最新提供Kendo UI for jQueryKendo UI for AngularKendo UI Support for ReactKendo UI Support for Vue四个控件。Kendo UI for jQuery是创建现代Web应用程序的最完整UI库。

Kendo UI通过继承基本窗口小部件类为您提供创建自定义窗口小部件的选项。

使用MVVM

1. 为了使该小部件具有MVVM-aware,您需要定义一些事件。具体来说,公开dataBinding事件和dataBound事件。在使用小部件对DOM进行更改之前,将要调用dataBinding事件。这使MVVM有机会遍历将要突变的片段,并取消绑定当前绑定的任何片段。 第二个事件是dataBound事件,它使MVVM返回片段,并重新绑定必要的事件, 这些事件通过小部件上的事件对象公开。这些事件是字符串,因此在开发Kendo UI窗口小部件时,将它们定义为窗口小部件顶部的常量,作为Kendo UI使用模式的一部分。

通过将这些事件公开为MVVM可以监听的事件,您可以在小部件和MVVM核心引擎之间实现松散耦合。 这意味着,如果您不公开这些事件,则MVVM将不会知道窗口小部件的生命周期。 这是一个非常好的架构,这是一个非常好的架构,因为它可以确保您的小部件不会破坏其他不知道的MVVM绑定。

var DATABINDING = "dataBinding",DATABOUND = "dataBound",CHANGE = "change"
var Repeater = kendo.ui.Widget.extend({
init: function(element, options) {
  ...
  },
  options{
  ...
  },
// The events are used by other widgets or developers - API for other purposes.
  // These events support MVVM bound items in the template for loose coupling with MVVM.
  events: [
  // Call before mutating DOM.
  // MVVM will traverse DOM, unbind any bound elements or widgets.
  DATABINDING,
  // Call after mutating DOM.
  // Traverses DOM and binds ALL THE THINGS.
  DATABOUND
  ]
  });

2. MVVM希望您从窗口小部件中公开DOM片段,该片段代表每一行或每个重复的数据元素。 您必须返回最外面的元素,MVVM才能使用。虽然有所不同,但这通常只是this.element.children。 由于呈现的每个模板项目都是一个DOM片段,并附加到绑定的元素上,因此您只需要这些。 通过使它在Items对象之外可用,将其公开用于MVVM。

var DATABINDING = "dataBinding",DATABOUND = "dataBound",CHANGE = "change"
var Repeater = kendo.ui.Widget.extend({
init: function(element, options) {
  ...
  },
  options{
  ...
  },
// The events are used by other widgets or developers - API for other purposes.
  // These events support MVVM bound items in the template. for loose coupling with MVVM.
  events: [
  // Call before mutating DOM.
  // MVVM will traverse DOM, unbind any bound elements or widgets.
  DATABINDING,
  // Call after mutating DOM.
  // Traverses DOM and binds ALL THE THINGS.
  DATABOUND
  ],
// MVVM expects an array of DOM elements that represent each item of the datasource.
  // Has to be the children of the outermost element.
  items: function() {
  return this.element.children();
  }
  });

3. 由于可以使用MVVM更改数据源,因此需要实现setDataSource函数。 当在ViewModel中设置数据源时,MVVM会调用此方法。 将内部DataSource引用设置为与MVVM传递的引用相等,然后使用已定义的dataSource()函数重新构建DataSource。

// For supporting changing the datasource over MVVM.

  setDataSource: function(dataSource) {
// Set the internal datasource equal to the one passed in by MVVM.
this.options.dataSource = dataSource;
// Rebuild the datasource if necessary or just reassign.
this._dataSource();
}

4. 您需要对分配或构建数据源的方法进行一些小的调整,在init中调用的_dataSource方法可完成3件事:

  • 分配数据源,或从数组或配置对象建立。
  • 从DataSource读取(如果启用了autoBind且尚未从DataSource读取)。
  • 将数据源上的change事件绑定到您手动处理的内部刷新方法。

由于您可能已经在数据源上绑定了一次更改事件,因此请确保在必要时取消绑定。如果不这样做,则小部件将保留所有绑定的列表,并多次执行刷新功能。 同样,MVVM将监听尚未定义的内部_refreshHandler函数,您需要将内部_refreshHandler指向公开的刷新方法。不过,请首先检查绑定到DataSource上的change事件的公共刷新和内部_refreshHandler之间是否存在现有连接,如果存在,则仅删除对更改事件的绑定。 如果内部_refreshHandler与公共刷新功能之间没有连接,则需要创建它。这是通过$ .proxy jQuery方法完成的,该方法使用正确的上下文(即小部件本身)调用公共刷新。 最后,重新绑定到DataSource的change事件。

如果您以前没有使用过代理jQuery函数,则以下内容可能会造成混淆,在调用_refreshHandler时,它应该执行公共刷新小部件函数,并且在该刷新函数内部,这将是一个指向窗口小部件本身,而不是窗口之类的其他东西。 由于JavaScript中关键字的值始终在变化,因此这是确保刷新函数执行时范围正确的一种好方法。

_dataSource: function() {
var that = this;
// If the DataSource is defined and the _refreshHandler is wired up, unbind because
  // you need to rebuild the DataSource.
  if ( that.dataSource && that._refreshHandler ) {
  that.dataSource.unbind(CHANGE, that._refreshHandler);
  }
  else {
  that._refreshHandler = $.proxy(that.refresh, that);
  }
// Returns the datasource OR creates one if using array or configuration object.
  that.dataSource = kendo.data.DataSource.create(that.options.dataSource);
  // Bind to the change event to refresh the widget.
  that.dataSource.bind( CHANGE, that._refreshHandler );
if (that.options.autoBind) {
  that.dataSource.fetch();
  }
  }

5. 在公共刷新中触发dataBinding和dataBound事件。 请注意,dataBinding发生在更改DOM之前,而dataBound发生在此之后。

refresh: function() {var that = this,view = that.dataSource.view(),html = kendo.render(that.template, view);
// Trigger the dataBinding event.
  that.trigger(DATABINDING);
// Mutate the DOM (AKA build the widget UI).
  that.element.html(html);
// Trigger the dataBound event.
  that.trigger(DATABOUND);
  }

现在,您的窗口小部件中已完全启用了MVVM。 定义小部件,如下面的示例所示。

<div data-role="repeater" data-bind="source: dataSource"></div>
<script>
var viewModel = kendo.observable({
dataSource:  new kendo.data.DataSource({
transport: {
read: "Customers/Orders",
dataType: "json"
}
})
});
kendo.bind(document.body.children, viewModel);
</script>

注意,小部件现在通过数据绑定绑定到ViewModel内部的dataSource变量。 这意味着,如果我们在数据源中添加客户端项,则您的窗口小部件将立即反映更改,而无需重新渲染任何内容。

在下面的完整示例中,请注意将项目添加到数据源时,它会立即反映在Repeater小部件中。

```dojo<label for="newItem">Enter A New Item</label><input id="newItem" data-bind="value: newItem" class="k-input" /><button class="k-button" data-bind="click: add">Add Item</button>
<div data-role="repeater" data-bind="source: items" data-template="template"></div>
<script type="text/x-kendo-template" id="template">
  <div style="color: salmon; margin-right: 10px'"><h1>#= data #</h1></div>
  </script>
<script>
  var viewModel = kendo.observable({
  items: ["item1", "item2", "item3"],
  newItem: null,
  add: function(e) {
  if (this.get("newItem")) {
  this.get("items").push(this.get("newItem"));
  }
  }
  });
kendo.bind(document.body, viewModel);
  </script>
```
使用价值有限的小部件

为了使小部件支持值绑定,您需要:

  • 向窗口小部件添加一个value方法,该方法设置当前窗口小部件的值,如果未传递任何参数,则返回当前值。
  • 更改窗口小部件值时触发窗口小部件更改事件。

以下示例演示如何创建一个简单的输入小部件,以选择焦点值。

1. 创建窗口小部件并实现所需的功能。

(function ($) {var kendo = window.kendo;
var SelectedTextBox = kendo.ui.Widget.extend({
  init: function (element, options) {
  kendo.ui.Widget.fn.init.call(this, element, options);
this.element.on("focus", this._focus);
  },
options: {
  name: "SelectedTextBox"
  },
_focus: function () {
  this.select();
  },
destroy: function () {
  this.element.off("focus", this._focus);
  }
  });
kendo.ui.plugin(SelectedTextBox);
  })(jQuery);

2. 添加一个value方法。

var SelectedTextBox = kendo.ui.Widget.extend({
...
value: function (value) {
if (value !== undefined) {
this.element.val(value);
} else {
return this.element.val();
}
}
});

3. 触发change事件。

var SelectedTextBox = kendo.ui.Widget.extend({init: function (element, options) {...this._changeHandler = $.proxy(this._change, this);this.element.on("change", this._changeHandler);},
...
_change: function () {
  this.trigger("change");
  },
destroy: function () {
  this.element.off("change", this._changeHandler);
  this.element.off("focus", this._focus);
  }
  });

以下示例结合代码片段并展示完整的代码。

<script>(function ($) {var kendo = window.kendo;
var SelectedTextBox = kendo.ui.Widget.extend({
  init: function (element, options) {
  kendo.ui.Widget.fn.init.call(this, element, options);
this._changeHandler = $.proxy(this._change, this);
  this.element.on("change", this._changeHandler);
  this.element.on("focus", this._focus);
  },
options: {
  name: "SelectedTextBox"
  },
_change: function () {
  this._value = this.element.val();
  this.trigger("change");
  },
_focus: function () {
  this.select();
  },
value: function (value) {
  if (value !== undefined) {
  this.element.val(value);
  } else {
  return this.element.val();
  }
  },
destroy: function () {
  this.element.off("change", this._changeHandler);
  this.element.off("focus", this._focus);
  }
  });
kendo.ui.plugin(SelectedTextBox);
  })(jQuery);
  </script>
<input type="text" data-role="selectedtextbox" data-bind="value:foo" />
<script>
  var viewModel = kendo.observable({
  foo: "bar"
  });
kendo.bind(document.body, viewModel);
  </script>

Kendo UI R3 2019全新发布,最新动态请持续关注Telerik中文网!

扫描关注慧聚IT微信公众号,及时获取最新动态及最新资讯

慧聚IT微信公众号