Статьи

Как приготовить полное приложение для Windows 8 с HTML5, CSS3 и JavaScript за неделю: день 5


Выпуск Windows 8 Release Preview (RP) вышел, и вы можете скачать его здесь:

http://windows.microsoft.com/en-US/windows-8/release-preview

Тогда очевидно, что я должен перенести моего маленького UrzaGatherer для предварительного просмотра.

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

С полной версией можно ознакомиться здесь:
http://www.catuhe.com/MSDN/urza/day5.zip

Ну и конечно же все предыдущие эпизоды:

Портирование в Release Preview

Чтобы помочь вам перенести собственное приложение, мы (в Microsoft) выпустили отличный документ:
http://go.microsoft.com/fwlink/?LinkId=251943

Кроме того, я предлагаю вам прочитать следующий блог, где команда разработчиков Windows 8 рассказывает о различиях между CP и RP:
http://blogs.msdn.com/b/windowsappdev/archive/2012/05/31/what-s -Изменен-для-приложения-разработчиков-Since-на-потребительского preview.aspx

С моей точки зрения, вот основные проблемы, с которыми я столкнулся:

Новый навигатор.js

Первый момент касается файла navigator.js, в который я добавил несколько интересных новинок.

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

_navigated: function (args) {
    var that = this;
    var newElement = that._createPageElement();
    var parentedComplete;
    var parented = new WinJS.Promise(function (c) { parentedComplete = c; });

    args.detail.setPromise(
        WinJS.Promise.timeout().then(function () {
            if (that.pageElement.winControl && that.pageElement.winControl.unload) {
                that.pageElement.winControl.unload();
            }
            return WinJS.UI.Pages.render(args.detail.location, newElement, args.detail.state, parented);
        }).then(function parentElement(control) {
            that._previousPage = newElement.winControl;
            that.element.appendChild(newElement);
            that.element.removeChild(that.pageElement);

            parentedComplete();

            var offset = { top: "0px", left: "50px" };
            var enterPage = WinJS.UI.Animation.enterPage(newElement, offset);
            enterPage.then(function () {
                document.body.focus();
                that.navigated();

                setImmediate(function () {
                    if (that._previousPage.afterPageEnter) {
                        that._previousPage.afterPageEnter(newElement);
                    }
                });
            });
        })
    );
},

Полный новый файл navigator.js доступен здесь:
http://www.catuhe.com/MSDN/Urza/Navigator.zip

Страница по умолчанию

Теперь первая страница вашего проекта должна выглядеть примерно так:

(function () {
    "use strict";

    var app = WinJS.Application;
    var nav = WinJS.Navigation;
    var ui = WinJS.UI;

…
    app.onactivated = function (eventObject) {
        if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch ||
            eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.search ||
            eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.fileOpenPicker) {

            eventObject.setPromise(WinJS.UI.processAll().then(function () {
                WinJS.Resources.processAll().then(function () {


…
                    if (nav.location) {
                        nav.history.current.initialPlaceholder = true;
                        return nav.navigate(nav.location, nav.state);
                    } else {
                        return nav.navigate(UrzaGatherer.navigator.home);
                    }
                });
            }));
        }
    };

    app.oncheckpoint = function (args) {
    };

    app.start();
})();

Активация приложения теперь обрабатывается обещанием, представленным аргументом события onactivation . Навигация также запускается вашим кодом с помощью функции nav.navigate .

Многомерный список просмотра

Другим важным моментом является новый способ, используемый для определения многомерных списков.

listView.layout= new ui.GridLayout({
        groupInfo: function () {
            return {
                enableCellSpanning: true,
                cellWidth: 28,
                cellHeight: 13
            };
        }
    });

Это новое наименование было создано для того, чтобы подчеркнуть тот факт, что каждый элемент должен иметь пропорциональный размер относительно указанного размера ячейки ( cellWidth / cellHeight ).

Обходной путь ошибки Semantic Zoom

Release Preview не является окончательной версией, поэтому могут быть найдены небольшие ошибки.

Один из них было действительно трудно исправить, поэтому я решил поделиться с вами решением Sourire

На главной странице присутствует семантический зум. При определенных обстоятельствах (связанных с мощностью компьютера) базовый listView просто не отображается. Очевидно, что это не воспроизводится в режиме отладки (круто!) И не каждый раз (опять круто!).

После целого дня борьбы я, наконец, нашел обходной путь: после настройки источников данных, вам просто нужно снова запустить процесс компоновки семантического управления масштабированием:

var zoomedListView = element.querySelector(".zoomedList").winControl;

var groupDataSource = UrzaGatherer.ExpansionsListWithCardOfTheDay.createGrouped(
                  this.groupKeySelector, this.groupDataSelector, this.groupCompare);

