NativeScript 快速指南



NativeScript - 简介

通常情况下,开发移动应用程序是一项复杂且具有挑战性的任务。有很多框架可用于开发移动应用程序。Android 提供基于 Java 语言的原生框架,而 iOS 提供基于 Objective-C/Swift 语言的原生框架。但是,要开发支持两种操作系统的应用程序,我们需要使用两种不同的框架用两种不同的语言进行编码。

为了克服这种复杂性,移动框架支持此功能。使用跨平台或混合框架的主要原因是更容易维护单个代码库。一些流行的框架包括 NativeScript、Apache Cordova、Xamarin 等。

JavaScript 框架概述

JavaScript 是一种多范式语言。它支持函数式编程、面向对象编程和基于原型的编程。JavaScript 最初用于客户端。如今,JavaScript 也被用作服务器端编程语言。JavaScript 框架是一种使使用 JavaScript 更轻松、更流畅的工具。

使用此框架,程序员可以轻松地将应用程序编码为设备响应式。响应式是此框架变得非常流行的原因之一。

让我们看看一些流行的 JS 框架:

Angular

Angular 是一个最强大、高效且开源的 JavaScript 框架之一。我们可以构建移动和桌面应用程序。谷歌使用此框架。它用于开发单页应用程序 (SPA)。

Vue.js

VueJS 是一个渐进式 JavaScript 框架,用于开发交互式 Web 界面。它是用于简化 Web 开发的著名框架之一。它可以轻松地集成到大型项目中以进行前端开发,没有任何问题。其双重集成模式是创建高端 SPA 或单页应用程序最吸引人的功能之一。

React

ReactJS 是一个用于构建可重用 UI 组件的 JavaScript 库。它由 Facebook 开发。它目前是最流行的 JavaScript 库之一,拥有强大的基础和庞大的社区。

Node.js

Node.js 是一个开源的、跨平台的运行时环境,用于开发服务器端和网络应用程序。它基于 Google Chrome 的 JavaScript 引擎 (V8 引擎)。Node.js 应用程序是用 JavaScript 编写的,可以在 OS X、Microsoft Windows 和 Linux 上运行。它提供丰富的各种 JavaScript 模块库,简化了 Web 应用程序的开发。

NativeScript 概述

NativeScript 是一个开源框架,用于创建原生 iOS 和 Android 移动应用程序。它是一个 JIT 编译框架。NativeScript 代码运行在 JS 虚拟机上。它对 Android 和 iOS 平台都使用 V8 引擎运行时。NativeScript 使用 XML、JS 和 CSS 进行开发。它有一个名为 PlayGround 的 WebIDE。此 PlayGround 支持易于使用的界面、易于管理的项目、热重载和设备上的调试。

NativeScript 允许开发人员快速有效地创建原生跨平台应用程序,并节省开发、测试和培训成本。因此,原生应用程序在未来几年内将继续丰富强大,以使其更好用。

功能

NativeScript 拥有充满活力的社区支持。以下是 NativeScript 的一些主要功能:

  • 可扩展的

  • 热模块替换

  • 易于设置

  • 我们可以构建丰富的动画、图形、图表和列表

  • 开发人员可以使用任何视图作为应用程序的根视图

  • 惰性编码

好处

NativeScript 帮助小型或大型公司构建跨平台移动应用程序。一些主要好处包括:

  • 开发人员可以重用现有的工具和代码

  • 易于修改、故障排除和更新新版本

  • 开发体验良好,因此我们不必花费时间学习新工具

  • 来自 JavaScript 的平台特定 API,无需学习 Cordova 插件

  • 轻松使用不同的登录提供商进行身份验证

NativeScript - 安装

本节说明如何在您的机器上安装 NativeScript。

先决条件

在进行安装之前,我们需要以下先决条件:

  • Node.js

  • Android

  • iOS

验证 Node.js

Node.js 是一个基于 Google Chrome 内部 JavaScript 引擎 v8 构建的 JavaScript 运行时引擎。NativeScript 广泛使用 Node.js 来执行各种目的,例如创建启动模板应用程序、编译应用程序等。您的机器上必须安装 Node.js

希望您已在机器上安装了 Node.js。如果尚未安装,请访问链接 https://node.org.cn/ 下载最新的 LTS 包并安装它。

要在终端上验证 Node.js 是否已正确安装,请输入以下命令:

node --version

您应该能够看到版本号。截至目前,当前稳定的“LTS”版本为 node 12.14.0。

CLI 设置

NativeScript CLI 是一个基于终端/命令行的应用程序,允许您创建和开发 NativeScript 应用程序。Node.js 包管理器 npm 用于在您的机器上安装 NativeScript CLI。

使用以下命令安装 NativeScript CLI:

npm install -g nativescript

执行此命令后,我们应该看到以下输出:

Command

setupcli

我们已在系统中安装了最新的 NativeScript CLI,tns。现在,在您的终端中输入以下命令:

tns

这将列出快速入门指南。您应该看到以下输出:

CLI

cli

即使没有任何其他设置,我们也可以使用 tns 来创建和开发应用程序。但是,我们无法将应用程序部署到真实设备。相反,我们可以使用 NativeScript PlayGround iOS / Android 应用程序运行应用程序。我们将在接下来的章节中检查它。

安装 NativeScript Playground 应用

转到您的 iOS App Store 或 Google Play 商店并搜索 NativeScript Playground 应用。应用程序出现在搜索结果中后,点击安装选项。它将把 NativeScript Playground 应用安装到您的设备上。

NativeScript Playground 应用程序将有助于在 Android 或 iOS 设备上测试您的应用程序,而无需将应用程序部署到真实设备或模拟器。这将减少开发应用程序的时间,并提供一种轻松启动移动应用程序开发的方法。

Android 和 iOS 设置

在本节中,让我们学习如何设置系统以在模拟器或真实设备上构建和运行 iOS 和 Android 应用程序。

步骤 1:Windows 依赖项

在 Windows 命令提示符中以管理员身份执行以下命令:

@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex 
((new-object net.webclient).DownloadString('https://www.nativescript.org/setup/win'))"

此命令之后,脚本将下载、安装依赖项并进行配置。

步骤 2:macOS 依赖项

要在 macOS 上安装,您必须确保已安装 Xcode。Xcode 对 NativeScript 来说是必需的。如果未安装 Xcode,请访问以下链接 https://developer.apple.com/xcode/ 下载并安装它。

现在在您的终端中执行以下命令:

sudo ruby -e "$(curl -fsSL https://www.nativescript.org/setup/mac)"

执行上述命令后,脚本将安装 iOS 和 Android 开发的依赖项。完成后,关闭并重新启动终端。

步骤 3:Android 依赖项

希望您已配置以下先决条件:

  • JDK 8 或更高版本

  • Android SDK

  • Android 支持库

  • Google 存储库

  • Android SDK Build-tools 28.0.3 或更高版本

  • Android Studio

如果未配置上述先决条件,请访问以下链接 https://developer.android.com.cn/studio/ 进行安装。最后,在环境变量中添加 JAVA_HOME 和 ANDROID_HOME。

步骤 4:验证依赖项

现在一切就绪。您可以使用以下命令验证依赖项:

tns doctor

这将验证所有依赖项并总结如下结果:

√ Getting environment information 
No issues were detected. 
√ Your ANDROID_HOME environment variable is set and points to correct directory. 
√ Your adb from the Android SDK is correctly installed. 
√ The Android SDK is installed. 
√ A compatible Android SDK for compilation is found. 
√ Javac is installed and is configured properly. 
√ The Java Development Kit (JDK) is installed and is configured properly. 
√ Local builds for iOS can be executed only on a macOS system. 
   To build for iOS on a different operating system, you can use the
   NativeScript cloud infrastructure. 
√ Getting NativeScript components versions information... 
√ Component nativescript has 6.3.0 version and is up to date. 
√ Component tns-core-modules has 6.3.2 version and is up to date. 
√ Component tns-android has 6.3.1 version and is up to date. 
√ Component tns-ios has 6.3.0 version and is up to date.

如果您发现任何问题,请在继续开发应用程序之前更正这些问题。

NativeScript - 架构

NativeScript 是一个创建移动应用程序的高级框架。它隐藏了创建移动应用程序的复杂性,并公开了一个相当简单的 API 来创建高度优化和高级的移动应用程序。NativeScript 使即使是入门级开发人员也能轻松地在 Android 和 iOS 上创建移动应用程序。

让我们在本节中了解 NativeScript 框架的架构。

简介

NativeScript 框架的核心概念是使开发人员能够创建混合风格的移动应用程序。混合应用程序使用平台特定的浏览器 API 在普通移动应用程序内托管 Web 应用程序,并通过 JavaScript API 向应用程序提供系统访问。

NativeScript 大量投资于 **JavaScript 语言**,为开发人员提供高效的框架。由于 **JavaScript** 是客户端编程(Web 开发)的事实上的标准,并且每个开发人员都非常了解 JavaScript 语言,因此它有助于开发人员轻松地进入 NativeScript 框架。在底层,NativeScript 通过一组称为 **原生插件** 的 JavaScript 插件公开原生 API。

NativeScript 建立在 原生插件 的基础之上,并提供许多高级且易于使用的 JavaScript 模块。每个模块都执行特定功能,例如访问摄像头、设计屏幕等。所有这些模块都可以多种方式组合以构建复杂的移动应用程序。

下图显示了 NativeScript 框架的高级概述:

Framework

**NativeScript 应用程序** - NativeScript 框架允许开发人员使用 Angular 风格的应用程序或 Vue 风格的应用程序。

**JavaScript 模块** - NativeScript 框架提供了一套丰富的 JavaScript 模块,清晰地分为 UI 模块、应用程序模块、核心模块等。应用程序可以随时访问所有模块来编写任何级别的复杂应用程序。

**JavaScript 插件** - NativeScript 框架提供大量 JavaScript 插件来访问平台相关功能。模块使用 JavaScript 插件来提供平台特定的功能。

**原生插件** - 原生插件是用平台特定的语言编写的,用于包装系统功能,然后 JavaScript 插件将进一步使用这些功能。

**平台 API** - 平台供应商提供的 API。

简而言之,NativeScript应用程序使用模块编写和组织。模块是用纯JavaScript编写的,并且模块通过插件访问平台相关的功能(在需要时),最终,插件桥接平台API和JavaScript API。

NativeScript应用程序的工作流程

正如我们之前了解到的,NativeScript应用程序由模块组成。每个模块都启用一个特定的功能。引导NativeScript应用程序的两个重要模块类别如下:

  • 根模块

  • 页面模块

根模块和页面模块可以归类为应用程序模块。应用程序模块是NativeScript应用程序的入口点。它引导一个页面,使开发人员能够创建页面的用户界面,并最终允许执行页面的业务逻辑。应用程序模块包含以下三个项目:

  • 使用XML编码的用户界面设计(例如page.xml/page.component.html)

  • 使用CSS编码的样式(例如page.css/page.component.css)

  • 模块在JavaScript中的实际业务逻辑(例如page.js/page.component.ts)

NativeScript提供了许多UI组件(在UI模块下)来设计应用程序页面。在基于Angular的应用程序中,UI组件可以用XML格式或HTML格式表示。应用程序模块使用UI组件设计页面并将设计存储在单独的XML文件中,例如 *page.xml/page.component.html*。可以使用标准CSS设置设计样式。

应用程序模块将设计的样式存储在单独的CSS文件中,例如 *page.css/page.component.css*。可以使用JavaScript/TypeScript完成页面的功能,它可以完全访问设计以及平台功能。应用程序模块使用单独的文件,例如page.js/page.component.ts来编写页面的实际功能。

