Быстрое кроссплатформенное HTML5 приложение на Framework7

Задумываясь о разработке html5 приложения, многим сразу на ум приходит jQuery, или точнее jQueryMobile. И попробовав написать даже самое простенькое приложение используя jQueryMobile, очень легко разочароваться, так как производительность и отзывчивость получившегося html5 приложения куда ниже ожидаемого, и уж совсем его не сравнить с нативными приложениями.4c101889f2834db093c26515d747b12f.jpgСоответственно, если продолжить идти по пути html5, вы постепенно узнаёте, что тормоза и плохая отзывчивость из-за того, что есть множество тонкостей, например, что jquery далеко не самый быстрый вариант для приложения или по-умолчанию любое нажатие пользователя срабатывает с 300 мс задержкой, что ухудшает отзывчивость.Так же важным моментом является есть ли набор готовых типичный компонентов, таких как список, кнопки, боковое меню итд, время на повторную разработку которых нет смысла тратить. Можно добавить еще к этому списку то, что как-то всё таки нужно решить проблему производительности, чтобы конкурировать с нативными приложениями.

Framework7И мы, наконец, подходим к самому главное, чтобы не забивать себе голову решением таких проблем, а получить сразу готовый инструмент для разработки быстрых, отзывчивых и функциональных html5 приложений, существует Framework7. Сам я с ним столкнлся совершенно случайно, и удивился тому, насколько он прост в использовании без необходимости искать решения в разных местах, достаточно просто подключить framework7.js.Стоит отметить, что для работы с Framework7 не нужно использовать какие-то сторонние модули или библиотеки, так как он всё уже содержит:

High-performance Animation — хочется выделить это отдельно, так как анимации и правда очень быстрые fast-clicks — решает проблему задержки 300 мс без сторонних библиотек Template7 — движок шаблонов, синтаксис как у Handlebars, но меньше весит и скорость до 3х раз быстрее Dom7 — более быстрая и прозрачная замена jQuery Navigation / Router — множество вариантов переходов и их контроля Поддержка стилей, включая частичную поддержку material design Огромный список встроенных компонентов, таких как forms, buttons, list view, pull to refresh, infinite scroll, slide menu итд Свайпы — встроенные свайпы на все случаи жизни: вызвать меню свайпом, возврат к предыдущему экрану, удалить элемент итд И множество других полезных вещей На сайте есть огромное кол-во примеров (работают в браузере), инструкций и обучающих статей (например, работа Framework7 совместно с AngularJS)www.idangero.us/framework7Пример приложения aa53d1cc48b04de093e83ed04d2cd114.jpgЧтобы далеко не ходить, создадим небольшое приложение-пример, где можно будет посмотреть, как объединить отдельные компоненты фреймворка в единое приложение. Будем использовать slide menu, pull to refresh, infinite scroll, смену material/ios style на лету и огромный списком на 8000 элементов, который не тормозит (virtual list).

Структура приложения довольно простая:

index.html — дизайн приложения about.html — дизайн другого view app.js — файл инициализации и настроек приложения css/app.css — этот файл в общем-то не нужен, так как в framework7.css есть уже все настройки дизайна, но можно, например, сменить цвет фона бокового меню lib/framework7.js — сам фреймворк lib/framework7.css — дизайн всех элементов и компонентов в стиле ios lib/framework7.material.css — дизайн всех элементов и компонентов в стиле material Больше ничего не потребуется, другие библиотеки или фреймворки для создания приложения не нужны. Но при желании можно использовать requirejs, angularjs, matreshka.js итд.index.html Для начала рассмотрим каркас index.html: My App

Добавление компонентов очень просто реализовано (для каждого компонента есть инструкция на сайте), например, чтобы добавить pull-to-refresh, достаточно добавить в 
класс pull-to-refresh-content, и дизайн стрелочки, которая будет показываться при обновлении:
Теперь надо добавить table view (list view), в котором будет список наших элементов. Для создания коротких списков подойдет List View (Media List итд, список можно создавать статически или динамически):
    тут данные