listView.itemDataSource = groupDataSource.dataSource;
listView.groupDataSource = groupDataSource.groups.dataSource;
zoomedListView.itemDataSource = groupDataSource.groups.dataSource;

if (onlyOnce)
    element.querySelector(".zoomControl").winControl.forceLayout();

Обратите внимание на использование переменной onlyOnce, чтобы быть уверенным, что вы применяете патч только в первый раз.

Волшебство setImmediate

Последним важным моментом этой миграции является понимание функции setImmediate (или msSetImmediate ):
http://msdn.microsoft.com/en-us/library/windows/apps/hh453394.aspx

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

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

Чтобы учесть эту проблему, я обновил файл navigator.js , чтобы изменить обработчик нажатия кнопки «Назад»:

if (backButton) {
    backButton.onclick = function () {
        setImmediate(function () {
            nav.back();
        });
    };

    if (nav.canGoBack) {
        backButton.removeAttribute("disabled");
    } else {
        backButton.setAttribute("disabled", "disabled");
    }
}

 Другой пример можно найти в коде, используемом для прокрутки:

setImmediate(function () {
    if (currentIndex)
        listView.indexOfFirstVisible = currentIndex;
}); 

Добавление привязки с WinJS.Binding.as

Я не охватывал привязку данных в предыдущих эпизодах. Это действительно важный момент, и, наконец, я широко использовал его в UrzaGatherer.

Например, я хотел добавить случайную карту на главном экране, и я хотел менять карту каждые две минуты:

image_thumb9

Для этого я создал список привязок со всеми расширениями. Я добавил в этот список конкретный объект, используемый для представления случайной карты.

Чтобы сделать эту карту привязываемой (я имею в виду: каждое изменение, примененное к карте, автоматически синхронизируется с пользовательским интерфейсом), это действительно просто, потому что вам просто нужно использовать класс WinJS.Binding.as :

var bindableCard = new WinJS.Binding.as(card);
 expansion.cardsList.push(bindableCard);

Using this class, you create a completely bindable object.

<div class="cardOfTheDayTemplate" data-win-control="WinJS.Binding.Template">
    <div class="card-image-container" data-win-control="UrzaGatherer.Tools.DelayImageLoader"
        data-win-options="{root: 'cards'}">
        <img class="card-image" data-win-bind="src: url" src="#" />
    </div>
    <div class="card-overlay">
    </div>
    <h4 class="card-title" data-win-bind="textContent: name"></h4>
    <div class="item-border">
    </div>
    <div class="item-check" 
        data-win-bind="style.display: card.isChecked UrzaGatherer.Tools.BoolToDisplayConverter">
        <div class="checkBackground"></div>
        <div class="checkmark"></div>
    </div>
</div>

 Все основано на данных-win-bind . Шаблоны, используемые списками, полностью совместимы с этим объектом, и когда свойство объекта изменяется, пользовательский интерфейс отвечает автоматически (как в XAML !!):

var updateCardOfTheDay = function () {
    var card;

    do {
        var cardNumber = Math.floor(Math.random() * cards.length);
        card = cards[cardNumber];
    }
    while (card.size.isPlane);

    if (cardOfTheDayBinding.element) {
        WinJS.Utilities.query("img", cardOfTheDayBinding.element).forEach(function (img) {
            WinJS.Utilities.removeClass(img, "loaded");
        });
    }

    cardOfTheDayBinding.url = card.logo;
    cardOfTheDayBinding.name = card.name;
    cardOfTheDayBinding.card = card;
}

Благодаря этой превосходной технологии я решил обновить все свои шаблоны. Так, например, когда пользователь выбирает использование локальных или удаленных файлов, мне просто нужно изменить соответствующие свойства моих объектов:

var updateBlockOfflineState = function (block, offline) {
            if (offlineMode) {
               block.logo = "ms-appdata:///local/blocks/" + block.name.replace(":", "_") + ".png";
               block.banner = "ms-appdata:///local/blocks/" + block.name.replace(":", "_") + "_banner.png";
            }
            else {
               block.logo = root + "/blocks/" + block.name.replace(":", "_") + ".png";
               block.banner = root + "/blocks/" + block.name.replace(":", "_") + "_banner.png";
            }
    }

image_thumb6

Это оно!!

Это оно! Вы сделали. Приложение можно опубликовать в магазине (уже сделано для UrzaGatherer: http://apps.microsoft.com/webpdp/app/urzagatherer/92adce33-8490-4af7-9392-9c35c91d8a37 ).

Теперь не стесняйтесь использовать мои учебники в качестве основы для вашего проекта. Вы почти готовы сейчасClignement d'œil