根模块

NativeScript通过UI容器管理用户界面和用户交互。每个UI容器都应该有一个*根模块*,UI容器通过它来管理UI。NativeScript应用程序有两种类型的UI容器:

应用程序容器 - 每个NativeScript应用程序都应该有一个应用程序容器,它将使用application.run()方法设置。它初始化应用程序的UI。

模型视图容器 - NativeScript使用模型视图容器管理模式对话框。NativeScript应用程序可以拥有任意数量的模型视图容器。

每个根模块都应该只有一个UI组件作为其内容。UI组件又可以拥有其他UI组件作为其子组件。NativeScript提供了许多UI组件,例如TabView、ScrollView等,具有子组件功能。我们可以将它们用作根UI组件。一个例外是*Frame*,它没有子组件选项,但可以用作根组件。Frame提供加载页面模块和导航到其他*页面模块*的选项。

页面模块

在NativeScript中,每个页面基本上都是一个*页面模块*。页面模块使用NativeScript提供的丰富的UI组件进行设计。页面模块通过*Frame*组件(使用其defaultPage属性或使用navigate()方法)加载到应用程序中,而*Frame*组件又使用*根模块*加载,*根模块*又在应用程序启动时使用application.run()加载。

应用程序的工作流程可以用下图表示:

Application

下文将详细解释上图:

  • NativeScript应用程序启动并调用application.run()方法。

  • application.run()加载一个*根模块*。

  • 使用以下任何一个UI组件设计*根模块*:

    • Frame

    • TabView

    • SideDrawer

    • 任何布局视图

  • Frame组件加载指定的页面(页面模块)并进行渲染。其他UI组件将根据*根模块*中的指定进行渲染。其他UI组件还可以选择将*页面模块*作为其主要内容加载。

基于Angular的NativeScript应用程序的工作流程

正如我们之前了解到的,NativeScript框架提供了多种方法来满足不同类别的开发人员。NativeScript支持的方法如下:

  • NativeScript核心 - NativeScript框架的基本或核心概念

  • Angular + NativeScript - 基于Angular的方法

  • Vuejs + NativeScript - 基于Vue.js的方法

让我们学习如何将Angular框架集成到NativeScript框架中。

步骤1

NativeScript提供了一个对象(platformNativeScriptDynamic)来引导Angular应用程序。platformNativeScriptDynamic有一个方法bootstrapModule,用于启动应用程序。

使用Angular框架引导应用程序的语法如下:

import { platformNativeScriptDynamic } from "nativescript-angular/platform"; 
import { AppModule } from "./app/app.module"; 
platformNativeScriptDynamic().bootstrapModule(AppModule);

这里:

AppModule 是我们的根模块。

步骤2

应用程序模块的一个简单实现(如下所示代码)。

import { NgModule } from "@angular/core"; 
import { NativeScriptModule } from "nativescript-angular/nativescript.module"; 
import { AppRoutingModule } from "./app-routing.module"; 
import { AppComponent } from "./app.component"; 
@NgModule(
   {
      bootstrap: [
         AppComponent
      ], imports: [
         NativeScriptModule,
         AppRoutingModule
      ], declarations: [
         AppComponent
      ]
   }
) export class AppModule { }

这里:

AppModule 通过加载AppComponent组件来启动应用程序。Angular组件类似于页面,用于设计和编程逻辑。

AppComponent (app.component.ts) 的简单实现及其演示逻辑 (app.component.css) 如下:

app.component.ts

import { Component } from "@angular/core"; 
@Component(
   {
      selector: "ns-app",
      templateUrl: "app.component.html"
   }
)
export class AppComponent { }

这里:

templateUrl 指的是组件的设计。

app.component.html

<page-router-outlet></page-router-outlet>

这里:

page-router-outlet 是Angular应用程序附加的位置。

总而言之,Angular框架由类似于NativeScript框架的模块组成,但略有不同。Angular中的每个模块都将有一个Angular组件和一个路由设置文件(page-routing.mocdule.ts)。路由按模块设置,负责导航。Angular组件类似于NativeScript核心中的页面。

每个组件都将有一个UI设计(page.component.html)、一个样式表(page.component.css)和一个JavaScript/TypeScript代码文件(page.component.ts)。

NativeScript - Angular 应用

让我们创建一个简单的基本应用程序来了解NativeScript应用程序的工作流程。

创建应用程序

让我们学习如何使用NativeScript CLI,tns创建简单的应用程序。tns提供了一个create命令,用于在NativeScript中创建一个新项目。

创建新应用程序的基本语法如下:

tns create <projectname> --template <template_name>

其中:

  • Projectname 是项目名称。

  • template_name 是项目模板。NativeScript提供了许多启动模板来创建不同类型的应用程序。使用基于Angular的模板。

让我们创建一个名为NativeScriptSamples的新目录来处理我们的新应用程序。现在,打开一个新的终端,然后移动到我们的目录并键入以下命令:

tns create BlankNgApp --template tns-template-blank-ng

其中,tns-template-blank-ng 指的是基于AngularJS的空白移动应用程序。

输出

..... 
..... 
..... 
Project BlankNgApp was successfully created. 
Now you can navigate to your project with $ cd BlankNgApp 
After that you can preview it on device by executing $ tns preview

现在,我们的第一个移动应用程序 *BlankNgApp* 已创建。

应用程序的结构

在本章中,让我们通过分析我们的第一个应用程序BlankNgApp来了解NativeScript应用程序的结构。NativeScript应用程序被组织成多个部分,它们如下:

  • 配置部分

  • Node模块

  • Android源代码

  • iOS源代码

  • 应用程序源代码

应用程序的总体结构如下:

│ angular.json 
│ LICENSE 
│ nsconfig.json 
│ package-lock.json 
│ package.json 
│ tsconfig.json 
│ tsconfig.tns.json 
│ tsfmt.json 
│ webpack.config.js 
│
├───App_Resources 
│  ├───Android 
│  │ 
│  └───iOS 
│ 
├───hooks 
│ 
├───node_modules 
| 
└───src 
   │ app.css 
   │ main.ts 
   │ package.json 
   │ 
   └───app 
      │  app-routing.module.ts 
      │  app.component.html 
      │  app.component.ts 
      │  app.module.ts 
      │ 
      └───home 
         home-routing.module.ts 
         home.component.html 
         home.component.ts 
         home.module.ts

让我们了解应用程序的每个部分以及它如何帮助我们创建应用程序。

配置部分

应用程序根目录中的所有文件都是配置文件。配置文件的格式为JSON格式,这有助于开发人员轻松理解配置详细信息。NativeScript应用程序依赖于这些文件来获取所有可用的配置信息。让我们在本节中浏览所有配置文件。

package.json

package.json文件设置应用程序的标识(id)以及应用程序正常工作所依赖的所有模块。以下是我们的package.json:

{ 
   "nativescript": {
      "id": "org.nativescript.BlankNgApp",
      "tns-android": {
         "version": "6.3.1"
      }, "tns-ios": {
         "version": "6.3.0"
      } 
   }, "description": "NativeScript Application", 
   "license": "SEE LICENSE IN <your-license-filename>", 
   "repository": "<fill-your-repository-here>", 
   "dependencies": { 
      "@angular/animations": "~8.2.0", 
      "@angular/common": "~8.2.0", 
      "@angular/compiler": "~8.2.0", 
      "@angular/core": "~8.2.0", 
      "@angular/forms": "~8.2.0", 
      "@angular/platform-browser": "~8.2.0", 
      "@angular/platform-browser-dynamic": "~8.2.0", 
      "@angular/router": "~8.2.0", 
      "@nativescript/theme": "~2.2.1", 
      "nativescript-angular": "~8.20.3", 
      "reflect-metadata": "~0.1.12", 
      "rxjs": "^6.4.0", 
      "tns-core-modules": "~6.3.0", 
      "zone.js": "~0.9.1" 
   }, 
   "devDependencies": { 
      "@angular/compiler-cli": "~8.2.0", 
      "@ngtools/webpack": "~8.2.0", 
      "nativescript-dev-webpack": "~1.4.0", 
      "typescript": "~3.5.3" 
   }, 
   "gitHead": "fa98f785df3fba482e5e2a0c76f4be1fa6dc7a14", 
   "readme": "NativeScript Application" 
}

这里:

应用程序的标识 (nativescript/id) - 将应用程序的id设置为org.nativescript.BlankNgApp。此id用于将我们的应用程序发布到Play商店或iTunes。此id将是我们的应用程序标识符或包名称。

依赖项 (dependencies) - 指定我们所有依赖的节点模块。由于默认的NativeScript实现依赖于Angular框架,因此包含Angular模块。

开发依赖项 - 指定应用程序依赖的所有工具。由于我们使用TypeScript开发应用程序,因此它包含TypeScript作为其中一个依赖模块。

angular.json - Angular框架配置信息。

nsconfig.json - NativeScript框架配置信息。

tsconfig.json, tsfmt.json & tsconfig.tns.json - TypeScript语言配置信息

webpack.config.js - 使用JavaScript编写的Webpack配置。

Node模块

由于NativeScript项目是基于节点的项目,因此它将所有依赖项存储在node_modules文件夹中。我们可以使用npm (npm install) 或tns将所有应用程序依赖项下载并安装到node_moduels中。

Android源代码

NativeScript自动生成Android源代码并将其放置在App_Resources\Android文件夹中。它将用于使用*Android SDK*创建Android应用程序

iOS源代码

NativeScript自动生成iOS源代码并将其放置在App_Resources\iOS文件夹中。它将用于使用iOS SDK和XCode创建iOS应用程序

应用程序源代码

实际的应用程序代码放在src文件夹中。我们的应用程序在src文件夹中具有以下文件。

└───src 
   │ app.css 
   │ main.ts 
   │ package.json 
   │ 
   └───app 
   │ app-routing.module.ts 
   │ app.component.html 
   │ app.component.ts 
   │ app.module.ts 
   │ 
   └───home 
         home-routing.module.ts 
         home.component.html 
         home.component.ts 
         home.module.ts

让我们了解所有文件的作用以及它们在本节中的组织方式:

步骤1

main.ts - 应用程序的入口点。

// this import should be first in order to load some required settings (like globals and reflect-metadata) 
import { platformNativeScriptDynamic } from "nativescript-angular/platform";
import { AppModule } from "./app/app.module"; 
platformNativeScriptDynamic().bootstrapModule(AppModule);

在这里,我们将AppModule设置为应用程序的引导模块。

步骤2

app.css - 应用程序的主要样式表如下所示:

@import "~@nativescript/theme/css/core.css"; 
@import "~@nativescript/theme/css/brown.css"; 
/* Place any CSS rules you want to apply on both iOS and Android here. 
This is where the vast majority of your CSS code goes. */

这里:

app.css导入NativeScript框架的核心样式表和棕色主题样式表。

步骤3

app\app.module.ts - 应用程序的根模块。

import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
@NgModule(
   {
      bootstrap: [
         AppComponent
      ], 
      imports: [
         NativeScriptModule,
         AppRoutingModule
      ], 
      declarations: [
         AppComponent
      ], schemas: [
         NO_ERRORS_SCHEMA
      ]
   }
)
export class AppModule { }

这里:

AppModule基于NgModule创建,并设置应用程序的组件和模块。它导入两个模块NativeScriptModule和AppRoutingModule以及一个组件AppComponent。它还将AppComponent设置为应用程序的根组件。

步骤4

app.component.ts - 应用程序的根组件。

