在开发Windows Store应用时,经常会遇到需要自定义控件的情况。WinJS库为提供了强大的工具来创建这些控件。本文将带了解如何使用WinJS库来创建一个自定义的自动完成(autocomplete)控件,并在此过程中学习一些WinJS的基本概念。
编写自定义控件的第一步是将它们放入自己的命名空间中。命名空间有助于将一组标识符(如类、函数或其他开发语言结构)逻辑地分组。WinJS提供了一个Namespace对象,可以帮助定义命名空间。将使用WinJS.Namespace.define函数,它接受两个参数:命名空间名称和一个包含命名空间标识符的对象。以下示例定义了一个名为MyApp.UI的新命名空间:
WinJS.Namespace.define(
"MyApp.UI", {
// 标识符
}
);
WinJS.Namespace对象还包括一个defineWithParent函数来定义命名空间层次结构,但在本例中不使用它。
现在有了命名空间,接下来是创建控件类。由于JavaScript不包括类概念,可以使用构造函数和原型继承来模拟这种行为。幸运的是,WinJS包括一个Class对象,它公开了定义、派生或混合JavaScript“类”的函数。为了定义一个类,将使用WinJS.Class.define函数。该函数接受三个参数:一个用于初始化对象的构造函数,一个要添加到每个创建实例的实例成员对象,以及一个将添加到类原型的静态成员对象。让在之前创建的命名空间内定义Autocomplete类:
WinJS.Namespace.define(
"MyApp.UI", {
Autocomplete: WinJS.Class.define(
function(element, options) {
// 构造函数主体
},
{
// 实例成员
},
{
// 静态成员
}
);
}
);
如所见,define函数接收所有三个参数。在构造函数中,将得到两个参数,分别是控件的元素和一个用于配置控件的options对象。这两个参数对于构建WinJS控件是必需的,因为它们映射到元素的data-win-control和data-win-options HTML属性,当调用processAll函数时。
现在有了控件类的模板,让创建它的功能。在编写任何代码之前,让了解期望从控件中得到什么。控件需要动态创建一个datalist元素并将其附加到输入类型上(如果想了解新的HTML5 datalist元素,可以访问以下链接)。控件还需要获取一个将显示为自动完成列表的选项列表。让编写代码:
(function(WinJS) {
WinJS.Namespace.define(
"MyApp.UI", {
Autocomplete: WinJS.Class.define(
function(element, options) {
if (!element || element.tagName.toLowerCase() !== "input") {
throw "input type must be provided";
}
options = options || {};
this._setElement(element);
this._setOptionList(options.optionList);
this._element.winControl = this;
WinJS.UI.setOptions(this, options);
this._createDataList();
},
{
_element: null,
_optionList: null,
_setElement: function(element) {
this._element = element;
},
_setOptionList: function(optionList) {
optionList = optionList || [];
this._optionList = optionList;
},
_createDataList: function() {
var i = 0, len = this._optionList.length, dl = document.createElement('datalist');
dl.id = 'dl' + this._element.id;
this._element.setAttribute("list", dl.id);
for (; i < len; i += 1) {
var option = document.createElement('option');
option.value = this._optionList[i];
dl.appendChild(option);
}
document.body.appendChild(dl);
},
element: {
get: function() {
return this._element;
}
}
}
)
});
})(WinJS);
如所见,构造函数首先检查元素是否为输入类型。它还设置了元素和选项列表,这些应该在选项对象中提供。最后,它创建了datalist元素。在实例成员对象中,将函数和属性分为私有和公共成员部分。这种划分只是逻辑上的(并用注释标记),如所见,私有成员在名称前有下划线字符。主要功能是_createDataList函数,它处理datalist的创建并将输入类型列表属性设置为列表ID。所有其他函数都很简单。
现在有了控件,让使用它。在示例应用中,在js文件夹下添加了一个data.js文件,并编写了以下代码:
(function() {
"use strict";
WinJS.Namespace.define(
"Data", {
cities: [
"Seattle",
"Las Vegas",
"New York",
"Salt lake City"
]
}
);
})();
可以获取任何其他数据源(云、服务、存储)的数据,但希望示例尽可能简单。
在位于pages/home文件夹的home.html文件中,添加了一个文本输入类型,使用data-win-control和data-win-options属性进行配置:
<input type="text" name="txtCities" id="txtCities" data-win-control="WinJS.UI.Autocomplete" data-win-options="{ optionList: Data.cities }" />
不要忘记添加autocomplete.js文件和data.js文件的脚本标签,否则示例将无法工作。