Создание мобильных приложений с Cordova и Vue.js

Разработка /
Разработка: Создание мобильных приложений с Cordova и Vue.js

Cordova это фреймворк, с которым вы можете создавать мобильные приложения с использование веб-технологий, таких как HTML, Javascript и CSS. Это позволяет создавать приложения сразу для нескольких платформ (к примеру, на Android и iOS) с общей кодовой базой. Несмотря на то, что вам всё ещё нужны платформо-зависимые технологии, типа Android SDK и XCode для сборки, вы можете создавать приложения без использования нативного Android- или iOS-кода.

А так как наш код это HTML и Javascript, мы легко можем использовать любимые Javascript библиотеки вроде Vue.js с Cordova.

И сегодня мы рассмотрим пример создания мобильного приложения с Cordova и Vue.js.

Исходный код проекта можно взять здесь.

Подготовка

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

  • Скачайте Node.js
  • Установите Cordova: npm install -g cordova
  • Ознакомьтесь с основами Vue.js

Создание проекта Cordova

Создадим проект и назовём его RandomWord:

cordova create RandomWord
cd RandomWord

Это создаст иерархию директорий:
Разработка: Создание мобильных приложений с Cordova и Vue.js

  • config.xml — содержит информацию о приложении, используемых плагинах и платформах
  • platforms — содержит библиотеки Cordova для целевых платформ, на которых приложение будет запущено
  • plugins — содержит библиотеки плагинов Cordova, используемые в приложении. Они предоставляют приложению доступ к устройству: к камере, состоянию батареи и т.п.
  • www — содержит исходный код приложения на HTML, Javascript и CSS
  • hooks — содержит скрипты для настройки системы сборки приложения

Добавим платформу Android:

cordova platform add android --save

Эта команда добавит библиотеку платформы Android в папку platforms (platforms/android).

...
    <engine name="android" spec="~5.2.1" />
</widget>

Проверим установленные зависимости для сборки/запуска приложений Android с Cordova:

cordova requirements


Собираем наше приложение под Android:

cordova build android

Подключите ваш телефон к компьютеру и запустите приложение:

cordova run android

Если не подключать устройство, Cordova запустит приложение в эмуляторе. Наше приложение пока лишь показывает картинку и надпись:
Разработка: Создание мобильных приложений с Cordova и Vue.js

Для построения приложения под iOS нужно выполнить те же шаги, заменив в командах android на ios. Также есть вариант использовать ваш браузер вместо мобильного устройства, установив платформу browser.

Изменим немного файл config.xml:

<?xml version='1.0' encoding='utf-8'?>
<widget id="io.coligo.randomword" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>RandomWord</name>
    <description>
        A mobile app for generating a random word.
    </description>
    <author email="michaelviveros@gmail.com" href="http://www.michaelviveros.com/">
        Michael Viveros
    </author>
    ...


Добавляем Vue.js

Добавим Vue.js CDN в конец файла www/index.html:

...
        <script type="text/javascript" src="cordova.js"></script>
        <script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>


Для того, чтобы приложение могло вызывать библиотеку Vue.js, добавим строчку в конец мета-тега Content Security Policy (CSP) в www/index.html:

; script-src 'self' http://cdn.jsdelivr.net/vue/1.0.16/vue.js 'unsafe-eval'

CSP позволяет создать список разрешённых источников и разрешает браузеру обрабатывать контент только из этих источников.

Часть мета-тега CSP script-src отвечает за то, откуда будут браться скрипты, исполняемые нашим приложением.
  • ’self’ — разрешены скрипты только из этого же источника, например, www/js/index.js
  • cdn.jsdelivr.net/vue/1.0.16/vue.js — разрешена библиотека Vue.js
  • ’unsafe-eval’ — разрешено выполнение небезопасного кода, так как некоторый код из Vue.js использует строки для генерации функций
Мета-тег CSP должен выглядеть так:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; script-src 'self' http://cdn.jsdelivr.net/vue/1.0.16/vue.js 'unsafe-eval'">