import { Component } from "@angular/core"; 
@Component(
   { 
      selector: "ns-app", 
      templateUrl: "app.component.html" 
   }
) 
export class AppComponent { }

这里:

AppComponent设置组件的模板和样式表。模板使用NativeScript UI组件以纯HTML设计。

步骤5

app-routing.module.ts - AppModule的路由模块

import { NgModule } from "@angular/core"; 
import { Routes } from "@angular/router"; 
import { NativeScriptRouterModule } from "nativescript-angular/router"; 
const routes: Routes = [
   { path: "", redirectTo: "/home", pathMatch: "full" },
   { path: "home", loadChildren: () =>
   import("~/app/home/home.module").then((m) => m.HomeModule) } 
];
@NgModule(
   {
      imports: [NativeScriptRouterModule.forRoot(routes)], 
      exports: [NativeScriptRouterModule] 
   }
)
export class AppRoutingModule { }

这里:

AppRoutingModule使用NativeScriptRouterModule并设置AppModule的路由。它基本上将空路径重定向到/home,并将/home指向HomeModule。

步骤6

app\home\home.module.ts - 定义一个新的模块,HomeModule。

import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptCommonModule } from "nativescript-angular/common";
import { HomeRoutingModule } from "./home-routing.module";
import { HomeComponent } from "./home.component";
@NgModule(
   {
      imports: [
         NativeScriptCommonModule,
         HomeRoutingModule
      ],
      declarations: [
         HomeComponent
      ],
      schemas: [
         NO_ERRORS_SCHEMA
      ]
   }
)
export class HomeModule { }

这里:

HomeModule导入两个模块,HomeRoutingModule和NativeScriptCommonModule以及一个组件HomeComponent

步骤7

app\home\home.component.ts - 定义Home组件,并用作应用程序的主页。

import { Component, OnInit } from "@angular/core";
@Component(
   {
      selector: "Home", templateUrl: "./home.component.html" 
   }
) 
export class HomeComponent implements OnInit { 
   constructor() { 
      // Use the component constructor to inject providers. 
   } 
   ngOnInit(): void { 
      // Init your component properties here. 
   } 
}

这里:

HomeComponent设置Home组件的模板和选择器。

步骤8

app\home\home-routing.module.ts - HomeModule的路由模块,用于定义Home模块的路由。

import { NgModule } from "@angular/core"; 
import { Routes } from "@angular/router"; 
import { NativeScriptRouterModule } from "nativescript-angular/router"; 
import { HomeComponent } from "./home.component"; 
const routes: Routes = [
   { path: "", component: HomeComponent } 
]; 
@NgModule(
   { 
      imports: [NativeScriptRouterModule.forChild(routes)], 
      exports: [NativeScriptRouterModule] 
   }
) 
export class HomeRoutingModule { }

这里:

HomeRoutingModule将空路径设置为HomeComponent。

步骤9

app.component.html 和 home.component.html - 它们使用 NativeScript UI 组件来设计应用程序的 UI。

运行你的应用

如果你想在不使用任何设备的情况下运行你的应用,请键入以下命令:

tns preview

执行此命令后,它将生成一个二维码,你可以扫描并连接到你的设备。

输出

QRCode

二维码

现在二维码已生成,下一步连接到 PlayGround。

NativeScript PlayGround

在你的 iOS 或 Android 手机上打开 NativeScript PlayGround 应用,然后选择“扫描二维码”选项。它将打开相机。将相机对准控制台中显示的二维码。这将扫描二维码。扫描二维码将触发应用程序构建,然后将应用程序同步到设备,如下所示:

Copying template files... 
Platform android successfully added. v6.3.1 
Preparing project... 
File change detected. Starting incremental webpack compilation... 
webpack is watching the files… 
Hash: 1f38aaf6fcda4e082b88 
Version: webpack 4.27.1 
Time: 9333ms 
Built at: 01/04/2020 4:22:31 PM
               Asset          Size        Chunks         Chunk Names 
               0.js           8.32 KiB     0     [emitted] 
          bundle.js           22.9 KiB    bundle [emitted] bundle 
       package.json          112 bytes           [emitted] 
         runtime.js             73 KiB   runtime [emitted] runtime 
tns-java-classes.js            0 bytes  [emitted] 
          vendor.js            345 KiB   vendor  [emitted] vendor 
Entrypoint bundle = runtime.js vendor.js bundle.js 
[../$$_lazy_route_resource lazy recursive] ../$$_lazy_route_resource lazy 
namespace object 160 bytes {bundle} [built] [./app.css] 1.18 KiB {bundle} [built] [./app/app-routing.module.ts] 688 bytes {bundle} [built] 
[./app/app.component.html] 62 bytes {bundle} [built] 
[./app/app.component.ts] 354 bytes {bundle} [built] 
[./app/app.module.ts] 3.22 KiB {bundle} [built] 
[./app/home/home.module.ts] 710 bytes {0} [built] 
[./main.ts] 1.84 KiB {bundle} [built] 
[@angular/core] external "@angular/core" 42 bytes {bundle} [built] [nativescript-angular/nativescript.module] external "nativescript-
angular/nativescript.module" 42 bytes {bundle} [built] 
[nativescript-angular/platform] external "nativescript-angular/platform" 42 
bytes {bundle} [built] [tns-core-modules/application] external "tns-core-
modules/application" 42 bytes {bundle} [built] 
[tns-core-modules/bundle-entry-points] external "tns-core-modules/bundle-entry-points" 42 
bytes {bundle} [built] 
[tns-core-modules/ui/frame] external "tns-core-
modules/ui/frame" 42 bytes {bundle} [built] 
[tns-core-modules/ui/frame/activity] external "tns-core-
modules/ui/frame/activity" 42 bytes {bundle} [built] 
   + 15 hidden modules Webpack compilation complete. Watching for file changes. 
Webpack build done! 
Project successfully prepared (android) 
Start sending initial files for device Bala Honor Holly (ff5e8622-7a01-4f9c-
b02f-3dc6d4ee0e1f). 
Successfully sent initial files for device Bala Honor Holly (ff5e8622-7a01-4f9c-b02f-3dc6d4ee0e1f). 
LOG from device Bala Honor Holly: HMR: Hot Module Replacement Enabled. Waiting for signal. 
LOG from device Bala Honor Holly: Angular is running in the development mode. 
Call enableProdMode() to enable the production mode.

输出

扫描后,你应该在你的设备上看到你的 BlankNgApp。如下图所示:

BlankNgApp

在设备上运行你的应用

如果你想在你的应用程序中测试连接的设备,你可以使用以下语法进行验证:

'tns device <Platform> --available-devices'

之后,你可以使用以下命令执行你的应用程序:

tns run

以上命令用于在本地构建你的应用程序并安装到 Android 或 iOS 设备上。如果你想在 Android 模拟器上运行你的应用程序,请键入以下命令:

tns run android

对于 iOS 设备,你可以使用以下命令:

tns run ios

这将在 Android/iOS 设备上初始化应用程序。我们将在后续章节中更详细地讨论这一点。

LiveSync (实时同步)

NativeScript 提供应用程序更改与预览应用程序的实时同步。让我们使用你喜欢的任何编辑器(Visual Studio Code 是更好的选择)打开项目。让我们在代码中添加一些更改,看看 LiveSync 如何检测到这些更改。

现在打开文件 app.css,它将包含以下内容:

@import "~@nativescript/theme/css/core.css"; 
@import "~@nativescript/theme/css/blue.css"; 
/* Place any CSS rules you want to apply on both iOS and Android here. 
This is where the vast majority of your CSS code goes. */

这里,import 语句指定了我们应用程序的颜色方案。让我们将蓝色方案更改为棕色方案,如下所示:

@import "~@nativescript/theme/css/core.css"; 
@import "~@nativescript/theme/css/brown.css"; 
/* Place any CSS rules you want to apply on both iOS and Android here. 
This is where the vast majority of your CSS code goes. */

设备上的应用程序将刷新,你应该看到一个棕色的 ActionBar,如下所示:

输出

以下是 BlankNgApp 首页 - 棕色主题。

Brown Theme

NativeScript - 模板

NativeScript 提供了许多现成的模板,可以创建从简单的空白但功能齐全的应用程序到复杂的基于 Tab 的应用程序。

使用模板

如前所述,可以使用 tns 命令的create 子命令创建新的应用程序。

tns create <app-name> --template <tns-template-name>

这里:

tns-template-name 是模板的名称。

如果你想使用 JavaScript 创建一个只有一个页面且没有任何自定义样式的模板,请使用以下命令:

tns create <app-name> --template tns-template-blank

可以使用 TypeScript 创建相同的模板,如下所示:

tns create <app-name> --template tns-template-blank-ts

导航模板

导航模板用于创建中等复杂程度到复杂的应用程序。它预配置了SideDrawer 组件和多个页面。SideDrawer 组件包含一个隐藏的视图,用于导航 UI 或常用设置。使用以下命令创建基于导航的应用程序:

tns create <app-name> --template tns-template-drawer-navigation

Tab 导航模板

Tab 导航模板用于创建基于 Tab 的应用程序。它预配置了TabView 组件和多个页面。使用以下命令创建基于 Tab 的应用程序:

tns create <app-name> --template tns-template-tab-navigation

主从模板

主从模板用于创建基于列表的应用程序,以及列表中每个项目的详细信息页面。

tns create <app-name> --template tns-template-master-detail

自定义模板

要创建简单的自定义模板,我们需要克隆空白模板。正如你已经知道的,NativeScript 支持 JavaScript、TypeScript、Angular 和 Vue.js 模板,因此你可以选择任何语言并创建你自己的自定义模板。

例如,使用以下命令从 git 仓库克隆简单和自定义模板:

git clone https://github.com/NativeScript/template-blank-ts.git

现在,它将创建移动应用程序结构,以便你可以进行任何更改并运行你的 Android/iOS 设备。此结构基于一系列指南。让我们简要了解一下这些指南。

结构

你的自定义模板必须满足以下要求:

  • 不要将你的代码放在应用程序根文件夹内。

  • 创建一个单独的文件夹,并在其中添加功能区域。

  • 页面、视图模型和服务应放置在功能区域中。这有助于创建整洁的代码。

  • 创建页面文件夹,并将.ts、.xml、.scss/css 等文件放在其中。

package.json

将 package.json 文件放在应用程序模板的根文件夹中。使用以下格式为 name 属性提供值:

{
   "name": "tns-template-blank-ts", 
   displayName": "template-blank", 
}

为 version 属性赋值。定义如下:

"version": "3.2.1",

为 main 属性赋值,指定应用程序的主要入口点。定义如下:

"main": "app.js",

为 android 属性赋值。定义如下:

"android": { 
   "v8Flags": "--expose_gc" 
},

应在你的代码中指定 repository 属性,如下所示:

"repository": { 
   "type": "git", 
   "url": "https://github.com/NativeScript/template-master-detail-ts" 
},

样式

使用以下语法在你的应用程序模板中导入样式和主题:

@import '~nativescript-theme-core/scss/light';

我们还可以使用以下代码分配自定义背景颜色:

