返回博客首页
← 所有文章

NativeScript for Capacitor v2 发布

2022 年 4 月 25 日 — 由 技术指导委员会 (TSC)

随着 @nativescript/capacitor 2.0 的发布,带来了更多的成熟度,以及以下改进:

  • 能够从 Capacitor 中使用 NativeScript 插件
  • 能够从 Capacitor 中使用 @nativescript/core
  • 快速启动时间(~ < 20ms)
  • 在 iOS 和 Android 上都使用 v8 引擎

去年,我们发布了 v1,它首次带来了从 Capacitor 中利用 NativeScript 的能力,我们不断受到它带来的有效解决方案的启发。

扩展 Capacitor 的选择

由于能够从 Capacitor 中使用 NativeScript 插件,社区拥有更多选择来解决开发难题。

以 Capacitor 插件对 Zip 处理的请求为例,在这里可以找到

您可能会遇到一个插件,它支持一个平台,但可能不支持另一个平台。在这种情况下,一位熟练的贡献者提供了 Android zip 插件,在这里可以找到,但它目前不支持 iOS。

如果您熟悉 Swift 和 Objective C,您可以帮助贡献该插件来添加 iOS 支持,但如果您不熟悉呢?

假设您正在一个时间紧迫的移动项目中工作,并且需要立即为 iOS 提供 Zip 处理支持。

使用 @nativescript/zip 与 Capacitor

通过按照这里的文档安装 @nativescript/capacitor,您现在可以使用各种 NativeScript 插件,例如

它支持 iOS 和 Android,甚至支持密码保护的 zip/解压缩!👀

在 Capacitor 项目中使用 NativeScript 插件的好处在于,您可以只使用您需要的部分。您可以使用 capacitor-zip 用于 Android,也可以使用 @nativescript/zip 用于 iOS。

@nativescript/capacitor 为您提供了一个隔离的开发区域,src/nativescript,与您的 Ionic 代码库并列,仅在 Capacitor 运行时生效。它还隔离了 NativeScript 依赖项,以便进行干净的架构控制和组织。

  1. 安装 NativeScript 插件
cd src/nativescript
npm install @nativescript/zip
  1. 修改 src/native-custom.d.ts 以包含您想从 Ionic 中使用的强类型实用程序。此文件可帮助您维护对任何公开给 Ionic 代码库的自定义 NativeScript 实用程序的强类型接口。
/**
 * Define your own custom strongly typed native helpers here.
 */
export interface ZipOptions {
  directory: string;
  archive?: string;
  unzip?: boolean;
}

export interface nativeCustom {
  // example provided with every install
  openNativeModalView(): void;

  /*
   * Added for our new zip/unzip abilities!
   */
  fileZip(options: ZipOptions): void;
}
  1. 为我们的 zip 功能添加一个新文件:src/nativescript/examples/zip.ts

  2. 导入到 src/nativescript/index.ts(NativeScript 入口点)

/**
 * Zip/Unzip handling
 */
import './examples/zip';
  1. src/nativescript/examples/zip.ts 中实现新的实用程序方法
import { Zip } from '@nativescript/zip';
import { path, knownFolders } from '@nativescript/core';
import { ZipOptions } from '../../native-custom';

native.fileZip = function (options: ZipOptions) {
  const directory = path.join(knownFolders.documents().path, options.directory);
  const archive = path.join(knownFolders.temp().path, options.archive);
  if (options.unzip) {
    console.log('Unzipping archive:', archive);
    console.log('Into folder:', directory);

    Zip.unzip({
      directory,
      archive,
      onProgress: (progress) => {
        console.log('unzip progress:', progress);
      },
    }).then((filePath) => {
      console.log('Unzipped files are here:', filePath);
    });
  } else {
    console.log('Zipping directory:', directory);
    console.log('Into archive:', archive);

    Zip.zip({
      directory,
      archive,
      onProgress: (progress) => {
        console.log('zip progress:', progress);
      },
    }).then((filePath) => {
      console.log('Zipped file is here:', filePath);
    });
  }
};
  1. 在您的 Ionic 代码库中使用,例如:src/app/explore-container.component.ts
import { native } from '@nativescript/capacitor';

// ...
export class ExploreContainerComponent {
  fileZip(unzip?: boolean) {
    const directory = 'assets';
    const archive = 'assets.zip';
    if (unzip) {
      native.fileUnzip({
        directory,
        archive,
      });
    } else {
      native.fileZip({
        directory,
        archive,
      });
    }
  }
}
  1. 绑定到您的视图以进行用户交互
<div id="container">
  <p><a (click)="fileZip()">Zip File</a></p>
  <p><a (click)="fileZip(true)">Unzip Files</a></p>