После замены кода в теле www/index.html некоторым кодом Vue.js, этот файл должен стать таким:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; script-src 'self' http://cdn.jsdelivr.net/vue/1.0.16/vue.js 'unsafe-eval'">
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Random Word</title>
    </head>
    <body>
        <div id="vue-instance" class="app">
            <h1>Random Word</h1>
            <button id="btn-get-random-word" @click="getRandomWord">Get Random Word</button>
            <p>{{ randomWord }}</p>
        </div>
        <script type="text/javascript" src="cordova.js"></script>
        <script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

Теперь добавим немного Javascript для генерации и вывода случайного слова.

В www/js/index.js уже есть код, он может сменить цвет фона или заголовок, при получении приложением события deviceready. И нам не нужно пока лезть в эти методы. Однако, попробуйте сами разобраться с методом bindEvents для выполнения различных действий на различных этапах жизненного цикла приложения.

Мы добавим новый метод в файл www/js/index.js, назовём его setupVue, он будет создавать новый объект Vue и привязывать его к блоку random word. Новый объект Vue будет содержать метод getRandomWord, извлекающий случайное слово из списка слов при нажатии кнопки Get Random Word.

var app = {
    initialize: function() {
        this.bindEvents();
        this.setupVue();
    },
    ...
    setupVue: function() {
        var vm = new Vue({
            el: "#vue-instance",
            data: {
                randomWord: '',
                words: [
                    'formidable',
                    'gracious',
                    'daft',
                    'mundane',
                    'onomatopoeia'
                ]
            },
            methods: {
                getRandomWord: function() {
                    var randomIndex = Math.floor(Math.random() * this.words.length);
                    this.randomWord = this.words[randomIndex];
                }
            }
        });
    }
};

app.initialize();


После удаления ненужного кода, файл www/js/index.js будет таким:

var app = {
    initialize: function() {
        this.bindEvents();
        this.setupVue();
    },
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    receivedEvent: function(id) {
        console.log('Received Event: ' + id);
    },
    setupVue: function() {
        var vm = new Vue({
            el: "#vue-instance",
            data: {
                randomWord: '',
                words: [
                    'formidable',
                    'gracious',
                    'daft',
                    'mundane',
                    'onomatopoeia'
                ]
            },
            methods: {
                getRandomWord: function() {
                    var randomIndex = Math.floor(Math.random() * this.words.length);
                    this.randomWord = this.words[randomIndex];
                }
            }
        });
    }
};

app.initialize();


Соберём приложение, подключим телефон и запустим:

cordova build android
cordova run android


Приложение теперь выглядит примерно так:
Разработка: Создание мобильных приложений с Cordova и Vue.js

HTTP запросы с vue-resource

Вместо того, чтобы использовать заданный список слов в нашем приложении, используем для этого специальный веб-сервис, например, этот: Wordnik Random Word API

В конец мета-тега CSP добавьте следующий код для разрешения работать с этим ресурсом:

; connect-src http://api.wordnik.com:80/v4/words.json/randomWord

В connect-src мы указали приложению, куда разрешено делать http-запросы.

Добавим библиотеку vue-resource для создание таких запросов.

index.html немного изменится:

<!DOCTYPE html>
...
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; script-src 'self' http://cdn.jsdelivr.net/vue/1.0.16/vue.js https://cdn.jsdelivr.net/vue.resource/0.7.0/vue-resource.min.js 'unsafe-eval'; connect-src http://api.wordnik.com:80/v4/words.json/randomWord">
...
        <script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>
        <script src="https://cdn.jsdelivr.net/vue.resource/0.7.0/vue-resource.min.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

Отредактируем файл www/js/index.js для использования веб-сервиса:

...
    setupVue: function() {
        var vm = new Vue({
            el: "#vue-instance",
            data: {
                randomWord: ''
            },
            methods: {
                getRandomWord: function() {
                    this.randomWord = '...';
                    this.$http.get(
                        'http://api.wordnik.com:80/v4/words.json/randomWord?api_key=a2a73e7b926c924fad7001ca3111acd55af2ffabf50eb4ae5'
                    ).then(function (response) {
                        this.randomWord = response.data.word;
                    }, function (error) {
                        alert(error.data);
                    });
                }
            }
        });
    }
};

app.initialize();

Соберём и запустим приложение:

cordova build android
cordova run android