/* Colors */ 
$background: #fff; 
$primary: lighten(#000, 13%);

NativeScript - 小部件

NativeScript 提供大量用户界面组件,称为“widget”(部件)。每个部件执行一项特殊任务,并带有一组方法。让我们在本节中详细了解 NativeScript 部件。

按钮 (Button)

按钮是一个用于执行点击事件操作的组件。当用户点击按钮时,它将执行相应的操作。定义如下:

<Button text="Click here!" tap="onTap"></Button>

让我们在我们的 BlankNgApp 中添加按钮,如下所示:

步骤1

打开src\app\home\home.component.html。这是我们 home 组件的 UI 设计页面。

步骤2

GirdLayout 组件内添加一个按钮。完整的代码如下:

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar> 
<GridLayout> 
   <button text="Click Here!"></button> 
</GridLayout>

输出

以下是按钮的输出:

GirdLayout

步骤3

我们可以使用 CSS 来设置按钮的样式,如下所示:

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar> 
<GridLayout> 
   <button text="Click Here!" class="-primary"></button> 
</GridLayout>

这里,-primary 类用于表示主按钮。

输出

以下是ButtonPrimary 的输出:

ButtonPrimary

步骤4

NativeScript 提供格式化选项,可在按钮中提供自定义图标。示例代码如下:

<GridLayout> 
   <Button class="-primary"> 
      <FormattedString> 
         <Span text="&#xf099;" class="fa"></Span> 
         <Span text=" Button.-primary with icon"></Span> 
      </FormattedString> 
   </Button> 
</GridLayout>
.fa {
   font-family: "FontAwesome", "fontawesome-webfont";
}

这里:

&#xf099 指定图标在字体 FontAwesome 中的位置。下载最新的 Font Awesome 字体并将 fontawesome-webfont.ttf 放入 src\fonts 文件夹。

输出

以下是ButtonPrimary 的输出:

FontAwesome

步骤5

可以使用以下语法创建圆角按钮:

<Button text="Button.-primary.-rounded-sm" class="-primary -rounded-sm"></Button>

输出

以下是 ButtonPrimary 的输出:

Home

标签 (Label)

Label 组件 用于显示静态文本。将主页更改为如下所示:

<GridLayout> 
   <Label text="NativeScript is an open source framework for creating native iOS and Android apps in TypeScript or JavaScript." textWrap="true">
   </Label> 
</GridLayout>

这里,textWrap 将包装标签的内容,如果标签超出屏幕宽度。

输出

以下是 Label 的输出:

Label

文本字段 (TextField)

TextField 组件 用于获取用户信息。让我们将主页更改为如下所示:

<GridLayout> 
   <TextField hint="Username" 
      color="lightblue" 
      backgroundColor="lightyellow" 
      height="75px">
   </TextField> 
</GridLayout>

这里:

  • color 表示文本颜色

  • backgroundColor 表示文本框的背景

  • height 表示文本框的高度

输出

以下是文本字段的输出:

Text Field

文本视图 (TextView)

TextView 组件 用于获取用户的多行文本内容。让我们将主页更改为如下所示:

<GridLayout> 
   <TextView loaded="onTextViewLoaded" hint="Enter text" returnKeyType="done" autocorrect="false" maxLength="100"> 
   </TextView> 
</GridLayout>

这里,maxLength 表示TextView 接受的最大长度。

输出

以下是 TextView 的输出:

TextView

搜索栏 (SearchBar)

此组件用于搜索任何查询或提交任何请求。定义如下:

<StackLayout> 
   <SearchBar id="bar" hint="click here to search ..."></SearchBar> 
<StackLayout>
SearchBar

我们可以应用样式:

<StackLayout> 
   <SearchBar id="bar" hint="click here to search ..." color="green" backgroundColor="green"></SearchBar> 
</StackLayout>

以下是 SearchBarStyle 的输出:

SearchBarstyle

开关 (Switch)

Switch 基于切换,在选项之间进行选择。默认状态为 false。定义如下:

<StackLayout> 
   <Switch checked="false" loaded="onSwitchLoaded"></Switch> 
</StackLayout>

以上程序的输出如下所示:

Program

滑块 (Slider)

滑块是一个滑动组件,用于选择一个数值范围。定义如下:

<Slider value="30" minValue="0" maxValue="50" loaded="onSliderLoaded"></Slider>

以上程序的输出如下所示:

Slider

进度条 (Progress)

Progress 部件指示操作的进度。当前进度以条形表示。定义如下:

<StackLayout verticalAlign="center" height="50"> 
   <Progress value="90" maxValue="100" backgroundColor="red" color="green" row="0"></Progress>
</StackLayout>

以下是 Progress 部件的输出:

Progress

活动指示器 (ActivityIndicator)

ActivityIndicator 显示任务的进度。定义如下:

<StackLayout verticalAlign="center" height="50"> 
   <ActivityIndicator busy="true" color="red" width="50" 
   height="50"></ActivityIndicator> 
</StackLayout>

以下是 ActivityIndicator 的输出:

ActivityIndicator

图像 (Image)

Image 部件用于显示图像。可以使用 'ImageSource' url 加载它。定义如下:

<StackLayout class="m-15" backgroundColor="lightgray">
   <Image src="~/images/logo.png" stretch="aspectFill"></Image> 
</StackLayout>

Image 部件的输出如下所示:

Image

网页视图 (WebView)

WebView 显示网页。可以使用 URL 加载网页。定义如下:

<WebView row="1" loaded="onWebViewLoaded" id="myWebView" src="http://www.google.com"></WebView>

以上代码的输出如下所示:

WebView

日期选择器 (DatePicker)

DatePicker 组件用于选择日期。定义如下:

<StackLayout class="m-15" backgroundColor="lightgray"> 
   <DatePicker year="1980" month="4" day="20" verticalAlignment="center"></DatePicker> 
</StackLayout>

DatePicker 组件的输出如下所示:

DatePicker

时间选择器 (TimePicker)

TimePicker 组件用于选择时间。定义如下:

<StackLayout class="m-15" backgroundColor="lightgray"> 
<TimePicker hour="9" 
   minute="25" 
   maxHour="23" 
   maxMinute="59" 
   minuteInterval="5"> 
</TimePicker> 
</StackLayout>

以下是 TimePicker 组件的输出:

TimePicker

NativeScript - 布局容器

NativeScript 提供一系列容器组件,其唯一目的是布局 UI 部件组件。布局容器充当父组件,可以拥有一个或多个子组件。布局容器的全部子组件可以根据其父布局容器提供的方法进行排列。

NativeScript 支持六种布局容器,它们如下:

  • 绝对布局容器

  • 停靠布局容器

  • 网格布局容器

  • 堆叠布局容器

  • 换行布局容器

  • FlexBox 布局容器

让我们在本节中详细了解所有布局容器的概念。

绝对布局 (Absolute Layout)

AbsoluteLayout 容器是 NativeScript 中最简单的布局容器。AbsoluteLayout 不对其子元素施加任何约束,并将使用二维坐标系(左上角为原点)在其内部放置其子元素。

AbsoluteLayout 使用其子元素的四个属性来定位它们,它们如下:

top - 定义子元素从原点向下(y 方向)的放置位置。

left - 定义子元素从原点向侧(x 方向)的放置位置。

width - 定义子元素的宽度。

height - 定义子元素的高度。

让我们在应用程序的主页中添加 AbsoluteLayout 容器,如下所示:

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar> 

<AbsoluteLayout width="200" height="300" backgroundColor="blue"> 
   <Label text="Top Left" left="0" top="0" width="100" height="150" backgroundColor="green">
   </Label> 
   <Label text="Top Right" left="100" top="0" width="100" height="150" backgroundColor="blue"></Label> 
   <Label text="Bottom Left" left="0" top="150" width="100" height="150" backgroundColor="orange">
   </Label>
   <Label text="Bottom Right" left="100" top="150" width="100" height="150" backgroundColor="red"></Label> 
</AbsoluteLayout>

输出

AbsoluteLayout 的输出如下所示:

AbsoluteLayout

停靠布局 (DockLayout)

Docklayout 容器组件允许其子元素在其内部停靠。容器的每一侧(顶部、底部、左侧、右侧)都可以停靠一个子组件。DockLayout 容器使用其子元素的 dock 属性来正确停靠它们。

dock 属性的可能值如下:

top - 布局容器将子组件停靠在顶部角落。

bottom - 布局容器将子组件停靠在底部角落。

left - 布局容器将子组件停靠在左侧角落。

right - 布局容器将子组件停靠在右侧角落。

默认情况下,DockLayout 容器停靠其最后一个子组件。可以通过将 stretchLastChild 属性设置为零来覆盖它。

让我们在应用程序的主页中添加DockLayout 容器,如下所示:

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar> 
<DockLayout width="250" height="300" backgroundColor="blue" stretchLastChild="false"> 
   <Label text="left" dock="left" width="50" backgroundColor="green"></Label> 
   <Label text="top" dock="top" height="50" backgroundColor="orange"></Label> 
   <Label text="right" dock="right" width="50" backgroundColor="red"></Label< 
   <Label text="bottom" dock="bottom" height="50" 
   backgroundColor="orange"></Label> 
</DockLayout>

输出

以下是 DockLayout 的输出:

DockLayout

网格布局 (GridLayout)

GridLayout 容器组件是一个复杂的布局容器,它以表格格式(带有行和列)排列子元素。默认情况下,它有一行一列。它具有以下属性:

columns - 用于表示每列的默认宽度,由逗号分隔。可能的值是数字、* 和 auto 关键字。

其中:

  • 数字表示绝对列宽。

  • 表示列宽相对于其他列的宽度。它前面可以加上数字,表示列宽应该是最小列宽的多少倍。例如,2* 表示列宽应该是最小列宽的两倍。

  • auto 表示列宽与其最宽子元素一样宽。

例如,*,2* 表示两列,第二列是第一列的两倍大小。

rows − 用于表示用逗号分隔的每一行默认高度。值表示方式类似于 columns。

GridLayout 使用其子元素的以下指定属性进行布局:

row − 行号

col − 列号

rowSpan − 子内容在布局中跨越的总行数。

colSpan − 子内容在布局中跨越的总列数。

让我们在应用程序的主页中添加 GridLayout 容器,如下所示:

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar> 
<GridLayout columns="50, auto, *" rows="50, auto, *" width="210" height="210"
   backgroundColor="blue"> 
   <Label text="Row: 0; Column 0" row="0" col="0" backgroundColor="green"></Label> 
   <Label text="Row: 0; Column 1" row="0" col="1" colSpan="1" backgroundColor="brown"></Label> 
   <Label text="Row: 1; Column 0" row="1" col="0" rowSpan="1" backgroundColor="red"></Label> 
   <Label text="Row: 1; Column 1" row="1" col="1" backgroundColor="orange"></Label> 
</GridLayout>

输出

以下是 GridLayout 的输出:

GridLayout

StackLayout

StackLayout 以一维线状(水平或垂直)的方式组织其子元素。它可以使用布局选项根据布局中的空间进行大小调整。它具有 orientation 属性,可用于指定方向,水平或垂直。

让我们在应用程序的主页中添加 StackLayout 容器,如下所示:

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar> 
<StackLayout orientation="vertical" width="200" height="200" backgroundColor="blue"> 
   <Label text="Label1" width="50" height="50" backgroundColor="green"></Label> 
   <Label text="Label2" width="50" height="50" backgroundColor="brown"></Label> 
   <Label text="Label3" width="50" height="50" backgroundColor="red"></Label> 
   <Label text="Label4" width="50" height="50" backgroundColor="orange"></Label> 
</StackLayout>

输出

StackLayout 的输出如下所示:

StackLayout

WrapLayout

WrapLayout 用于在新行或新列上换行内容。

它具有以下三个属性:

orientation − 水平或垂直显示。

itemWidth − 每个子元素的布局宽度。

itemHeight − 每个子元素的布局高度。

让我们在应用程序的主页中添加 WrapLayout 容器,如下所示:

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar> <WrapLayout orientation="horizontal" width="200" height="200" backgroundColor="blue">
   <Label text="Label1" width="70" height="70" backgroundColor="green"></Label> 
   <Label text="Label2" width="70" height="70" backgroundColor="brown"></Label 
   <Label text="Label3" width="70" height="70" backgroundColor="red"></Label> 
   <Label text="Label4" width="70" height="70" backgroundColor="orange"></Label> 
</WrapLayout>

输出

WrapaLayout

Flexbox 布局

FlexboxLayout 容器组件是高级布局容器之一。它提供选项来呈现从简单的布局到非常复杂和精密的布局。它基于 CSS Flexbox。

FlexboxLayout 组件有很多属性,如下所示:

flexDirection

它表示子组件排列的方向。flexDirection 的可能值如下:

row − 子组件并排排列。

row-reverse − 子组件并排排列,但方向相反。

column − 子组件上下排列。

column-reverse − 子组件上下排列,但方向相反。

让我们在应用程序的主页中添加 FlexLayout 容器,如下所示:

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar> 
<FlexboxLayout flexDirection="row"> 
   <Label text="First Item" backgroundColor="red"></Label> 
   <Label text="Second Item" backgroundColor="green"></Label> 
   <Label text="Third Item" backgroundColor="red"></Label> 
   <Label text="Fourth Item" backgroundColor="green"></Label> 
   <Label text="Fifth Item" backgroundColor="red"></Label> 
</FlexboxLayout>

输出

以下是 FlexLayout - Row 的输出:

FlexLayout

现在,让我们将 flexDirection 值从 row 更改为 row-reverse,并检查它如何影响布局。

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar> <FlexboxLayout flexDirection="row-reverse"> 
   <Label text="First Item" backgroundColor="red"></Label> 
   <Label text="Second Item" backgroundColor="green"></Label> 
   <Label text="Third Item" backgroundColor="red"></Label> 
   <Label text="Fourth Item" backgroundColor="green"></Label> 
   <Label text="Fifth Item" backgroundColor="red"></Label> 
</FlexboxLayout>

输出

以下是 Flex 布局 - Row Reverse 的输出:

FlexLayout1

让我们将 flexDirection 值从 row-reverse 更改为 column,并检查它如何影响布局。

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar> 
<FlexboxLayout flexDirection="column"> 
   <Label text="First Item" backgroundColor="red"></Label> 
   <Label text="Second Item" backgroundColor="green"></Label> 
   <Label text="Third Item" backgroundColor="red"></Label> 
   <Label text="Fourth Item" backgroundColor="green"></Label> 
   <Label text="Fifth Item" backgroundColor="red"></Label> 
</FlexboxLayout>

输出

以下是 FlexLayout - Column 的输出:

FlexLayout Column

让我们将 flexDirection 值从 column 更改为 column-reverse,并检查它如何影响布局。

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar> 
<FlexboxLayout flexDirection="column-reverse"> 
   <Label text="First Item" backgroundColor="red"></Label> 
   <Label text="Second Item" backgroundColor="green"></Label> 
   <Label text="Third Item" backgroundColor="red"></Label> 
   <Label text="Fourth Item" backgroundColor="green"></Label> 
   <Label text="Fifth Item" backgroundColor="red"></Label> 
</FlexboxLayout>

输出

以下是 FlexLayout - Column Reverse 的输出:

Column Reverse

flexWrap

它表示子组件将以单行/单列呈现,还是通过在 flexDirection 设置的方向上换行流入多行。

可能的值如下:

wrap − 如果在给定方向 (flexDirection) 中没有可用空间,则换行子组件。

wrap-reverse − 与 wrap 相同,只是组件流向相反。

让我们添加 flexWrap 属性,然后将其值设置为 wrap。还要添加如下所示的三个子元素:

<ActionBar> 
   <Label text="Home"></Label> 
&tl;/ActionBar> 
<FlexboxLayout flexDirection="row" flexWrap="wrap"> 
   <Label text="First Item" backgroundColor="red"></Label> 
   <Label text="Second Item" backgroundColor="green"></Label> 
   <Label text="Third Item" backgroundColor="red"></Label> 
   <Label text="Fourth Item" backgroundColor="green"></Label> 
   <Label text="Fifth Item" backgroundColor="red"></Label>
   <Label text="Sixth Item" backgroundColor="green"></Label> 
   <Label text="Seventh Item" backgroundColor="red"></Label> 
   <Label text="Eighth Item" backgroundColor="green"></Label> 
</FlexboxLayout>

输出

以下是 flexWrap 的输出:

FlexWrap

JustifyContent

它表示子组件彼此之间以及整体结构如何排列。它具有以下三个属性:

flex-end − 它将子组件打包到末尾。

space-between − 它通过均匀分布在行中来打包子组件。

space-around − 与 space-between 类似,但它通过均匀分布在行中以及它们周围的相等空间来打包子组件。

让我们也添加 justifyContent 并检查它的行为:

<ActionBar> 
   <Label text="Home"></Label>
</ActionBar> 
<FlexboxLayout flexDirection="row" flexWrap="wrap" justifyContent="space-around"> 
   <Label text="First Item" backgroundColor="red"></Label> 
   <Label text="Second Item" backgroundColor="green"></Label> 
   <Label text="Third Item" backgroundColor="red"></Label> 
   <Label text="Fourth Item" backgroundColor="green"></Label> 
   <Label text="Fifth Item" backgroundColor="red"></Label> 
   <Label text="Sixth Item" backgroundColor="green"></Label> 
   <Label text="Seventh Item" backgroundColor="red"></Label> 
   <Label text="Eighth Item" backgroundColor="green"></Label> 
</FlexboxLayout>

输出

以下是 Flex 布局 - JustifyContent 的输出:

JustifyContent

FlexLayout 容器为其子元素提供了另外两个属性来指定顺序和收缩能力。它们如下:

order − 它确定 FlexLayout 容器的子元素呈现的顺序。

flexShrink − 它确定子元素收缩到 0 级别的能力。

NativeScript - 导航

导航使用户能够快速滑动到他们想要的屏幕,或者在应用程序中导航,或者执行特定操作。导航组件帮助您实现导航,从简单的按钮点击到更复杂的模式。

NativeScript 的核心版本和 Angular 版本之间的导航差异很大。虽然核心框架导航是导航过程的基础,但 NativeScript 的 Angular 模型采用核心导航概念并对其进行扩展,使其与 Angular 框架兼容。

让我们在本节中同时了解核心导航概念和 Angular 对导航的采用。

核心概念

让我们在本节中了解 NativeScript 中的导航是如何工作的。

在 NativeScript 中,导航根据其应用的方向分为四个不同的类别,如下所示:

  • 向前导航

  • 向后导航

  • 横向导航

  • 底部导航

向前导航

向前导航 指的是将用户导航到层次结构下一级的屏幕。它基于两个 NativeScript 组件,FramePage。

Frame

Frame 是导航的根级别组件。它不是可见容器,而是充当页面之间转换的容器。

一个简单的示例如下:

<Frame id="featured" defaultPage="featured-page" />

这里:

Frame 导航到(或加载)featured-page 页面组件并呈现它。

Page

Page 紧挨着 Frame 组件,它充当 UI 组件的容器。简单的示例定义如下:

<Page loaded="onPageLoaded"> 
   <ActionBar title="Item" class="action-bar"></ActionBar>
   <AbsoluteLayout> 
      <Label text="Label"/< 
      <Button text="navigate('another-page')" tap="onTap"/> 
   </AbsoluteLayout> 
</Page>

这里:

  • 最初,Page 加载屏幕的所有 UI 组件并呈现它。

  • 当用户点击按钮时,它会将用户导航到another-page 页面。

向后导航

向后导航方法允许在单个应用程序内或跨不同应用程序在屏幕之间向后移动。它与向前导航的方向相反。简单的 goBack() 方法用于导航回上一页。

它定义如下:

<Page class="page" loaded="onPageLoaded"> 
   <ActionBar title="Item" class="action-bar"></ActionBar> 
   <StackLayout class="home-panel"> 
      <Button class="btn btn-primary" text="Back" tap="goBack"/> 
   </StackLayout> 
</Page>

这里:

当用户点击按钮时,将触发goBack() 方法。goBack() 将用户导航到上一页(如果可用)。

横向导航

横向导航是指在同一层次结构级别的屏幕之间导航。它基于中心模式。它通过特定的导航组件启用,例如 BottomNavigation、Tabs、TabView、SideDrawer 和 Modal View。

一个简单的示例定义如下:

<Page class="page" xmlns="http://www.nativescript.org/tns.xsd"> 
   <ActionBar title="Hub" class="action-bar"></ActionBar> 
   <StackLayout class="home-panel"> 
      <Button class="btn btn-primary" text="navigate('featured-page')" tap="navigateToFeatured" /> 
      <Button class="btn btn-primary" text="navigate('search-page')" tap="navigateToSearch" />
   </StackLayout> 
</Page>

这里:

  • navigateToFeatured 函数使用 navigate() 方法将用户导航到特色页面。

  • 同样,navigateToSearch 函数将用户导航到搜索页面。

中心页面也可以使用页面屏幕中可用的 navigate 方法访问,并且可以使用 goBack() 方法离开中心页面。

一个简单的示例如下:

<Page class="page"> 
   <ActionBar title="Item" class="action-bar"></ActionBar> 
   <StackLayout class="home-panel"> 
      <Button class="btn btn-primary" text="navigate('hub-page')" tap="navigateToHub" /> 
      <Button class="btn btn-primary" text="goBack()" tap="goBack" /> 
   </StackLayout> 
</Page>

底部和标签导航

移动应用程序中最常见的导航样式是基于标签的导航。标签导航位于屏幕底部或标题下方的顶部。它是通过使用TabViewBottomNavigation 组件实现的。

基于 Angular 的导航

NativeScript 扩展其导航概念以适应 Angular 路由概念。NativeScript 通过扩展 Angular RouterModule 提供了一个新模块 NativeScriptRouterModule。

NativeScript Angular 导航概念可以分为以下几节:

  • page-router-outlet 标签

  • nsRouterLink 属性

  • RouterExtension

  • 自定义RouterReuseStrategy

让我们在本节中学习所有上述 Angular 导航。

页面路由出口

如前所述,page-router-outlet 是 Angular 的 router-outlet 的替代品。page-router-outlet 包装了 Nativescript 核心导航框架的 Frame 和 Page 策略。每个 page-router-outlet 创建一个新的 Frame 组件,并且出口中配置的每个组件都将使用 Page 组件进行包装。然后,使用本机 navigate 方法导航到另一个页面/路由。

路由链接 (nsRouterLink)

nsRouterLink 是 Angular 的 RouterLink 的替代品。它使 UI 组件能够使用路由链接到另一个页面。nsRouterLink 还提供以下两个选项:

pageTransition − 用于设置页面转换动画。true 启用默认转换。false 禁用转换。特定值(如 slide、fadein 等)设置特定转换。

clearHistory − true 清除 nsRouterLink 的导航历史记录。

一个简单的示例代码如下:

<Button text="Go to Home" [nsRouterLink]="['/home']" 
   pageTransition="slide" clearHistory="true"></Button>

路由扩展

NativeScript 提供 RouterExtensions 类并公开核心 NativeScript 的导航功能。

RouterExtensions 公开的的方法如下:

  • navigate

  • navigateByUrl

  • back

  • canGoBack

  • backToPreviousPage

  • canGoBackToPreviousPage

使用 RouterExtensions 的一个简单的示例代码如下:

import { RouterExtensions } from "nativescript-angular/router"; 
@Component({ 
   // ... 
}) 
export class HomeComponent { 
   constructor(private routerExtensions: RouterExtensions) { } 
}

自定义路由重用策略

NativeScript 使用自定义路由重用策略 (RouterReuseStrategy) 来适应移动应用程序的体系结构。与 Web 应用程序相比,移动应用程序在某些方面有所不同。

例如,当用户从页面导航离开时,可以在 Web 应用程序中销毁页面,并在用户导航到页面时重新创建它。但是,在移动应用程序中,页面将被保留并重用。在设计路由概念时,会考虑这些概念。

路由

NativeScript Angular 应用程序中的一个简单的路由模块如下所示:

import { NgModule } from "@angular/core"; 
import { Routes } from "@angular/router"; 
import { NativeScriptRouterModule } from "nativescript-angular/router"; 
import { HomeComponent } from "./home.component"; 
import { SearchComponent } from "./search.component"; 
const routes: Routes = [ 
   { path: "", redirectTo: "/home", pathMatch: "full" }, 
   { path: "home", component: HomeComponent }, 
   { path: "search", component: SearchComponent }, 
];
@NgModule({ 
   imports: [NativeScriptRouterModule.forRoot(routes)], 
   exports: [NativeScriptRouterModule] 
}) 
export class AppRoutingModule { }

这里:

路由模块与 Angular 版本非常相似,除了极少数例外。实际上,NativeScript 通过以类似于 Angular 框架的方式公开它来使用其核心导航策略。

NativeScript - 事件处理

在每个 GUI 应用程序中,事件在启用用户交互方面都扮演着非常重要的角色。每当用户与应用程序交互时,都会触发一个事件,然后执行相应的操作。

例如,当用户单击应用程序登录页面上的登录按钮时,它会触发登录过程。

事件涉及两个参与者:

  • 事件发送者 − 触发实际事件的对象。

  • 事件监听器 − 监听特定事件并在触发事件时执行的函数。

Observable 类

它是一个预定义的类,用于处理事件。它定义如下:

const Observable = require("tns-core-modules/data/observable").Observable;

在 NativeScript 中,几乎每个对象都派生自 Observable 类,因此每个对象都支持事件。

事件监听器

让我们在本节中了解如何创建一个对象并向该对象添加事件监听器。

步骤1

创建一个用于生成事件的按钮,如下所示:

const Button = require("tns-core-modules/ui/button").Button; 
const testButton = new Button();

步骤2

接下来,向按钮添加文本,如下所示:

testButton.text = "Click";

步骤3

创建一个函数 onTap,如下所示:

let onTap = function(args) {
   console.log("you clicked!"); 
};

步骤4

现在将 tap 事件附加到 onTap 函数,如下所示:

testButton.on("tap", onTap, this);

添加事件监听器的另一种方法如下:

testButton.addEventListener("tap", onTap, this);

步骤5

通过 UI 本身附加事件的另一种方法如下所示:

<Button text="click" (tap)="onTap($event)"></Button>

这里:

$event 的类型为 EventData。EventData 包含两个属性,如下所示:

Object − 用于触发事件的可观察实例。在本例中,它是 Button 对象。

EventName − 它是事件名称。在本例中,它是 tap 事件。

步骤6

最后,事件监听器可以随时分离/删除,如下所示:

testButton.off(Button.onTap);

您还可以使用另一种格式,如下所示:

testButton.removeEventListener(Button.onTap);

修改 BlankNgApp

让我们修改 BlankNgApp 应用程序以更好地理解 NativeScript 中的事件。

步骤1

打开 home 组件的 UI,src/app/home/home.component.html 并添加以下代码:

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar>
<StackLayout> 
   <Button text='Fire an event' class="-primary" color='gray' (tap)='onButtonTap($event)'></Button>
</StackLayout>

这里:

  • tap 是事件,Button 是事件触发器。

  • onButtonTap 是事件监听器。

步骤2

打开 home 组件的代码,‘src/app/home/home.component.ts’ 并更新以下代码:

import { Component, OnInit } from "@angular/core"; 
import { EventData } from "tns-core-modules/data/observable"; 
import { Button } from "tns-core-modules/ui/button" 
@Component({ 
   selector: "Home", 
   templateUrl: "./home.component.html" 
}) 
export class HomeComponent implements OnInit { 
   constructor() { 
      // Use the component constructor to inject providers. 
   } 
   ngOnInit(): void { 
      // Init your component properties here. 
   } 
   onButtonTap(args: EventData): void { 
      console.log(args.eventName); 
      const button = <Button>args.object; 
      console.log(button.text); 
   } 
}

这里:

  • 添加了新的事件监听器 onButtonTap。

  • 打印事件名称 tap 和按钮文本,在控制台中触发事件。

步骤3

运行应用程序并点击按钮。它会在控制台打印以下内容。

LOG from device <device name>: tap 
LOG from device <device name>: Fire an event

NativeScript - 数据绑定

数据绑定是NativeScript支持的高级概念之一。NativeScript尽可能遵循Angular数据绑定的概念。数据绑定使UI组件能够无需任何编程工作即可显示/更新应用程序数据模型的当前值。

NativeScript支持两种数据绑定类型,如下所示:

单向数据绑定 - 模型更改时更新UI。

双向数据绑定 - 同步UI和模型。无论何时更新模型,UI都会自动更新;同样,无论何时UI从用户处获取数据(UI更新),模型也会更新。

让我们在本节中学习这两个概念。

单向数据绑定

NativeScript提供了一个简单的选项,可以在UI组件中启用单向数据绑定。要启用单向数据绑定,只需在目标UI的属性中添加方括号,然后为其赋值必要的模型属性。

例如,要更新Label组件的文本内容,只需按如下所示更改UI代码:

<Label [text]='this.model.prop' />

这里:

this.model.prop 指的是模型this.model的属性。

让我们修改我们的BlankNgApp来理解单向数据绑定。

步骤1

添加一个新的模型User (src/model/user.ts),如下所示:

export class User { 
   name: string 
}

步骤2

打开组件的UI,src/app/home/home.component.html 并按如下所示更新代码:

<ActionBar> 
   <Label text="Home"></Label> 
</ActionBar>
<GridLayout columns="*" rows="auto, auto, auto"> 
   <Button text="Click here to greet" class="-primary" color='gray' 
      (tap)='onButtonTap($event)' row='1' column='0'>
   </Button> 
   <Label [text]='this.user.name' row='2' column='0' 
      height="50px" textAlignment='center' style='font-size: 16px; 
      font-weight: bold; margin: 0px 32px 0 25px;'>
   </Label> 
</GridLayout>

这里:

  • Label的文本设置为用户模型的属性名称。

  • 按钮点击事件附加到onButtonTap方法。

步骤3

打开home组件的代码,src/app/home/home.component.ts 并按如下所示更新代码:

import { Component, OnInit } from "@angular/core"; 
import { User } from "../../model/user" 
@Component({
   selector: "Home", 
   templateUrl: "./home.component.html" 
}) 
export class HomeComponent implements OnInit { 
   public user: User; 
   constructor() {
      // Use the component constructor to inject providers. 
      this.user = new User(); 
      this.user.name = "User1"; 
   }
   ngOnInit(): void { 
      // Init your component properties here. 
   } 
   onButtonTap(args: EventData) { 
      this.user.name = 'User2'; 
   } 
}

这里:

  • 导入了user模型

  • 在组件的构造函数中创建User对象

  • 实现了onButtonTap事件。onButtonTap的实现更新User对象并将属性名称设置为User2

步骤4

编译并运行应用程序,然后单击按钮更改模型,它将自动更改Label文本。

应用程序的初始状态和最终状态如下所示:

初始状态

单向数据绑定初始状态如下所示:

One Way Data Binding

最终状态

单向数据绑定最终状态如下所示:

Final State

双向数据绑定

NativeScript还为高级功能提供双向数据绑定。它将模型数据绑定到UI,并将UI中更新的数据绑定到模型。

要进行双向数据绑定,请使用ngModel属性,然后将其用[]和()括起来,如下所示:

<TextField [(ngModel)] = 'this.user.name'></TextField>

让我们修改BlankNgApp应用程序以更好地理解双向数据绑定。

步骤1

将NativeScriptFormsModule导入HomeModule (src/app/home/home.module.ts),如下所示:

import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core"; 
import { NativeScriptCommonModule } from "nativescript-angular/common"; 
import { HomeRoutingModule } from "./home-routing.module"; 
import { HomeComponent } from "./home.component"; 
import { NativeScriptFormsModule } from "nativescript-angular/forms";
@NgModule({ 
   imports: [ 
      NativeScriptCommonModule, 
      HomeRoutingModule, 
      NativeScriptFormsModule 
   ], 
   declarations: [ 
      HomeComponent 
   ], 
   schemas: [ 
      NO_ERRORS_SCHEMA 
   ]
}) 
export class HomeModule { }

这里:

NativeScriptFormsModule启用双向数据绑定。否则,双向数据绑定将无法按预期工作。

步骤2

更改home组件的UI,如下所示:

<ActionBar> <Label text="Home"></Label></ActionBar> 
<GridLayout columns="*" rows="auto, auto"> 
   <TextField hint="Username" row='0' column='0' color="gray" 
      backgroundColor="lightyellow" height="75px" [(ngModel)]='this.user.name'>
   </TextField> 
   <Label [text]='this.user.name' row='1' column='0' height="50px" 
      textAlignment='center' style='font-size: 16px; font-weight: bold; 
      margin: 0px 32px 0 25px;'>
   </Label> 
</GridLayout>

这里:

Label组件的text属性使用单向数据绑定设置。如果更新模型user,则其text属性将自动更新。

TextField组件将ngModel设置为this.user.name。如果更新模型user,则其text属性将自动更新。同时,如果用户更改TextField的值,则模型也会更新。如果模型更新,它也会触发Label的text属性更改。因此,如果用户更改数据,它将显示在Label的text属性中。

步骤3

运行应用程序并尝试更改文本框的值。

应用程序的初始状态和最终状态将类似于以下指定的状态:

初始状态

双向数据绑定 – 初始状态如下所示:

Initial State

最终状态

双向数据绑定 – 最终状态如下所示:

Two Way Final State

NativeScript - 模块

一个NativeScript模块包含一组打包为单个库的相关功能。让我们学习NativeScript框架提供的模块。

它包含NativeScript框架的核心功能。让我们在本节中了解核心模块。

Application

Application包含移动应用程序的平台特定实现。简单的核心模块定义如下:

const applicationModule = require("tns-core-modules/application");

Console

Console模块用于记录消息。它具有以下方法:

console.log("My FirstApp project"); 
console.info("Native apps!"); 
console.warn("Warning message!"); 
console.error("Exception occurred");

application-settings

application-settings 模块包含管理应用程序设置的方法。要添加此模块,我们需要添加以下代码:

const appSettings = require("tns-core-modules/application-settings");

application-setting中提供的一些方法如下:

  • setBoolean(key: string, value: boolean) - 设置布尔对象

  • setNumber(key: string, value: number) - 设置数字对象

  • setString(key: string, value: string) - 设置字符串对象

  • getAllKeys() - 包含所有存储的键

  • hasKey(key: string) - 检查键是否存在

  • clear - 清除存储的值

  • remove - 基于键删除任何条目。

使用应用程序设置的简单示例如下:

function onNavigatingTo(args) { 
   appSettings.setBoolean("isTurnedOff", false);
   appSettings.setString("name", "nativescript"); 
   appSettings.setNumber("locationX", 54.321); 
   const isTurnedOn = appSettings.getBoolean("isTurnedOn"); 
   const username = appSettings.getString("username"); 
   const locationX = appSettings.getNumber("locationX"); 
   // Will return "not present" if there is no value for "noKey" 
   const someKey = appSettings.getString("noKey", "not present"); 
}
exports.onNavigatingTo = onNavigatingTo; 
function onClear() {
   // Removing a single entry via its key name 
   appSettings.remove("isTurnedOff"); 
   // Clearing the whole settings 
   appSettings.clear(); 
}

http

此模块用于处理http请求和响应。要将此模块添加到您的应用程序中,请添加以下代码:

const httpModule = require("tns-core-modules/http");

我们可以使用以下方法发送数据:

getString - 用于发出请求并从URL下载数据作为字符串。其定义如下:

httpModule.getString("https://.../get").then(
   (r) => { 
      viewModel.set("getStringResult", r); 
   }, (e) => 
   { 
   }
);

getJSON - 用于访问JSON中的数据。其定义如下:

httpModule.getJSON("https://.../get").then((r) => { 
}, (e) => { 
});

getImage - 从指定的URL下载内容并返回ImageSource对象。其定义如下:

httpModule.getImage("https://.../image/jpeg").then((r) => { 
}, (e) => { 
});

getFile - 它有两个参数URL和文件路径。

  • URL - 下载数据。

  • 文件路径 - 将URL数据保存到文件中。其定义如下:

httpModule.getFile("https://").then((resultFile) => { 
}, (e) => { 
});

request - 它具有options参数。它用于请求选项并返回HttpResponse对象。其定义如下:

httpModule.request({ 
   url: "https://.../get", 
   method: "GET" 
}).then((response) => { 
}, (e) => { 
});

Image-source

image-source模块用于保存图像。我们可以使用以下语句添加此模块:

const imageSourceModule = require("tns-core-modules/image-source");

如果要从资源加载图像,请使用以下代码:

const imgFromResources = imageSourceModule.fromResource("icon");

要从本地文件添加图像,请使用以下命令:

const folder = fileSystemModule.knownFolders.currentApp(); 
const path = fileSystemModule.path.join(folder.path, "images/sample.png"); 
const imageFromLocalFile = imageSourceModule.fromFile(path);

要将图像保存到文件路径,请使用以下命令:

const img = imageSourceModule.fromFile(imagePath); 
const folderDest = fileSystemModule.knownFolders.documents(); 
const pathDest = fileSystemModule.path.join(folderDest.path, "sample.png"); 
const saved = img.saveToFile(pathDest, "png"); if (saved) { 
   console.log(" sample image saved successfully!"); 
}

Timer

此模块用于在特定时间间隔执行代码。要添加它,我们需要使用require

const timerModule = require("tns-core-modules/timer");

它基于两种方法:

setTimeout - 用于延迟执行。它以毫秒表示。

setInterval - 用于以特定间隔重复应用。

Trace

此模块对于调试很有用。它提供日志信息。此模块可以表示为:

const traceModule = require("tns-core-modules/trace");

如果要在您的应用程序中启用它,请使用以下命令:

traceModule.enable();

ui/image-cache

image-cache模块用于处理图像下载请求和缓存下载的图像。此模块可以表示如下:

const Cache = require("tns-core-modules/ui/image-cache").Cache;

connectivity

此模块用于接收已连接网络的连接信息。它可以表示为:

const connectivityModule = require("tns-core-modules/connectivity");

功能模块

功能模块包括许多特定于系统/平台的模块。一些重要的模块如下:

platform - 用于显示有关设备的信息。它可以定义如下:

const platformModule = require("tns-core-modules/platform");

fps-meter - 用于捕获每秒帧数。它可以定义如下:

const fpsMeter = require("tns-core-modules/fps-meter");

file-system - 用于处理设备文件系统。其定义如下:

const fileSystemModule = require("tns-core-modules/file-system");

ui/gestures - 用于处理UI手势。

UI模块

UI模块包括UI组件及其相关功能。一些重要的UI模块如下:

  • frame

  • page

  • color

  • text/formatted-string

  • xml

  • styling

  • animation

NativeScript - 插件

npm包用于添加原生功能。使用此包,我们可以安装、搜索或删除任何插件。本节详细解释了插件。

命令

add - 用于安装插件。

update - 更新指定的插件并修改其依赖项。

remove - 删除插件。

build - 用于为iOS或Android项目构建插件。

create - 为您的项目创建插件。

添加插件

以下语法用于添加新插件:

tns plugin add <plugin-name>

例如,如果要添加nativescript-barcodescanner,可以使用以下代码:

tns plugin add nativescript-barcodescanner

您可以看到以下响应:

+ [email protected] 
added 1 package from 1 contributor and audited 11704 packages in 8.76s

您也可以使用npm模块添加上述插件:

npm install nativescript-barcodescanner

现在,NativeScript CLI从npm下载插件并将其添加到您的node_modules文件夹中。

如果要将插件直接添加到您的package.json并解决所有依赖项问题,可以使用以下命令代替之前的命令:

npm i nativescript-barcodescanner

如果要在开发过程中安装开发依赖项,请使用以下代码:

npm i tns-platform-declarations --save-dev

这里:

tns-platform-declarations是开发过程中仅IntelliSense所需的开发依赖项。

导入插件

现在,我们已经安装了nativescript-barcodescanner插件。让我们使用以下命令将其添加到您的项目中:

const maps = require("nativescript-barcodescanner"); 
maps.requestPermissions();

更新插件

此方法用于更新指定的插件,因此它会卸载之前的插件并安装新版本并修改其依赖项。其定义如下:

tns plugin update <Plugin name version>

删除插件

如果要删除插件(如果不需要),可以使用以下语法:

tns plugin remove <plugin-name>

例如,如果要删除上面安装的nativescript-google-maps-sdk,请使用以下命令:

tns plugin remove nativescript-barcodescanner

您可以看到以下响应:

Successfully removed plugin nativescript-barcodescanner

构建插件

它用于构建位于platforms/android中的插件的Android特定项目文件。让我们使用以下命令构建nativescript-barcodescanner插件:

tns plugin build nativescript-barcodescanner

创建插件

NativeScript插件是简单的JavaScript模块。它定义在您的应用程序src\package.json文件中。此模块用于为NativeScript插件开发创建一个新项目。其定义如下:

tns plugin create <Plugin Repository Name> [--path <Directory>]

NativeScript - 使用 JavaScript 的原生 API

本节解释了使用JavaScript访问原生API的概述。

编组

NativeScript运行时为Android和iOS平台提供隐式类型转换。这个概念称为编组。例如,NativeScript-iOS平台可以隐式转换JavaScript和Objective-C数据类型,类似地,Java/Kotlin可以轻松映射到JavaScript项目类型和值。让我们简要了解如何在每种类型中执行编组。

数值

我们可以轻松地将iOS和Android数值类型转换为JavaScript数字。iOS到JavaScript的简单数值转换定义如下:

console.log(`max(7,9) = ${max(7,9)}`);

这里:

本机max()函数被转换为JavaScript数字。

Android环境

Java支持不同的数值类型,例如byte、short、int、float、double和long。JavaScript只有number类型。

考虑以下所示的简单Java类:

class Demo extends java.lang.Object {
   public int maxMethod(int a,int b) {
      if(a>b) {
         return a;
      } else {
         return b;
      }
   }
}

这里:

以上代码包含两个整型参数。我们可以使用JavaScript调用以上代码对象,如下所示:

//Create an instance for Demo class 
var obj = new Demo(); 

//implicit integer conversion for calling the above method 
obj.maxMethod(7,9);

字符串

Android字符串定义在java.lang.string中,iOS字符串定义在NSSring中。让我们看看如何在两个平台上执行编组。

Android

字符串是不可变的,但字符串缓冲区支持可变字符串。

以下代码是简单映射的示例:

//Create android label widget 
var label = new android.widget.Label(); 

//Create JavaScript string 
var str = "Label1";  

//Convert JavaScript string into java label.setText(str); 
// text is converted to java.lang.String

布尔类定义在 java.lang.Boolean 中。此类将布尔值包装在一个对象中。我们可以轻松地将布尔值转换为字符串,反之亦然。下面给出了一个简单的示例:

//create java string 
let data = new java.lang.String('NativeScript'); 

//map java String to JavaScript string, 
let result = data.startsWith('N'); 

//return result 
console.log(result);// true

iOS 环境

NSString 类是不可变的,但其子类 NSMutableString 是可变的。此类包含用于处理字符串的各种方法。其声明如下:

class NSString : NSObject

考虑如下所示的一个简单的 Objective-C 声明:

NSString *str = @"nativescript"; 
//convert the string to uppercase
NSString *str1; 
str1 = [str uppercaseString]; 
NSLog(@"Uppercase String : %@\n", str1 );

NSString 可以轻松地映射到 JavaScript 字符串。

数组

本节解释如何在数组中执行编组。让我们先来看一个 iOS 环境的例子。

数组声明

class NSArray : NSObject

这里:

NSArray 用于管理称为数组的对象的有序集合。它用于创建静态数组。其子类NSMutableArray 用于创建动态数组。

考虑可以使用数组文字创建 NSArray 对象,如下所示:

let array: NSArray = ["React","Vue","TypeScript"]

现在,我们可以将此数组映射到 JavaScript,如下所示:

//create native array 
let nsArr = NSArray.arrayWithArray("React","Vue","TypeScript"]); 

