Advertisement
  1. Code
  2. JavaScript

Создаем свое первое приложение NativeScript

Scroll to top
Read Time: 19 min

() translation by (you can also view the original English article)

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

  1. Настройка NativeScript
  2. Создание приложения
  3. Запуск приложения
  4. Отладка приложения

Мы будем специально запускать приложение на платформе Android. Но вы все равно можете следовать этой статье, если хотите развернуть приложение на iOS, поскольку код будет почти таким же. Единственные различия будут в процессе настройки NativeScript и команд, которые вы выполняете при запуске приложения.

Завершенный исходный код для этого приложения доступен на GitHub.

1. Настройка NativeScript

Чтобы настроить NativeScript, вам сначала нужно установить Node.js. После установки Node.js вы можете установить средство командной строки NativeScript, выполнив npm install -g nativescript в своем терминале.

Заключительный шаг - установить инструмент разработки для каждой платформы, в которой вы хотите развернуть ваше приложение. Для Android это Android SDK. Для iOS это XCode. Вы можете найти руководство по установке на веб-сайте NativeScript для получения более подробных инструкций по настройке необходимого программного обеспечения для вашей среды разработки.

После того, как вы настроили свою среду, запустите tns doctor, чтобы убедиться, что ваша среда готова для разработки NativeScript. Если вы работаете в Linux или Windows, вы увидите что-то вроде этого, если ваша среда готова:

1
NOTE: You can develop for iOS only on Mac OS X systems.
2
3
To be able to work with iOS devices and projects, you need Mac OS X Mavericks or later.
4
Your components are up-to-date.
5
6
No issues were detected.

Там есть заметка о том, что вы можете разрабатывать только для iOS только в системах Mac OS X. Это означает, что если вы находитесь на ПК, вы сможете использовать его только на устройствах Android. Однако, если вы находитесь на Mac, вы сможете развернуть свое приложение как на платформах iOS, так и на Android.

Если во время установки вы столкнулись с какими-либо проблемами, вы можете получить приглашение присоединиться к сообществу NativeScript Slack и после того, как вы присоединились к нему, перейдите на канал для начинающих и задайте свои вопросы там.

2. Создание приложения

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

Вот как выглядит приложение:

NativeScript appNativeScript appNativeScript app

Начните с выполнения следующей команды для создания нового проекта NativeScript:

1
tns create noter --appid "com.yourname.noter"

noter - это имя проекта, а com.yourname.noter - уникальный идентификатор приложения. Он будет использоваться позже, чтобы идентифицироать ваше приложение после его отправки в Play или App Store. По умолчанию команда tns create создаст для вас следующие папки и файлы:

  • app
  • node_modules
  • platforms
  • package.json

Обычно вам нужно использовать файлы только внутри каталога app. Но есть также случаи, когда вам может потребоваться отредактировать файлы внутри каталога platform/android. Один из таких случаев - это когда плагин, который вы пытаетесь использовать, не связывает автоматически зависимые и необходимые ему ресурсы.

Затем перейдите в каталог app и удалите все файлы, кроме папки App_Resources. Затем создайте следующие файлы:

  • app.js
  • app.css
  • notes-page.js
  • notes-page.xml

Это файлы, которые будут использоваться средой исполнения NativeScript. Так же, как при создании веб-страниц, файлы .css используются для стилизации а .js для функциональности. Но для разметки приложения мы используем XML вместо HTML. Обычно вы создаете отдельную папку для каждого экрана приложения (например, вход в систему, учетную запись или панель мониторинга) и файлы XML, CSS и JavaScript внутри каждой папки. Но поскольку это приложение имеет только один экран, мы создали все файлы в корневом каталоге.

Если вам нужна дополнительная информация о структуре каталогов NativeScript, ознакомьтесь с главой 2 руководства по началу работы с NativeScript.

3. Файл точки входа

Откройте файл app.js и добавьте следующий код:

1
var application = require("application");
2
application.start({ moduleName: "notes-page" });

