Статьи

Как написать пользовательский элемент управления WinJS

В последнее время я участвовал в нескольких проектах Windows 8. Один из вопросов, которые мне периодически задавали, был о том, как написать собственный пользовательский элемент управления приложениями Магазина Windows с библиотекой WinJS. В этом посте мы попытаемся дать вам старт для вашей библиотеки пользовательских элементов управления. Во время публикации вы шаг за шагом создадите элемент управления автозаполнением и узнаете несколько концепций WinJS. Итак, начнем.

Объект WinJS.Namespace

Первое, что нужно сделать, когда вы пишете свои собственные элементы управления, это поместить их в свое собственное пространство имен. Пространства имен помогают сгруппировать набор идентификаторов в логическую группу. Эти идентификаторы могут быть классами, функциями или любыми другими структурами языка разработки, которые вы хотите сгруппировать в пространстве имен. Для получения более подробной информации о пространствах имен JavaScript перейдите по следующей ссылке .

WinJS включает в себя объект пространства имен, который может помочь вам определить пространства имен. Вы будете использовать функцию WinJS.Namespace.define, которая получает два параметра: имя пространства имен и объект, заполненный идентификаторами пространства имен. В следующем примере определяется новое пространство имен MyApp.UI :

WinJS.Namespace.define("MyApp.UI", {
   // identifiers
});

Объект WinJS.Namespace также включает функцию defineWithParent для определения иерархий пространства имен, но в этом примере я не использую его.

Определение класса управления

Итак, теперь у нас есть пространство имен, что дальше? создание класса управления.

Поскольку JavaScript не включает концепцию класса, вы можете имитировать это поведение, используя функции конструктора и прототипное наследование. К счастью, WinJS включает в себя объект Class, который предоставляет функции для определения, извлечения или смешивания JavaScript-классов.

Чтобы определить класс, вы будете использовать функцию WinJS.Class.define . Функция получает три параметра: функцию конструктора для инициализации объектов, объект-члены экземпляра, который нужно добавить к каждому созданному экземпляру, и объект-член static, который будет добавлен к прототипу класса. Давайте определим класс Autocomplete внутри ранее созданного пространства имен:

WinJS.Namespace.define("MyApp.UI", {
        Autocomplete: WinJS.Class.define(function (element, options) {
            // constructor function body
        }, 
        { // instance members },
        { // static members });
});

Как видите, функция define получает все три параметра. В функции конструктора вы получите два параметра, которые являются элементом для элемента управления и объектом параметров для настройки элемента управления. Эти два параметра являются обязательными для создания элемента управления WinJS, поскольку они сопоставляются атрибутам HTML data-win-control и data-win-options элемента при вызове функции processAll .

Добавление функции управления

Теперь, когда у нас есть шаблон для класса управления, давайте создадим его функциональность. Прежде чем писать какой-либо код, давайте разберемся, что мы ожидаем от элемента управления. Элемент управления должен создать элемент списка данных на лету и прикрепить его к типу ввода (если вы хотите прочитать о новом элементе списка данных HTML5 , вы можете перейти по следующей ссылке ). Элемент управления также должен получить в качестве входных данных список параметров, который будет отображаться в виде списка автозаполнения. Итак, давайте напишем код:

(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();            
        },
            {
                //Private members
                _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);
                },

                //Public members
                element: {
                    get: function () {
                        return this._element;
                    }
                }
            })
    });
}(WinJS));

Как вы можете видеть, функция конструктора сначала проверяет, является ли элемент типом ввода. Он также устанавливает элемент и список опций, которые должны быть предоставлены в объекте опций. Последнее, что он делает, это создает элемент списка данных . В экземпляре объекта-члена вы разделяете функции и свойства на частный и публичный раздел-член. Это разделение является только логическим (и отмечено комментариями), и, как вы можете видеть, частные члены получают знак подчеркивания перед своим именем. Основная функциональность здесь является _createDataList функцией обработки создания DataList и устанавливает атрибут списка ввода типа в списке идентификаторы. Все остальные функции просты.

Использование элемента управления

Теперь, когда у нас есть контроль, давайте его использовать. В примере приложения я добавил файл data.js в папку js и написал в нем следующий код:

(function () {
    "use strict";

    WinJS.Namespace.define("Data", {
        cities: ["Seattle", "Las Vegas", "New York", "Salt lake City"]
    });
})();

Я мог получить любые данные из любого другого источника (облако, сервис, хранилище), но я хотел, чтобы пример был простым.

В файле home.html, расположенном в папке pages / home, я добавил тип ввода текста, который настраивается с помощью атрибутов 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, чтобы пример работал.

Теперь все настроено, и вы можете запустить приложение и увидеть результат:

Автозаполнение WinJS Custom Control

Полный пример можно скачать здесь .

Резюме

WinJS поставляется с множеством встроенных элементов управления, таких как FlipView, ListView ToggleSwitch и многие другие. С другой стороны, иногда необходимо создать свои собственные элементы управления. В этом посте вы узнали основы создания собственного пользовательского элемента управления WinJS.