//create simple javascript array 
let jsArr = ["Hello,World","NativeScript"]; 

//Now compare the two arrays, 
let compare = nsArr.isEqual(jsArr); 
console.log(comapre);

这将返回 false。

Android 数组声明

Java 数组定义在java.util.Arrays 中。此类包含各种用于操作数组的方法。下面是一个例子:

//javascript array 
let data = [12,45,23,56,34,78,50]; 

//create java array 
let result = ns.example.Math.maxElement(data);
console.log(result);

类和对象

类和对象是面向对象编程的基本概念。类是用户定义的原型。对象是类的实例。类表示一类对象共有的属性或方法的集合。让我们了解两种移动开发环境的原生类和对象。

Android环境

Java 和 Kotlin 类具有由完整包名称表示的唯一标识符。

例如:

android.view.View - 这是用于屏幕布局和与用户交互的基本用户界面类。我们可以如下所示在 JavaScript 中访问此类:

const View = android.view.View;

首先,我们使用以下语句导入类:

import android.view.View;

接下来,创建一个类,如下所示:

public class MyClass {
   public static void staticMethod(context) {
      //create view instance
      android.view.View myview = new android.view.View(context);
   }
}

在上述同一个类中,我们可以使用以下代码访问 JavaScript 函数:

const myview = new android.view.View(context);