Но для очень длинных списков требуется выгрузка элементов, которые сейчас не видны на экране, это необходимо для того, чтобы ничего не тормозило, и приложение работало как и нативное. Такий список называется Virtual List, и создается так же просто:
тут оставить пусто
В дальнейшем список надо будет проинициализировать и заполнить в app.jsСюда же добавим infinite-scroll, который добавляет так же, добавлением одноименного класса, дизайна крутилки и указанием начиная с какого расстояния вызывать infinite-scroll:

Чтобы сменить ios стиль на material стиль и наоборот, добавим 2 кнопки, например в левом меню:

Позже на класс changestyle повесим обработчик, чтобы реагировал на нажатие и менял css файл на указанный в rel. app.js Теперь рассмотрим файл app.js, в котором производится настройка приложения, инициализация списков итд. // Инициализируем движок фреймворка var myApp = new Framework7({ animateNavBackIcon: true, pushState: true, //при переходе между экранами, чтобы работала кнопка back на android modalTitle: «MyApp», modalButtonCancel: «Отмена», //текст Cancel кнопки swipePanel: 'left', //включаем левого меню свайпом });

// если запускается на ios, то кнопки back нету, и поэтому можно отключить if (Framework7.prototype.device.os == «ios») myApp.params.pushState = false; // вместо jQuery используем встроенный Dom7, переменную можно назвать $, чтобы было привычнее, но если оставить $$, то в дальнейшем можно будет легко подключить jQuery, если понадобится var $$ = Dom7;

// по клику меняем css файл, меняя ios и material стиль. Выбор запоминаем в localStorage, чтобы при перезапуске приложения загружался нужный css $$(».changestyle»).click (function () { $$(»#pagestyle»).attr («href»,$$(this).attr ('rel')); localStorage.setItem («css», $$(this).attr ('rel')); return false; });

// при первой загрузке загружаем запомненный css if (localStorage.getItem («css»)) { $$(»#pagestyle»).attr («href», localStorage.getItem («css»)); }

// инициализируем главную вьюху var mainView = myApp.addView ('.view-main', { dynamicNavbar: true, domCache: true, //чтобы навигация работала без сбоев и с запоминанием scroll position в длинных списках });