Это точка входа для приложения NativeScript. Он использует модуль приложения и его метод start для указания модуля, используемого для начальной страницы приложения. В этом случае мы указали notes-page, что означает, что модуль - notes-page.js, разметка - notes-page.xml, а стиль для страницы - notes-page.css. Это соглашение, используемое в NativeScript, что все файлы для определенной страницы должны иметь одно и то же имя.

4. Добавление разметки пользовательского интерфейса

Откройте файл notes-page.xml и добавьте следующий код:

1
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded">
2
    <Page.actionBar>
3
  	<ActionBar title="{{ app_title }}">
4
			<ActionBar.actionItems>
5
                <ActionItem tap="newNote" ios.position="right" android.position="actionBar">
6
                    <ActionItem.actionView>
7
                        <StackLayout orientation="horizontal">
8
                            <Label text="New Item" color="#fff" cssClass="header-item" />
9
                        </StackLayout>
10
                    </ActionItem.actionView>
11
                </ActionItem>
12
			</ActionBar.actionItems>
13
		</ActionBar>
14
	</Page.actionBar>
15
16
    <StackLayout>
17
        <StackLayout id="form" cssClass="form-container">
18
            <TextView text="{{ item_title }}" hint="Title" />
19
            <Button text="Attach Image" cssClass="link label" tap="openCamera" />
20
            <Image src="{{ attachment_img }}" id="attachment_img" cssClass="image" visibility="{{ attachment_img ? 'visible' : 'collapsed' }}" />
21
            <Button text="Save Note" tap="saveNote" cssClass="primary-button" />
22
        </StackLayout>
23
          
24
        <ListView items="{{ notes }}" id="list" visibility="{{ showForm ? 'collapsed' : 'visible' }}">
25
            <ListView.itemTemplate>
26
                <GridLayout columns="*,*" rows="auto,auto" cssClass="item">
27
                    <Label text="{{ title }}" textWrap="true" row="0" col="0" />
28
                    <Image src="{{ photo }}" horizontalAlignment="center" verticalAlignment="center" cssClass="image" row="1" col="0" visibility="{{ photo ? 'visible' : 'collapsed' }}" />
29
                    <Button text="delete" index="{{ index }}" cssClass="delete-button" tap="deleteNote" row="0" col="1" horizontalAlignment="right" loaded="btnLoaded" />
30
                </GridLayout>
31
            </ListView.itemTemplate>
32
        </ListView>
33
    </StackLayout>
34
</Page>

При создании страниц приложения в NativeScript вы всегда должны начинать с тега <Page>. Так NativeScript знает, что вы пытаетесь создать новую страницу. Атрибут xmlns указывает URL-адрес схемы, используемой для файла XML.

Если вы укажете URL-адрес схемы, вы можете увидеть определение всех тегов XML, которые вы можете использовать в NativeScript. Атрибут loaded определяет функцию, которая будет выполняться после загрузки страницы. Мы рассмотрим это определение функции позже в файле notes-page.js.

1
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded">
2
 ...
3
</Page>

По умолчанию заголовок приложения содержит только название приложения. Если вы хотите добавить другие компоненты пользовательского интерфейса, вам нужно переопределить его, используя <Page.actionBar>. Затем внутри вы определяете вещи, которые хотите видеть в заголовке. Заголовок указывается с помощью <ActionBar> и установки его атрибута title на нужный заголовок страницы.

Ниже мы использовали синтаксис mustache для вывода значения app_title, определенного в файле notes-page.js. Вот как вы выводите значения, привязанные к странице.

1
<Page.actionBar>
2
    <ActionBar title="{{ app_title }}">
3
		...
4
   
5
	</ActionBar>
6
</Page.actionBar>

Чтобы определить кнопки, сначала используйте <ActionBar.actionItems> в качестве родителя, и каждый <ActionItem> будет кнопками, которые вы хотите определить. Атрибут tap указывает функцию, которая будет выполняться при нажатии кнопки, а os.position и android.position - позиции кнопки в iOS и Android.