同样,我们可以访问 java.lang 包中的接口、常量和枚举。

iOS 环境

Objective-C 类定义在两个部分 @interface 和 @implementation 中。类定义以关键字@interface 开始,后跟接口(类)名称。在 Objective-C 中,所有类都派生自名为 NSObject 的基类。

它是所有 Objective-C 类的超类。简单的 Circle 类定义如下:

@interface Circle:NSObject {
   //Instance variable
   int radius;
}
@end

考虑一个带有一个方法的类,如下所示:

@interface MyClass : NSObject 
+ (void)baseStaticMethod; 
@end

可以使用以下代码将此类转换为 javascript:

function MyClass() { /* native call */ }; 
Object.setPrototypeOf(MyClass, NSObject); 
BaseClass.baseStaticMethod = function () { /* native call */ };

JavaScript instanceof 运算符用于验证对象是否继承自给定类。这可以定义为:

var obj = MyClass.alloc().init(); // object creation 
console.log(obj instanceof NSObject); //return true

这里:

Objective-C 实例是使用 alloc、init 或 new 方法创建的。在上面的例子中,我们可以很容易地使用 new 方法创建对象初始化,如下所示:

var obj = MyClass.new();

同样,您可以访问静态方法和属性。

NativeScript - 在 Android 上创建应用