// инициализируем и заполняем вирутальный список используя шаблон (один из вариантов использования Template7) var myList = myApp.virtualList ('.list-block.virtual-list', { items: [ { id: 1, title: 'Item 1', picture: 'http://lorempixel.com/88/88/abstract/1' }, { id: 2, title: 'Item 2', picture: 'http://lorempixel.com/88/88/abstract/2' } ], height:44, template: '

  • ' + '' + '
    ' + '
    ' + '
    ' + '
    {{title}}
    ' + '
    ' + '
    ' + '
    ' + '
  • ' });

    // пример функции, которая будет обновлять содержимое виртуального списка function reloadTable (table, array) { table.items = array; table.update (); }

    // заполним виртуальный лист 20 новыми элементами var itemsArray = []; function firstInitList (text, count) { itemsArray = []; for (var i = 0; i < count; i++ ) { itemsArray.push({ id: i, title: text + ' ' + i, picture: 'http://lorempixel.com/88/88/abstract/' + i }); } }

    firstInitList («Item», 20); reloadTable (myList, itemsArray);

    // инициализируем pull-to-refresh var ptrContent = $$('.pull-to-refresh-content'); ptrContent.on ('refresh', function (e) { // Эмулируем 0.5секундную задержку setTimeout (function () { refreshIt (); }, 500); });

    // просто случайные данные для генерации виртуального листа var authors = ['Beatles', 'Queen', 'Michael Jackson', 'Red Hot Chili Peppers'];

    function refreshIt () { // первые 10 элементов создадим с надписью Refresh firstInitList («Refresh», 10); myList.deleteAllItems (); myList.appendItems (itemsArray);

    // остальные 8000 случайным образом var temparr = []; for (var i = 0; i<8000; i++) { var picURL = 'http://lorempixel.com/88/88/abstract/' + Math.round(Math.random() * 10); var author = authors[Math.floor(Math.random() * authors.length)]; temparr.push({ id: i, title: author, picture: picURL }); } myList.appendItems(temparr); myApp.pullToRefreshDone(); }

    // инициализируем infinite-scroll $$('.infinite-scroll').on ('infinite', function () { loadMore (); });

    // флаг var loading = false;

    //прячем крутилку infinite-scroll’а $$('.infinite-scroll-preloader').hide ();

    function loadMore () { // если уже загружаем данные, то ничего не делаем if (loading) return; $$('.infinite-scroll-preloader').show (); // Эмулируем 1 секундную задержку setTimeout (function () { for (var i = lastIndex + 1; i <= lastIndex + itemsPerLoad; i++) { itemsArray.push({ id: i, title: 'Item ' + i, picture: 'http://lorempixel.com/88/88/abstract/1' }); } reloadTable(myList, itemsArray); // сбрасываем флаг, после загрузки данных loading = true; }, 1000); } app.css // дизайн крутилки для infinite-scroll .infinite-scroll-preloader { margin-top:-20px; margin-bottom: 10px; text-align: center; } .infinite-scroll-preloader .preloader { width:34px; height:34px; } // сменим цвет фона navbar .navbar { border-bottom: none; background: #2196f3; color: #ffffff; } .navbar a.link { color: #ffffff; } // сменить цвет фона левого меню .panel, .left-menu .list-button { background-color: #3f4041; } .left-menu .item-link.list-button { text-align: left; } В итоге получается очень отзывчивое, легкое и быстрое html5 приложение, которое можно использовать как и где угодно.Ускоряем html5 приложения на старых версия android. Crosswalk Хоть у нас и получилось очень быстрое и легкое приложение, на старых версиях андроид оно всё равно будет недостаточно производительным.Дело в том, что на версиях андроид до 4.4 используется очень тормозной webview (убедится в этом можно, например, если на 4.1 андроид поставить chrome beta и запустить приложение в нём, а потом сравнить с тем, что есть во встроенном браузере, то разница в скорости будет очень заметна). Поэтому если просто запаковать html5 приложение в apk, оно будет использовать именно встроенный тормозной webview.Только начиная с 5.x андроида, webview обновляется отдельно и базируется на свежем chromium, благодаря чему html5 приложение будет работать быстро и плавно.

    Проще говоря, если нужна хорошая производительность от html5 приложения на любых устройствах и любых версиях андроид, нужно чтобы оно работало на chromium движке. Проект, который позволяет это сделать, называется crosswalk и вместо встроенного webview используется свой собственный, который работает на последней версии chromium.

    072a750601254d1d93a22b7c6445ccb9.jpg

    Самый простой способ проверить как ваше html5 приложение будет работать с использованием crosswalk, это установить Intel XDK, создать пустой «Standart HTML5» проект, и заменить в созданном проекте папку www на вашу. Чтобы грузились картинки с удаленных серверов, в файл intelxdk.config.additions.xml нужно добавить:

    После этого выбрать Build и нажать на Crosswalk for Android. Приложение будет скомпилировано на удаленном сервере, и спустя несколько минут вы получите ссылку на apk (версия для arm и x86). К минусам можно отнести тот факт, то размер приложения увеличится на ~19 мб.Сайт framework7: www.idangero.us/framework7Онлайн пример готового приложения: comedian-ant-73047.bitballoon.com (так как онлайн, то немного тормозит загрузка стилей)Исходники: yadi.sk/d/Quu2VfApgcGXAГотовые apk файлы, созданные через Intel XDK: yadi.sk/d/marrZA5-gcGuQ

    © Habrahabr.ru