Чтобы указать текст кнопки, вы можете использовать атрибут text у <ActionItem>. Однако NativeScript в настоящее время не позволяет изменять цвет текста кнопки через CSS. Вот почему вместо этого мы использовали <ActionItem.actionView>, чтобы определить содержимое кнопки и установить ее цвет текста.

1
<ActionBar.actionItems>
2
  <ActionItem tap="newNote" ios.position="right" android.position="actionBar">
3
    <ActionItem.actionView>
4
        <StackLayout orientation="horizontal">
5
          <Label text="New Item" color="#fff" cssClass="header-item" />
6
        </StackLayout>
7
    </ActionItem.actionView>
8
  </ActionItem>
9
</ActionBar.actionItems>

Далее - фактическое содержание страницы. Вы можете организовать различные элементы, используя один или несколько контейнеров макета. Ниже мы использовали два доступных макета: StackLayout и GridLayout.

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

С другой стороны, GridLayout позволяет упорядочивать элементы в структуре таблицы. Если вы когда-либо использовали Bootstrap или другие фреймворки CSS, такой подход должен показаться вам естественным. GridLayout позволяет вам определять строки и столбцы, среди которых может быть размещен каждый компонент пользовательского интерфейса. Мы рассмотрим, как это будет реализовано позже. Пока давайте перейдем к коду.

Сначала давайте определим форму для создания новой заметки. Как и в HTML, вы можете определить такие атрибуты, как id и cssClass (эквивалентно атрибуту class в HTML). Атрибут id прикрепляется к элементу, если вы хотите его обработать из кода. В нашем случае мы хотим анимировать форму. CssClass используется для указания класса CSS, который вы будете использовать для стилизации элемента.

Внутри формы находится текстовое поле для ввода названия заметки, кнопка для прикрепления изображения, выбранное изображение и кнопка для сохранения заметки. Элемент изображения отображается только в том случае, если файл attachment_img имеет правдивое значение. Это будет тот случай, если ранее изображение было прикреплено.

1
<StackLayout id="form" cssClass="form-container">
2
  <TextView text="{{ item_title }}" hint="Title" />
3
  <Button text="Attach Image" cssClass="link label" tap="openCamera" />
4
  <Image src="{{ attachment_img }}" id="attachment_img" cssClass="image" visibility="{{ attachment_img ? 'visible' : 'collapsed' }}" />
5
  <Button text="Save Note" tap="saveNote" cssClass="primary-button" />
6
</StackLayout>

Далее приведен список, который показывает заметки, которые уже были добавлены пользователем. Списки создаются с использованием компонента ListView. Он принимает items как обязательный атрибут. Значение может быть либо простым массивом, либо наблюдаемым массивом.

Если вам не нужно выполнять какую-либо форму обновления (например, удаление или обновление поля) каждому элементу массива, будет создан простой массив JavaScript. В противном случае используйте наблюдаемый массив, который позволяет выполнять обновления массива и автоматически отображать его в пользовательском интерфейсе. Мы рассмотрим, как определяется наблюдаемый массив позже.

Также обратите внимание, что ListView может иметь атрибут itemTap, который позволяет вам указать функцию, которая будет выполняться при прослушивании элемента в ListView. Но в этом случае мы не добавили его, так как нам не нужно выполнять какие-либо действия при прослушивании элемента.

1
<ListView items="{{ notes }}" id="list" visibility="{{ showForm ? 'collapsed' : 'visible' }}">
2
    ...
3
</ListView>

Элементы в ListView можно определить с помощью <ListView.itemTemplate>. Здесь мы используем <GridLayout> для создания двух строк и двух столбцов. Атрибут columns используется, чтобы указать, сколько столбцов вы хотите получить в каждой строке.

В этом случае *, * означает, что есть два столбца, каждый из которых занимает равное количество доступного пространства в текущей строке. Поэтому, если вся строка имеет общую ширину 300 пикселей, каждый столбец будет иметь ширину в 150 пикселей. Таким образом, в основном каждый * представляет один столбец, и вы используете запятую для разделения каждого из них.