Приложение выглядит как раньше, однако слова берутся уже с помощью Random word API.

Компоненты Vue

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

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

Так должна выглядеть структура папок после добавления Vue Component:
Разработка: Создание мобильных приложений с Cordova и Vue.js
Создадим компонент, вызывающий наш метод получения слова в www/js/random-word.vue:

<template>
  <div class="app">      
    <h1>Random Word</h1>
    <button id="btn-get-random-word" @click="getRandomWord">Get Random Word</button>
    <p>{{randomWord}}</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      randomWord: ''
    }
  },
  methods: {
    getRandomWord: function() {
        this.randomWord = '...';
        this.$http.get(
            'http://api.wordnik.com:80/v4/words.json/randomWord?api_key=a2a73e7b926c924fad7001ca3111acd55af2ffabf50eb4ae5'
        ).then(function (response) {
            this.randomWord = response.data.word;
        }, function (error) {
            alert(error.data);
        });
    }
  }
}
</script>

Разметка HTML из файла www/index.html теперь находится в теге template, а Javascript код из www/js/index.js находится в теге script файла random-word.vue.

Создадим новый объект Vue, содержащий этот компонент в новом файле www/js/main.js:

var Vue = require('vue');
var VueResource = require('vue-resource');
var RandomWord = require('./random-word.vue');

Vue.use(VueResource);

var vm = new Vue({
  el: 'body',
  components: {
    'random-word': RandomWord
  }
});


Для склеивания компонентов мы используем browserify и vueify для создания файла bundle.js. Создадим новую папку scripts и в ней файл vueify-build.js.

scripts/vueify-build.js будет таким:

var fs = require('fs');
var browserify = require('browserify');
var vueify = require('vueify');

browserify('www/js/main.js')
  .transform(vueify)
  .bundle()
  .pipe(fs.createWriteStream('www/js/bundle.js'))

Раньше мы вызывали библиотеки Vue.js с CDN в www/index.html, но сейчас www/js/main.js использует javascript для этого. Создадим файл package.json для синхронизации всех зависимостей:

{
  "name": "random-word",
  "version": "1.0.0",
  "description": "A mobile app for generating a random word",
  "main": "index.js",
  "dependencies": {
    "browserify": "~13.0.1",
    "vue": "~1.0.24",
    "vue-resource": "~0.7.4",
    "vueify": "~8.5.4",
    "babel-core": "6.9.1",
    "babel-preset-es2015": "6.9.0",
    "babel-runtime": "6.9.2",
    "babel-plugin-transform-runtime": "6.9.0",
    "vue-hot-reload-api": "2.0.1"
  },
  "author": "Michael Viveros",
  "license": "Apache version 2.0"
}


Установить все зависимости проекта теперь можно одной командой:

npm install

Добавим хук в конец файла config.xml, чтобы Cordova знала о необходимости склеивания компонента перед сборкой приложения:

...
    <hook type="before_compile" src="scripts/vueify-build.js" />
</widget>

Мы помним, что scripts/vueify-build.js создаст собранный компонент и положит его в www/js/bundle.js

Добавим вызов компонента в тело www/index.html, создав тег random-word и тег script, вызывающий наш склеенный ранее компонент.

...
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Random Word</title>
    </head>
    <body>
        <random-word></random-word>
        <script src="js/bundle.js"></script>

        <script type="text/javascript" src="js/index.js"></script>
        <script type="text/javascript" src="cordova.js"></script>
    </body>
</html>


Помните, что тег link в www/index.html задаёт CSS приложения, а тег div в www/js/random-word.vue использует класс «app» из CSS.

Поскольку мы перенесли логику в другое место, теперь мы можем удалить метод setupVue из www/js/index.js:

var app = {
    initialize: function() {
        this.bindEvents();
    },
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    receivedEvent: function(id) {
        console.log('Received Event: ' + id);
    }
};

app.initialize();

Соберём и запустим приложение:

cordova build android
cordova run android


Заключение

Разрабатывать мобильные приложения с Cordova очень просто. А с Vue.js вы можете использовать огромное количество её функций в мобильных приложениях.

Написано по материалам Building a Mobile App with Cordova and Vue.js by Michael Viveros
0 комментариев
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.