</div>

这展示了如何利用 @nativescript/core 本身内的实用程序以及您需要的任何东西。

构建和运行

对于您使用的任何 NativeScript 插件,都可能与它们相关联的 iOS 或 Android 依赖项。您可以通过打开任何 node_modules 包来查看是否存在 platforms 文件夹。Capacitor 还需要了解这些依赖项。

使用 @nativescript/zip,我们可以看到它们,例如在 VS Code 中,使用以下方式

code src/nativescript/node_modules/@nativescript/zip

您会看到以下内容,部分内容如下:

platforms
  android
    include.gradle
  ios
    Podfile
index.android.js
index.d.ts
index.ios.js

编译后的 index.{android,ios}.js 文件是实现,而 platforms 文件夹指定了每个适用平台的原生依赖项。打开 platforms/ios/Podfile 会显示

pod 'SSZipArchive', '~> 2.4.3'

这是 @nativescript/zip 使用的iOS Cocoapod

打开 ios/App/Podfile,并让 Capacitor 的 iOS 构建也使用它

def capacitor_pods
  pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
  pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
  pod 'NativescriptCapacitor', :path => '../../node_modules/@nativescript/capacitor'
end

target 'App' do
  capacitor_pods
  # Add your Pods here

  # NativeScript
  pod 'NativeScript'
  pod 'NativeScriptUI'

  # Zip/Unzip
  pod 'SSZipArchive', '~> 2.4.3'
end

现在我们可以使用以下命令为 Capacitor 准备构建

yarn build:mobile

这将构建您的 Web 应用程序,然后隔离地捆绑您的 src/nativescript

您现在拥有完全可操作的 zip/解压缩处理功能

ionic cap run ios -l --external
NativeScript Zip plugin working from Capacitor

开发者注意事项

目前,在 v2 中,当使用带有原生依赖项的 NativeScript 插件(*如果它们包含 platforms/iosplatforms/android 文件夹*)时,您可以将它们手动添加到 Capacitor Podfile(对于 iOS)或 gradle(对于 Android)。

在未来版本中,这些将自动添加。

@nativescript/core 中有很多功能,我们目前只测试了其中的几个功能,但请随意进行实验!

示例:创建新文件并打开它

这展示了如何使用 @nativescript/core 文件 API 来创建文件并打开它

import { File, Utils, knownFolders, path } from '@nativescript/core';

native.createAndOpenFile = function (
  content: string,
  filename = 'new-file.txt'
) {
  const newFile = File.fromPath(
    path.join(knownFolders.documents().path, 'assets', filename)
  );
  newFile.writeTextSync(content, (err) => {
    if (err) {
      console.log('err:', err);
      return;
    }
  });

  Utils.openFile(newFile.path, 'File creation from {N} for Capacitor.');
};

示例:Ionic/Capacitor <--> NativeScript 事件通信

当需要在 Ionic/Capacitor 和您的 NativeScript 实用程序之间来回通信事件时,您可以使用

  • notifyEvent: (name: string, data?: any) => void: 使用可选数据通知事件名称。
  • onEvent: (name: string, callback: Function) => void: 监听事件名称,并执行回调函数。
  • removeEvent: (name: string, callback?: Function) => void: 移除事件监听器。

例如,使用上面的 zip 示例,您可以在 NativeScript 实用程序中使用 notifyEvent 来发出事件

  • src/nativescript/examples/zip.ts
// ...
import { notifyEvent } from "@nativescript/capacitor/bridge";

native.fileZip = function (options: ZipOptions) {
    // ...

    Zip.zip({
      directory,
      archive,
      onProgress: (progress) => {
        notifyEvent('zipProgress', progress);
      },
    }).then((filePath) => {
      notifyEvent('zipComplete', filePath);
    });
  }
};

然后,您可以在 Ionic 组件中监听这些事件

  • src/app/explore-container.component.ts:
import { native } from '@nativescript/capacitor';

// ...
export class ExploreContainerComponent implements OnInit {
  ngOnInit() {
    native.onEvent('zipComplete', (filepath) => {
      console.log('ionic zip complete:', filepath);
    });
    native.onEvent('zipProgress', (progress) => {
      console.log('ionic zip progress:', progress);
    });
  }
}

OpenJS 演示文稿和其他视频学习资料

您可以从以下额外资源中进一步探索将 NativeScript 与 Capacitor 一起使用

https://www.youtube.com/watch?v=OInjFvniccU

https://www.youtube.com/watch?v=AHcL_UbnnPY

帮助塑造未来

您可以通过多种有用的方式做出贡献

随时与我们一起庆祝 JavaScript 开发的奇迹和乐趣。