Атрибут rows работает аналогично, но контролирует объем пространства, используемого одной строкой. Auto означает, что он будет использовать только пространство, необходимое для детей каждой строки.

После определения columns и rows в GridLayout вам все равно нужно указать, какой из его дочерних элементов принадлежит к какой строке и столбцу. Первая строка содержит заголовок элемента (1-й столбец) и кнопку удаления (второй столбец). Вторая строка содержит изображение, прикрепленное к элементу (1-й столбец). Строка и столбцы указаны с использованием атрибута row и col для каждого элемента.

Также обратите внимание на использование horizontalAlignment и verticalAlignment. Вы можете рассматривать их как эквивалент NativeScript атрибута text-align HTML. Но вместо текста мы выравниваем компоненты пользовательского интерфейса. HorizontalAlignment может иметь значение right, left, center или stretch, тогда как verticalAlignment может иметь значение top, bottom, center или stretch. Большинство из них очевидны, за исключением stretch  который растягивает элемент, чтобы занять доступное горизонтальное или вертикальное пространство.

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

1
<ListView.itemTemplate>
2
  <GridLayout columns="*,*" rows="auto,auto" cssClass="item">
3
    <Label text="{{ title }}" textWrap="true" row="0" col="0" />
4
    <Image src="{{ photo }}" horizontalAlignment="center" verticalAlignment="center" cssClass="image" row="1" col="0" visibility="{{ photo ? 'visible' : 'collapsed' }}" />
5
  
6
    <Button text="delete" index="{{ index }}" cssClass="delete-button" tap="deleteNote" row="0" col="1" horizontalAlignment="right" loaded="btnLoaded" />
7
  </GridLayout>
8
</ListView.itemTemplate>

Мы не указали атрибут itemTap для ListView. Вместо этого мы хотим добавить действие удаления, которое будет выполняться всякий раз, когда нажимается кнопка «Удалить» внутри элемента списка. Каждый элемент имеет атрибут index, который мы передаем как пользовательский атрибут кнопки удаления. Это уникальный ключ, используемый для идентификации каждого элемента, чтобы мы могли легко обращаться к ним, когда это необходимо.

Также обратите внимание на атрибут loaded. Так же, как <Page> имеет атрибут loaded, кнопки могут также иметь его. Вы увидите позже, как это используется.

5. Код JavaScript

Теперь мы готовы посмотреть на JavaScript, который заставляет все это работать. В этом разделе мы заполним файл notes-page.js.

Инициализация

Сначала мы импортируем модули data/observable и data/observablearray. Это встроенные модули в NativeScript, которые позволяют создавать наблюдаемые объекты и массивы. Наблюдения позволяют нам автоматически обновлять пользовательский интерфейс, когда эти объекты и массивы обновляются.

В нашем приложении pageArray используется для хранения массива заметок, а pageData используется для привязки его к странице. PageData также служит в качестве общего контейнера для всех данных, которые мы хотим показать в пользовательском интерфейсе.

1
var Observable = require("data/observable");
2
var ObservableArray = require("data/observable-array");
3
4
var pageArray = new ObservableArray.ObservableArray();
5
var pageData = new Observable.Observable({
6
    notes: pageArray
7
});

Затем импортируйте все другие модули, которые мы будем использовать на этой странице:

  • camera: для работы с камерой устройства.
  • view: для ссылки на конкретные элементы на странице. Рассматривайте его как эквивалент document.getElementById в NativeScript.
  • ui/enums: глобальный словарь постоянных значений для чего-либо, связанного с пользовательскими интерфейсами.
  • ui/animation: для анимации элементов.
  • application-settings: для постоянных локальных данных.
  • file-system: для работы с файловой системой.