创建和发布您的应用可以让所有用户都可以使用您的 Android 应用程序。Google Play 是一个强大的发布平台。它可以帮助您向全球所有用户发布和分发您的 Android 应用程序。本章介绍如何在 Google Play 上发布您的原生应用。

NativeScript Sidekick

SideKick 是一个 GUI 客户端,支持所有类型的操作系统。它简化了 NativeScript CLI 过程,并有助于创建移动应用程序。

从 Sidekick 发布您的应用到 Google Play Console

下载和安装 Sidekick 取决于您的操作系统。请按照以下步骤在 Sidekick 中运行您的应用。

步骤 1:启动 Sidekick

让我们启动 Sidekick。它看起来类似于下图:

Sidekick

步骤 2:构建您的设备

现在,从您的设备打开您的应用,并从工具栏中选择构建选项,然后选择 Android。您将获得类似于下图的响应:

ToolBar

步骤 3:属性

单击属性选项卡并添加您的 Android 配置。屏幕看起来类似于以下内容:

Configuration

步骤 4:插件

Sidekick 有助于查找您的应用程序所依赖的插件。单击插件选项卡,它将列出以下内容:

Plugins

步骤 5:Android 证书

单击 Android 的齿轮图标并选择浏览选项,然后选择存储在文件系统中的证书。如下所示:

