Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. NativeScript
Code

创建你的第一个NativeScript应用程序

by
Difficulty:BeginnerLength:LongLanguages:

Chinese (Simplified) (中文(简体)) translation by Laura Kick (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, 你就可以在终端上执行 npm install -g nativescript 来安装 NativeScript 命令行工具。

最后步骤是为你想要部署的每个平台安装开发工具。对于 Android 来说是 Android SDK,对于 iOS 则是 XCode。 你可以依照 NativeScript 网站上的安装指南, 获取如何为开发环境设置必要软件的详细说明。

建立好开发环境之后, 执行 tns doctor 以确保你的环境做好开发 NativeScript 的准备。在 Linux 或 Windows 上, 当环境已就绪时, 你将会看到像下面的信息: 

这个说明提示了你只能用 Mac OS X 系统开发 iOS 应用。也就是说, 如果在个人电脑上开发, 你只能部署到 Android 设备。 但如果在 Mac 环境开发, 你就同时能部署到 iOS 和 Android 平台上。

如果在设置过程中遇到任何问题, 你可以得到加入 NativeScript Slack 社区的邀请。加入后, 请转到 getting started 频道并在那里询问你的问题。

2.创建应用程序

我们将要构建一个笔记应用程序。它允许用户创建笔记, 每份笔记都可选择附加一张由设备摄像头捕获的图像。 笔记内容通过 NativeScript 应用程序设置来保存, 并且可以单独删除。

这里是应用程序的外观:

NativeScript app

首先执行以下命令创建新的 NativeScript 项目:

noter 是项目的名称,而 com.yourname.noter 则是应用程序的独一 ID。在你提交到游戏或应用商店后,这将用来标识你的应用程序。 默认情况下 tns create 命令将为你创建以下的文件夹和文件:

  • app
  • node_modules
  • platforms
  • package.json

通常你只会接触到 app 目录中的文件。但在某些情况下, 你可能会需要编辑 platforms/android 目录中的文件。 像是你想用的plugin并没有自动连接到它需要的依赖和资产的时候。

接下来, 浏览到 app 目录并删除 App_Resources 文件夹以外的所有文件。然后创建下列文件:

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

NativeScript 运行时将使用这些文件。就如同构建网页时, css 文件用于样式设置和. js 文件用于添加功能那样。 但应用程序的标记语言, 我们使用了 XML 而非 HTML。通常你会为应用程序的每个屏幕创建一个单独的文件夹 (例如, 登录、注册或仪表板), 并在每个文件夹中有各自的 XML、CSS 和 JavaScript 文件。 但由于这个应用程序只有一个屏幕, 我们在根目录中创建所有的文件。

如果你需要更多关于 NativeScript 目录结构的详细信息, 请查阅 NativeScript Getting Started Guide 的第 2章

3.进入点文件

打开 app.js 文件并添加以下代码:

这里是 NativeScript 应用程序的进入点。它使用了 application 模块和它的 start 方法来指定应用程序初始页面所用的模块。 在本例中, 我们指定了 notes-page, 表示该模块是 notes-page.js, 标记是 notes-page.xml, 而页面的样式是 notes-page.css。 这是 NativeScript 的惯用模式, 即一个特定页面的所有文件都必须要有相同的名称。

4.添加 UI 标记

打开 notes-page.xml 文件并添加以下代码:

每当在 NativeScript 中创建应用程序页面时, 都应该以 <Page> 标记开始。这是让 NativeScript 知道你正在尝试创建新页面的方式。xmlns 属性指定了 XML 文件架构的 URL。

如果你去访问所指定的架构 URL, 会看到所有在 NativeScript 中可使用的 XML 标记的定义。 loaded 属性用于指定页面加载后要执行的函数。稍后, 我们将在 notes-page. js 文件中查看此函数定义。

默认情况下, 应用程序标题栏只包含应用程序的标题。如果想要添加其他 UI 组件, 你需要用 <Page.actionBar> 来重新定义。 在那里面定义你想要在标题栏上看到的内容。通过设置 <ActionBar> 的 title 属性来指定你想要的页面标题。

下面我们使用了 mustache 语法输出在 notes-page.js 文件中定义的 app_title 值。这就是如何输出绑定于页面的值的方法。

若要定义按钮, 请先使用 <ActionBar.actionITems> 作为父级, 而每个 <ActionItem> 就是你想定义的按钮。tap 属性 指定了按钮被点击时需要执行的函数, 而 os.positionandroid.position 分别为 iOS 及 Android 系统中按钮的位置。

若要指定按钮文本, 你可以使用 <ActionItem> 的 text 属性。然而 NativeScript 当前不允许通过 CSS 更改按钮的文本颜色。 这就是为什么我们得另外用 <ActionItem.actionView> 来定义按钮的内容以及设置其文本颜色。

接下来是实际的页面内容。你可以使用一或多个布局容器来排列各种不同的元素。下面我们使用了两个可用的布局: StackLayoutGridLayout

StackLayout 允许你堆叠其内部的所有元素。默认情况下, 此布局的方向是垂直的, 因此每一个 UI 组件都堆叠在上一个组件之下。想象一下乐高积木往下堆叠的样子。

另一方面, GridLayout 允许你在表格结构中排列元素。如果你曾经使用过 Bootstrap 或其他 CSS 网格框架, 对你来说应该很自然。 GridLayout 允许你定义行和列,在其中可放置 UI 组件。之后我们将看看如何实现这一点。现在让我们先转回到代码。

首先, 我们定义用于创建新笔记的窗体。就像在 HTML 中一样, 你可以定义如idcssClass(等同于HTML 的class属性) 等属性。 如果要从代码中操作, 请记得id属性是联结到元素上面。在我们的例子中, 我们希望稍后对窗体加入动画效果。cssClass指定了用于样式元素的 CSS 类。

窗体里面有用于输入筆記标题的文本框、附加图像的按钮、被选取的图像以及用于保存筆記的按钮。 只有当attachment_img 值为 truthy 时, 图像元素才会显现。这是在之前有附加图像时才会发生的情况。

接着是显示用户已添加的笔记列表。我们使用ListView组件创建列表。它接受items作为必需的属性。该值可以是普通数组或监控数组。

如果你不需要对数组中的每个项执行任何形式的更新 (如删除或更新字段) , 一个普通的 JavaScript 数组就能胜任。 否则, 请使用监控数组,对于该数组的任何更新, 都会自动反映到 UI 中。稍后我们将看看如何定义一个监控数组。

另外请注意到ListView可以有一个itemTap属性, 它允许你指定点击ListView时要执行的函数。但在这里, 我们还没有真正添加, 因为我们不需要在项目被点击时执行任何操作。

我们可以用<ListView.itemTemplate>来定义ListView中的项。在这里, 我们使用<GridLayout>创建两个行和两个列。columns属性用于指定每行中所你想要的列数。

在本例中 *,* 表示有两列, 每一列占用了当前行中可用空间的一半。 因此, 如果整行的总宽度为300像素, 则每列将为150像素宽。所以基本上每个 * 代表一列, 并使用逗号分隔它们。

rows 属性的工作方式类似, 但它控制单行所使用的大小。auto 表示它只会占用每行的子级所需要之大小。

GridLayout 中定义了columnsrows之后, 你还必须指定其子项各属于哪个行跟列。第一行包含该项目的标题 (第一列) 和 "删除" 按钮 (第二列)。 第二行包含附加到该项的图像 (第一列)。行和列是用每个元素的 rowcol 属性来指定的。

还要注意horizontalAlignmentverticalAlignment的使用。你可以将它们视为跟 HTML 的text-align属性等效的 NativeScript 属性。 和文本不同的是, 我们是对齐 UI 组件。horizontalAlignment的值可以为 right, left, centerstretch。而verticalAlignment的值可以为 top, bottom,  centerstretch。 这些值大多数都是不言而喻的, 而stretch值指示 UI 组件延伸以占满可用的水平或垂直空间。

在本例中,我们设定horizontalAlignmentverticalAlignment让图像在列里水平和垂直居中。而 horizontalAlignment 在 "删除" 按钮上使用, 使它与第二列的最右边对齐。

目前我们还没有指定ListViewitemTap属性。相反地, 我们希望附加一个删除操作, 只要点击列表项中的 "删除" 按钮就会执行。 每个项目都有一个index属性, 我们将它作为 "删除" 按钮的自定义属性传递。这是用于标识每个项目的独一键, 以方便在需要时引用它们。

还要注意的是loaded属性。正如<Page>具有loaded属性一样, 按钮同样可以有一个。稍后你会看到使用的方式。

5.JavaScript 代码

现在我们已经准备好来看那让整个程序运作起来的 JavaScript 了。在本节中, 我们将编写 node-page.js 的代码。

初始化

首先, 我们导入data/observabledata/observable-array 模块。这些是 NativeScript 中的内置模块, 允许我们创建监控对象和数组。 以在这些对象和数组被更新时能自动更新 UI。

在我们的应用程序中,pageArray是用于存储笔记的数组, 而pageData用于将其绑定到页面。pageData还充当显示在 UI 的所有数据之常规容器。

接着导入其他在此页面中将使用的所有模块:

  • camera:用于处理设备摄像头。
  • view:用于引用页面中的特定元素。它可看作是等效于 NativeScript 的document.getElementById
  • ui/enums: 所有与 UI 相关的常量值的全局字典。
  • ui/animation: 用于元素的动画处理。
  • application-settings: 用于保存本地数据。
  • file-system: 用于处理文件系统。

接下来,将在文件的全局变量值初始化。page存储了对当前页面的引用, notesArr是当前页面中笔记的普通数组副本, current_index是索引的初始值,用来作每个笔记的独一 ID 。

pageLoaded() 函数

我们使用exports让函数在页面上下文中可被调用。稍早你在 notes-page.xml 文件中看过了加载页面时执行pageLoaded ()函数。

pageLoaded()函数中, 我们一开始先获取页面的引用。然后, 我们显示用于创建新笔记的窗体, 并从应用程序设置中获取新笔记的标题和笔记的当前存储值。

接下来还是在pageLoaded()函数, 检查是否有本地存储的笔记。如果沒有, 我们会创建笔记数组。此数组将作为应用程序新用户的默认内容。 但是, 如果已经有存储于本地的笔记, 我们将它们转换为数组, 然后将这些数据添加到监控数组中。

注意到在把项目推入监控数组之前, 我们首先检查它是不是空的。必须这样做的原因是选择图像后, 摄像头模块会再次执行页面的loaded事件。 也就是如果我们不够小心的话,每次用户使用摄像头时会添加重复的项目到数组里。

现在, 我们已经设置了笔记的数据, 我们可以将item_title属性设为先前从应用程序设置中获取的值以更新页面标题。然后将pageData绑定到页面, 以便每当我们设置的项目更改时, UI 都会自动更新。

加入创建新筆記的窗体动画处理。我们使用view中的getViewById函数,传递作为第一个参数的上下文 (当前页)以及指定给你要操作的元素之id属性,来实现动画。

接下来, 调用animate 函数。该函数接受一个含有动画设置的对象。在此我们希望窗体在800毫秒的时间内从原来的位置向下滑动160像素。

newNote() 函数

newNote()函数会在用户点击标题栏的 New Item 操作项时执行。它负责隐藏和显示新项目ListView, 并根据showForm的当前值向上或向下滑动窗体。

如果showForm值为true, 表示它当前正在显示中, 我们将ListView的不透明度在400毫秒的时间内变为1, 然后将窗体向上滑动以隐藏它。否则, 我们隐藏ListView并向下滑动窗体。

btnLoaded() 函数

notes-page. xml 文件中,我们在删除筆記的按钮中设有一个loaded属性。这就是当该事件发生时执行的函数。

默认情况下, 当按钮在ListView项目内部定义时, 分配给ListViewitemTap属性的函数不会被执行。这是因为 NativeScript 假定每个列表项对应的操作只能由这些按钮触发。

下面的代码是该默认行为的变通方法。基本上这是移除了 "删除" 按钮的聚焦, 如此一来当用户点击ListView项目时, 你仍然可以执行函数。 这种情况下, 我们其实不需要这段代码, 因为我们没有分配任何功能给项目的点击, 但它在操作列表时是个好用的工具。

openCamera() 函数

接着是openCamera()函数, 当用户点击 Attach Image 按钮时就会被执行。使用照相机模块时当前状态并不会被保存, 因此必需先将新筆記的标题保存到应用程序设置中。

之后, 我们可以调用takePicture()方法启动设备中默认的摄像头应用程序。此方法接受一个含有图片设置的对象。 一旦用户拍摄了一张图片且点击了 Android 上的 Save 或 iOS 上的 use image 按钮, 该承諾就会被实现, 然后传递给then()的回调函数就会执行。

实际图像将作为参数传递给函数, 我们用它将文件保存到文档路径。完成后, 我们将完整的文件路径保存于应用程序设置及当前的应用程序状态, 以便稍后在我们要保存笔记时可以获取该变量值。

saveNote() 函数

saveNote()函数于用户点击 Save Note 按钮时执行。 它会获取笔记标题文本框和图像路径的当前值,递增 current_index,并将新项目添加到普通笔记数组和监控笔记数组。 然后将当前笔记和current_index保存于应用程序设置,从应用程序设置删除为新笔记设置的值,更新UI使表单的显示为空状态,并在隐藏新的笔记窗体时显示列表。

deleteNote() 函数

最后, 我们有 deleteNote() 函数, 当用户点击列表项里面的 "删除" 按钮时就会执行。 正如你从前面几个函数中看到过的那样, 一个对象被作为参数传递给附加于特定组件的事件处理函数。此对象具有object属性, 它引用了组件本身。

从那里你可以获取传递给它的属性值。在本例中, 我们将获取index属性值, 然后使用它来获取我们所要删除项目的实际索引。

6.添加样式

打开 app. css 文件并添加以下全局样式:

如果你想要应用页面专属的样式, 还可以创建 notes-page.css  文件并在其中定义样式。

7.运行及调试应用程序

你可以执行tns run在设备上运行应用程序, 以及之后在要部署的平台上。以下是 android 的一个例子:

如果你尚未安装 Android 平台,它会自动安装, 并于安装后在设备上运行应用程序。一旦应用程序开始运行, 你可以执行tns livesync android --watch在每次更改源文件时都能自动刷新应用程序。

调试

就像其他应用程序框架一样, NativeScript 允许开发者调试他们的应用程序。这是通过Chrome 开发工具完成的。做法有两种:

  1. 如果已有应用程序在运行中, 你可以打开一个新的终端窗口执行tns debug android --start以附加调试器到当前运行的应用程序实例。
  2. 如果还没有应用程序运行, 使用tns debug android --debug-brkto建立一个附加调试器的应用程序实例。

无论你采取哪个选项, 这都会在谷歌 Chrome 浏览器打开新的标签页, 让你就像调试普通的 JavaScript 网页应用那样调试应用程序。这意味着实际上你可以在源代码中使用console.log来检查运行中变量的内容。

结论与后续

在本文中, 你已经学会了如何使用 NativeScript 构建应用程序。具体地说, 你已经了解例如使用 UI 组件、布局、样式、动画、使用设备摄像机以及用应用程序设置来存保存用程序状态等概念。

现在, 你已经构建好你的第一个 NativeScript 应用程序, 是时候更进一步应用你的技能了, 请查阅还有什么是可以用 NativeScript 实现并用它构建更多的应用程序。

关注我们的公众号
Advertisement
Advertisement
Advertisement
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.