1
var cameraModule = require("camera");
2
var view = require("ui/core/view");
3
4
var uiEnums = require("ui/enums");
5
var animation = require("ui/animation");
6
7
var appSettings = require("application-settings");
8
9
var fs = require("file-system");

Затем инициализируйте значения для переменных, которые будут использоваться во всем файле. page используется для хранения ссылки на текущую страницу, notesArr - это простая копия текущих заметок на странице, а current_index - это начальное значение индекса, которое используется как уникальный идентификатор для каждой заметки.

1
var page;
2
3
var notesArr = [];
4
5
var current_index = -1;

Функция pageLoaded()

Функции становятся доступными в контексте страницы с помощью exports. Ранее в файле notes-page.xml вы видели, что функция pageLoaded() выполняется при загрузке страницы.

1
exports.pageLoaded = function(args) {
2
    ...
3
}

Внутри функции pageLoaded() мы начнем с ссылки на страницу. Затем мы показываем форму для создания новой заметки и получаем текущие сохраненные значения нового названия заметки и примечаний из настроек приложения.

1
page = args.object;
2
pageData.set('showForm', true);
3
4
var new_note_title = appSettings.getString('new_note_title');
5
var notes = appSettings.getString('notes');

Затем, еще в функции pageLoaded(), проверьте, есть ли заметки, которые хранятся локально. Если нет, мы создаем массив заметок. Этот массив будет использоваться в качестве контента по умолчанию для новых пользователей приложения. Однако, если уже есть заметки, хранящиеся локально, мы конвертируем их в массив и затем переносим эти данные в наблюдаемый массив.

Обратите внимание, что перед тем, как мы добавляем элементы в наблюдаемый массив, мы сначала проверяем, пуст ли он. Мы должны это сделать, потому что использование модуля камеры выполняет событие loaded на странице еще раз после выбора изображения. Это означает, что если мы не будем осторожны, мы в конечном итоге будем тиражировать дубликаты в массив каждый раз, когда пользователь будет использовать камеру.

1
if(!notes){    
2
  notes = [
3
    {
4
      index: 0,
5
      title: '100 push ups'
6
    },
7
    {
8
      index: 1,
9
      title: '100 sit ups'
10
    },
11
    {
12
      index: 2,
13
      title: '100 squats'
14
    },
15
    {
16
      index: 3,
17
      title: '10km running'
18
    }
19
  ];
20
21
}else{
22
  notes = JSON.parse(notes);
23
}
24
25
notesArr = notes;
26
if(!pageArray.length){
27
  for(var x = 0; x < notes.length; x++){
28
    current_index += 1;
29
    pageArray.push(notes[x]);
30
  }
31
}

Теперь, когда у нас установлены данные заметок, мы можем обновить заголовок страницы, установив свой атрибут item_title на значение, полученное нами ранее из настроек приложения. Затем привяжите pageData к странице, чтобы пользовательский интерфейс автоматически обновлялся всякий раз, когда изменятся элементы, которые мы установили.

1
pageData.set('item_title', new_note_title);
2
args.object.bindingContext = pageData;

Анимируйте форму для создания новых заметок. Мы делаем это, используя функцию getViewById в view и передавая в контекст (текущую страницу) в качестве первого аргумента и атрибут id, назначенный элементу, который вы хотите изменить.

Затем вызовите функцию animate. Она принимает объект, содержащий настройки анимации. Здесь мы хотим, чтобы форма сместилась на 160 пикселей от исходного положения в течение 800 миллисекунд.

1
view.getViewById(page, 'form').animate({
2
    translate: { x: 0, y: 160 },    
3
    duration: 800,
4
});

Функция newNote()

Функция newNote() выполняется, когда пользователь нажимает на элемент действия New Item в заголовке. Это скрывает и показывает новый элемент ListView и перемещает форму вверх или вниз в зависимости от текущего значения showForm.

Если showForm имеет значение true, что означает, что в данный момент она отображается, мы изменяем прозрачность ListView до 1 в течение 400 миллисекунд, а затем убираем форму вверх, чтобы скрыть ее. В противном случае мы скроем ListView и сдвинем форму вниз.