Certificates

选择后,关闭对话框。

步骤 6:构建您的应用程序

最后,从构建类型中单击本地构建选项,并从配置中选择发布选项。之后构建您的应用程序。

步骤 7:应用程序包

构建完成后,它将生成一个路径和apk文件。保存应用程序包的位置。此 apk 文件用于将其上传到 Google Play 商店。

步骤 8:在 Google Play 上发布

从工具栏中选择发布选项,然后选择 Google Play。然后,添加用于 Google Play 商店的管理 Android 证书对话框。如下所示:

Google Play

之后,选择构建类型并提供服务帐户 JSON 密钥,然后选择 Alpha、Beta 或 Production 轨道,最后单击上传。

在 Google Play 上发布您的应用

要在 Google Play Console 上发布您的应用,您必须满足以下先决条件。

先决条件

  • 您必须在 Google Play 上注册

  • 您拥有有效的 Google Play 自签名代码签名身份

发布您的应用的过程

以下步骤有助于了解如何在 Google Play 商店中发布您的应用。

步骤 1:登录 Google Play Console

打开 Google Play Console 并使用您的帐户登录。

步骤 2:创建应用

转到“所有应用”选项卡,然后单击“创建应用”并创建一个新应用。现在,添加默认语言、应用程序标题,最后单击“继续”以继续。

步骤 3:填写所需字段

转到商店列表选项卡并填写所需字段,然后完成所需的资源并保存所有更改。

步骤 4:价格和分发

转到“价格和分发”选项卡,完成所有设置并保存所有更改。

步骤 5:发布您的应用

选择“应用版本”选项卡并选择 Alpha、Beta。它用于测试您的应用程序。并且,选择 Production 轨道。它用于将您的应用发布到 Google Play。最后添加应用程序包 (apk)。

步骤 6:审核您的应用

这是您的最后一步。在审核中,验证是否存在任何问题。如果没有任何问题,则确认推出以发布您的应用。

NativeScript - 在 iOS 上创建应用

本章介绍如何在 App Store 上发布您的原生应用。请按照以下步骤发布您的应用。

先决条件

要执行此操作,您必须需要以下先决条件:

  • 分发证书

  • 分发配置文件

  • 在 iOS Dev 中心注册的捆绑包 ID

  • iTunes Connect 中的应用记录

发布您的应用的步骤

以下是发布您的应用的步骤:

步骤 1:打开 NativeScript Sidekick

启动 NativeScript Sidekick 并打开 Sidekick 中的应用。

步骤 2:选择发布

转到工具栏,然后从工具栏中选择发布选项。如下所示:

Publish

现在,选择 Apple App Store 选项。它看起来类似于下图:

Apple App Store

步骤 3:管理 iOS 配置文件和证书

单击 Apple App Store 齿轮图标并选择浏览选项并添加详细信息。

Cogwheel

步骤 4:构建您的应用

接下来,单击构建选项并构建您的应用,然后等待该过程完成。

步骤 5:提供凭据

这是您的最后一步。在您的帐户中指定 Apple 用户名和密码,然后单击上传并检查确认消息。如果您想提交您的应用以供审核,请转到 iTunes Connect 并提交。

NativeScript - 测试

测试是应用程序开发生命周期中非常重要的阶段。它确保应用程序质量。它需要仔细的计划和执行。它也是开发中最耗时的阶段。NativeScript 框架为应用程序的自动化测试提供了广泛的支持。

测试类型

通常,可以使用三种类型的测试过程来测试应用程序。它们如下:

单元测试

单元测试是测试应用程序最简单的方法。它基于确保一段代码(通常是函数)或类的某个方法的正确性。但是,它不能反映真实环境,因此它是查找错误的选择最少的选项。

通常,NativeScript 使用 Jasmine、Mocha with Chai 和 QUnit 单元测试框架。

要执行此操作,首先需要使用以下命令在项目中进行配置:

tns test init

现在,您将得到以下响应:

? Select testing framework: (Use arrow keys) 
> jasmine 
   mocha 
   qunit

现在,选择jasmine框架,您的屏幕看起来类似于此:

? Select testing framework: jasmine 
+ [email protected] 
added 90 packages from 432 contributors and audited 11944 packages in 8.753s 

+ [email protected] 
added 2 packages from 1 contributor and audited 11946 packages in 7.299s 

> [email protected] postinstall 
/Users/workspace/NativeScript/NativeApp/node_modules/core-js 

> node -e "try{require('./postinstall')}catch(e){}" 
Thank you for using core-js ( https://github.com/zloirock/core-js ) for 
polyfilling JavaScript standard library! 
The project needs your help! Please consider supporting of core-js on Open 
Collective or Patreon:

> https://opencollective.com/core-js 
> https://www.patreon.com/zloirock 
Also, the author of core-js ( https://github.com/zloirock ) is looking for a 
good job -) 
npm WARN [email protected] requires a peer of webpack@^2.0.0 
|| ^3.0.0 but none is installed. You must install peer dependencies yourself. 

+ [email protected] 
added 19 packages from 52 contributors and audited 12012 packages in 9.368s 

+ [email protected] 
added 2 packages from 35 contributors and audited 12014 packages in 6.925s 

+ [email protected] 
updated 1 package and audited 12014 packages in 7.328s 
+ @types/[email protected] 

> [email protected] postinstall /Users/deiva/workspace/NativeScript/NativeApp/node_modules/nativescript-unit
-test-runner 

> node postinstall.js 
+ [email protected] 

added 1 package from 1 contributor and audited 12032 packages in 7.14s 
Successfully installed plugin nativescript-unit-test-runner. 

Example test file created in src/tests 
Run your tests using the "$ tns test <platform>" command.

现在,测试文件已创建在 src\tests\example.ts 中。

创建您的测试

让我们在 example.ts 文件中添加一个简单的测试,如下所示:

describe("NativeApp test:", function() { 
   it("Check counter.", function() { 
      expect(mainViewModel.createViewModel().counter).toEqual(10); 
   }); 
   it("Check message.", function () { 
      expect(mainViewModel.createViewModel().message).toBe("10 taps left"); 
   }); 
});

这里:

首先,检查计数器是否等于 10,并检查消息是否为“还剩 10 次点击”。

让我们在下一步运行测试。

运行您的测试

现在,使用以下命令在已连接的 Android 或 iOS 设备上运行测试:

tns test android

这将返回以下状态:

? To continue, choose one of the following options: (Use arrow keys) 
> Configure for Cloud Builds 
   Configure for Local Builds 
   Configure for Both Local and Cloud Builds 
   Skip Step and Configure Manually

然后选择以下选项:

? To continue, choose one of the following options: Configure for Local Builds 
Running the setup script to try and automatically configure your environment. 
These scripts require sudo permissions 
.....

要在 Android 模拟器中执行您的测试套件,请运行以下命令:

tns test android --emulator

现在,karma 服务器准备构建并部署您的项目。

端到端 (E2E) 测试

单元测试是一个小型、简单且快速的流程,而 E2E 测试阶段则涉及多个组件并协同工作,涵盖应用程序中的流程。单元测试和集成测试无法实现这一点。

NativeScript Appium 插件用于执行 E2E 自动化测试。Appium 是一个用于移动应用程序的开源测试框架。要在您的项目中添加此框架,您必须拥有 XCode 的最新版本或 Android SDK 25.3.0 以上版本。

安装 Appium

让我们使用 npm 模块全局安装 Appium:

npm install -g appium

现在,您可以看到以下响应:

npm install -g appium 
/Users/.npm-global/bin/authorize-ios -> 
/Users/.npm-global/lib/node_modules/ appium/node_modules/.bin/authorize-ios 

> [email protected] install 
/Users/.npm-global/lib/node_modules/ appium/node_modules/appium-windows-driver

> node install-npm.js 
Not installing WinAppDriver since did not detect a Windows system 

> [email protected] postinstall /Users/.npm-
global/lib/node_modules/appium/node_modules/core-js 

> node -e "try{require('./postinstall')}catch(e){}" 
Thank you for using core-js ( https://github.com/zloirock/core-js ) for 
polyfilling JavaScript 
standard library! 
The project needs your help! Please consider supporting of core-js on Open Collective or Patreon: 

> https://opencollective.com/core-js 
> https://www.patreon.com/zloirock 
Also, the author of core-js ( https://github.com/zloirock ) 
is looking for a good job -) 

> [email protected] postinstall/Users/.npm-
global/lib/node_modules/appium/node_modules 
/appium-chromedriver 

> node install-npm.js 
............................................ 
............................................. 
+ [email protected] 
added 671 packages from 487 contributors in 28.889s

添加插件

让我们使用以下命令将nativescript-dev-appium插件作为 devDependency 添加到您的项目:

$ npm install -D nativescript-dev-appium

执行此操作后,选择mocha框架,您将获得类似于此的响应:

> node ./postinstall.js 
? What kind of project do you use
? javascript ? Which testing framework do you prefer? mocha 
+ [email protected]

现在,文件存储在您的项目文件夹中。

Project Folder

构建您的设备

让我们使用以下命令构建 Android 设备:

tns build android

上述命令将运行测试,应指定目标功能。如果您有 iOS 设备,您可以使用iOS设备进行构建。

运行测试

现在,我们已配置好设备。让我们使用以下命令运行我们的测试:

npm run e2e -- --runType <capability-name>

这里:

capability-name 定义在您的应用程序e2e/config/appium.capabilities.json中。

输出

Config

NativeScript - 结论

NativeScript 对于 Web 开发人员来说是一个很棒的移动应用程序,它可以非常轻松地完全测试他们的应用程序,而无需付出额外的努力。开发人员可以自信地开发外观精美且成功的应用程序,而不会在短时间内出现任何问题。

广告