概述: Kendo UI Web包含数百个创建HTML5 web app的必备元素,包括UI组件、数据源、验证、一个MVVM框架、主题、模板等。在前面的2篇文章《HTML5 Web app开发工具Kendo UI Web教程:创建自定义组件》中,已经对在Kendo UI Web中如何创建自定义组件的方法和步骤做了一些的讲解,本文将完成所有的创建内容。
- HTML5 Web app开发工具Kendo UI Web教程:如何配置Kendo UI Calendar
- HTML5 Web app开发工具Kendo UI Web教程:如何添加仪表和图表
- HTML5 Web app开发工具Kendo UI Web教程:AutoComplete功能解析
- HTML5 Web app开发工具Kendo UI Web教程:颜色拾取器的使用
- HTML5 Web app开发工具Kendo UI Web教程:Grid网格控件本地化
- HTML5 Web app开发工具Kendo UI Web教程:创建自定义组件(一)
- HTML5 Web app开发工具Kendo UI Web教程:创建自定义组件(二)
Kendo UI Web包含数百个创建HTML5 web app的必备元素,包括UI组件、数据源、验证、一个MVVM框架、主题、模板等。在前面的2篇文章《HTML5 Web app开发工具Kendo UI Web教程:创建自定义组件》中,已经对在Kendo UI Web中如何创建自定义组件的方法和步骤做了一些的讲解,本文将完成所有的内容。
模板绘制控件:
通过Kendo UI的Templates渲染进行HTML输出,Kendo UI Templates允许你编译HTML和注入数据或表达式到被评估以及作为一个HTML字符串返回的DOM片段的HTML中。在
Kendo UI中的所有组件都允许指定一种除组件使用的默认模版之外的模版。要指定模版,需要首先添加模版到选择对象中,并设置它的值为一个空的字符串,相反其他的配置设置,我们不会在这里设置它的默认值。
添加模版到选项:
1
2
3
4
5
|
options: {
name:
"Repeater"
,
autoBind:
true
,
template:
""
}
|
设置这个模版的默认值:
1
|
that.template = kendo.template(that.options.template ||
"<p><strong>#= data #</strong></p>"
)
|
实现一个刷新功能:
由于绑定到一个change方法,现在需要实现当DataSource改变或者是被直接调用的时候,这个refresh public函数会被调用,这个刷新方法就是我将要mutate DOM的地方。首先需要做的事情就是调用我们来自DataSource数据的that.dataSource.view(),接下来就是使用kendoRender,并随着DataSource数据通过一个模版,这个就是Kendo UI组件mutate DOM的方法。渲染方法应用数据到数据源并返回HTML字符串。
公有Refresh Function:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
refresh:
function
() {
var
that =
this
,
view = that.dataSource.view(),
html = kendo.render(that.template, view);
}
Mutate DOM Element HTML:
refresh:
function
() {
var
that =
this
,
view = that.dataSource.view(),
html = kendo.render(that.template, view);
that.element.html(html);
}
|
数据源控件的完整代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
(
function
() {
var
kendo = window.kendo,
ui = kendo.ui,
Widget = ui.Widget,
CHANGE =
"change"
;
var
Repeater = Widget.extend({
init:
function
(element, options) {
var
that =
this
;
kendo.ui.Widget.fn.init.call(that, element, options);
that.template = kendo.template(that.options.template ||
"<p><strong>#= data #</strong></p>"
);
that._dataSource();
},
options: {
name:
"Repeater"
,
autoBind:
true
,
template:
""
},
refresh:
function
() {
var
that =
this
,
view = that.dataSource.view(),
html = kendo.render(that.template, view);
that.element.html(html);
},
_dataSource:
function
() {
var
that =
this
;
// 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,
function
() {
that.refresh();
});
if
(that.options.autoBind) {
that.dataSource.fetch();
}
}
});
ui.plugin(Repeater);
})(jQuery);
|
下面是一个演示,有两个组件在这里进行了初始化,第一个是使用一个简单的阵列作为数据源,第二个是使用的远程端点、模板、并声明初始化。
1
2
3
4
5
6
7
8
9
|
var
dataSource =
new
kendo.data.DataSource({
data: [
"item1"
,
"item2"
,
"item3"
]
});
kendo.bind($(
"#container"
));
$(
"#repeater"
).kendoRepeater({
dataSource: [
"item1"
,
"item2"
,
"item3"
]
});
|
组件MVVM Aware:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
var
DATABINDING =
"dataBinding"
,
DATABOUND =
"dataBound"
,
CHANGE =
"change"
var
Repeater = kendo.ui.Widget.extend({
init:
function
(element, options) {
...
},
options{
...
},
// events are used by other widgets / 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将会要我们公有代表着我们组件的每一行或者是每个重复元素的DOM 片段,我们需要返回使用到的对于MVVM的最外层的元素,在通常情况下是this.element.children。由于每个模版项目呈现的是一个与绑定元素相关的DOM片段,我们可以通过使它对项目对象不可用,来对MVVM公有它。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
var
DATABINDING =
"dataBinding"
,
DATABOUND =
"dataBound"
,
CHANGE =
"change"
var
Repeater = kendo.ui.Widget.extend({
init:
function
(element, options) {
...
},
options{
...
},
// events are used by other widgets / 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.
// should be the outermost element's children
items:
function
() {
return
this
.element.children();
}
});
|
改变数据源:
1
2
3
4
5
6
7
|
// for supporting changing the datasource via 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();
}
|
调整 _dataSource:
对于我们用于指定和创建数据源的方法现在需要做一些调整。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
_dataSource:
function
() {
var
that =
this
;
// if the DataSource is defined and the _refreshHandler is wired up, unbind because
// we 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();
}
}
|
果说在之前你没有使用过代理 jQuery 函数,现在可能会有一点混乱,当_refreshHandler被调用时都会被调整,公有刷新组件功能更以及内置的刷新功能也会相应的实现,这个也会引用该组件的本身,并不是其他的类似于窗口的东西。由于关键字的值总是用JS改变,当刷新功能执行的时候,这个是一个好的办法来确保正确的范围。
触发绑定/绑定事件:
最后我们只需要触发数据绑定和数据绑定事件,在mutate DOM之前以及数据绑定直接发生之后,用公有的刷新和内存实现这个。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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,这就意味着我们可以像下面这个样自定义组件:
1
2
3
4
5
6
7
8
9
10
11
12
|
<div data-role=
"repeater"
data-bind=
"source: dataSource"
>
<script>
var
viewModel = kendo.observable({
dataSource:
new
kendo.data.DataSource({
transport: {
read:
"Customers/Orders"
,
dataType:
"json"
}
})
});
kendo.bind(document.body.children, viewModel);
</script>
|
以上就是完整的示例了,需要注意的是,当你添加一个项目到数据源的时候,它就会立即反映到中继器组件中。
1
2
3
4
5
6
7
8
9
10
11
|
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);
|