1
exports.newNote = function() {
2
3
  var showForm = pageData.get('showForm');
4
  var top_position = (showForm) ? -160 : 160; 
5
  var list_visibility = (showForm) ? 1 : 0;
6
7
  view.getViewById(page, 'list').animate({
8
    opacity: list_visibility,
9
    duration: 400 
10
  });
11
12
  view.getViewById(page, 'form').animate({
13
      translate: { x: 0, y: top_position },    
14
      duration: 800,
15
  });
16
17
  pageData.set('showForm', !showForm);
18
}

Функция btnLoaded()

В файле notes-page.xml у нас есть атрибут loaded кнопки для удаления заметки. Это функция, которая выполняется, когда это событие происходит.

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

Код ниже является обходным путем для этого поведения по умолчанию. Он просто убирает фокус с кнопки удаления, так что вы все равно можете выполнять функцию, когда пользователь набирает элемент ListView. В этом случае нам действительно не нужен этот код, поскольку мы не назначили какие-либо функциональные возможности для кранов элементов, но это хороший инструмент для работы со списками.

1
exports.btnLoaded = function (args) {
2
  var btn = args.object;
3
  btn.android.setFocusable(false);
4
}

Функция openCamera()

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

Впоследствии мы можем запустить приложение камеры по умолчанию в устройстве, вызвав метод takePicture(). Этот метод принимает объект, содержащий настройки изображения. После того, как пользователь сделал снимок и нажал кнопку «Сохранить» на Android или кнопку «Использовать изображение» в iOS, обещание разрешается, и функция обратного вызова, переданная в then(), выполняется.

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

1
exports.openCamera = function() {
2
  appSettings.setString('new_note_title', pageData.get('item_title'));
3
  cameraModule.takePicture({width: 300, height: 300, keepAspectRatio: true}).then(function(img) {
4
  
5
    var filepath = fs.path.join(fs.knownFolders.documents().path, "img_" + (new Date().getTime() / 1000) + ".jpg");
6
    img.saveToFile(filepath, uiEnums.ImageFormat.jpeg);
7
    
8
    appSettings.setString('new_note_photo', filepath);
9
    pageData.set('attachment_img', filepath);
10
11
  });
12
}

Функция saveNote()

Функция saveNote() выполняется, когда пользователь нажимает кнопку «Сохранить примечание». Она получает текущее значение текстового поля заголовка заметки и пути изображения, увеличивает current_index и добавляет новый элемент в массив простых заметок и наблюдаемый массив примечаний. Затем он сохраняет текущие заметки и current_index в настройках приложения, удаляет значения для новой заметки из параметров приложения, обновляет пользовательский интерфейс, чтобы форма отображала пустое состояние и отображает список, скрывая форму примечания.

1
exports.saveNote = function() {
2
  
3
  var new_note_title = pageData.get('item_title');
4
  var new_note_photo = pageData.get('attachment_img');
5
6
  current_index += 1;
7
  var new_index = current_index;
8
 
9
  var new_item = {
10
    index: new_index,
11
    title: new_note_title,
12
    photo: new_note_photo,
13
    show_photo: false
14
  };
15
16
  notesArr.push(new_item);
17
  pageArray.push(new_item);
18
 
19
  appSettings.setString('notes', JSON.stringify(notesArr));
20
 
21
  appSettings.setNumber('current_index', new_index);
22
23
  appSettings.remove('new_note_title');
24
  appSettings.remove('new_note_photo');
25
26
  pageData.set('showForm', false);
27
  pageData.set('item_title', '');
28
  pageData.set('attachment_img', null);
29
  
30
  view.getViewById(page, 'list').animate({
31
    opacity: 1,
32
    duration: 400 
33
  });
34
35
  view.getViewById(page, 'form').animate({
36
      translate: { x: 0, y: -160 },    
37
      duration: 800,
38
  });
39
40
}

Функция deleteNote()

Наконец, у нас есть функция deleteNote(), которая запускается, когда пользователь нажимает кнопку удаления внутри элемента списка. Как вы уже видели из предыдущих функций, объект передается в качестве аргумента для функций, которые привязаны как обработчик событий для определенного компонента. Этот объект имеет свойство объекта, которое относится к самому компоненту.

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

1
exports.deleteNote = function(args){
2
  
3
  var target = args.object;
4
5
  var index_to_delete = notesArr.map(function(e) { 
6
    return e.index; 
7
  }).indexOf(target.index);
8
9
  notesArr.map(function(item, index){
10
11
    if(index == index_to_delete){
12
      notesArr.splice(index_to_delete, 1);
13
      pageArray.splice(index_to_delete, 1);
14
      return false;
15
    }
16
  });
17
18
  appSettings.setString('notes', JSON.stringify(notesArr));
19
}

6. Добавление стилей

Откройте файл app.css и добавьте следующие глобальные стили:

1
ActionBar {
2
    background-color: #b898ff;   
3
    color: #fff;
4
}
5
6
.header-item {
7
    text-transform: uppercase;
8
}
9
10
.item {
11
    padding: 20;
12
    font-size: 20px;
13
}
14
15
.form-container {
16
    background-color: #fff;
17
    margin-top: -160px;
18
    padding: 20px;
19
    z-index: 10;
20
}
21
22
.label {
23
    font-size: 18px;
24
}
25
26
.link {
27
    text-align: left;
28
    background-color: transparent;
29
    color: #0275d8;
30
    padding: 5px;
31
    margin: 10px 0;
32
    text-transform: uppercase;
33
    font-size: 15px;
34
}
35
36
.image {
37
    width: 300;
38
    margin: 20 0;
39
}
40
41
.primary-button {
42
    padding: 5px;
43
    color: #fff;
44
    background-color: #0723bb;
45
    text-transform: uppercase;
46
}
47
48
.delete-button {
49
    font-size: 15px;
50
    background-color: #f50029;
51
    color: #fff;
52
}

Если вы хотите применить стили, специфичные для страницы, вы также можете создать файл notes-page.css и определить свои стили там.

7. Запуск и отладка приложения

Вы можете запустить приложение на своем устройстве, выполнив tns run, а затем платформу, на которой вы хотите развернуть. Вот пример для Android:

1
tns run android

Это автоматически устанавливает платформу Android для вас, если она еще не установлена, а затем запускает приложение на вашем устройстве после его установки. После запуска приложения вы можете выполнить tns livesync android --watch, чтобы автоматически обновлять приложение каждый раз, когда вы вносите изменения в исходные файлы.

Отладка

Как и любой другой фреймворк, NativeScript позволяет разработчикам отлаживать свое приложение. Это делается с помощью инструментов Chrome dev. Это можно сделать двумя способами:

  1. Если приложение уже запущено, вы можете открыть новое окно терминала и выполнить tns debug android --start, чтобы прикрепить отладчик к текущему запущенному экземпляру приложения.
  2. Если у вас еще нет приложения, используйте tns debug android --debug-brk, чтобы создать экземпляр приложения с прикрепленным к нему отладчиком.

Независимо от того, какой вариант вы выберете, откроется новая вкладка в браузере Google Chrome, которая позволит вам отлаживать приложение, как обычное веб-приложение JavaScript. Это означает, что вы действительно можете использовать console.log в своем исходном коде для проверки содержимого переменных, с которыми вы работаете.

Заключение и последующие шаги

В этой статье вы узнали, как создать приложение с помощью NativeScript. В частности, вы изучили такие концепции, как использование компонентов пользовательского интерфейса, макеты, стилизация, анимация, использование камеры устройства и поддержание состояния приложения с настройками приложения.

Теперь, когда вы создали свое первое приложение NativeScript, пришло время еще раз проявить свои навыки, проверив, что еще вы можете сделать с NativeScript и создать с ним еще несколько приложений.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.