返回博客首页
← 所有文章

在 NativeScript 应用中使用 Babel

2015 年 12 月 23 日 — 作者:Todor Totev

NativeScript 1.5 版本引入了对可以转译为 JavaScript 的语言的一流支持。简单来说,如果你选择的语言可以生成 JavaScript,现在就可以用它来创建 NativeScript 应用。NativeScript CLI 集成了对 TypeScript、Babel 和 CoffeeScript 的支持(我们支持的完整语言列表),但如果你想使用其他语言,只需按照现有 Babel 的模板创建一个插件即可。
 
即将发布的 ES7 语言版本包含async/await 特性,它让 UI 和网络代码的编写和维护变得轻而易举。我非常渴望在 NativeScript 应用中尝试 async 代码,并决定通过实现一个简单的应用来尝试它。我决定镜像cuteness 示例。但我的项目的目标更强大,这就是它遵循/r/hardcoreaww 子reddit 的原因。
 
我从一个新的项目开始

tns create hardcoreaww && cd hardcoreaww

然后我添加了对 Babel 和 Android 平台的支持

tns install babel && tns platform add android

为了设置我的开发环境,我启动了一个 Android 模拟器和我的代码编辑器。我使用很棒的
Visual Studio Code 来编写这篇文章。
 
然后,我需要设置 Babel。首先,Babel 需要一个运行时才能工作。
 
我使用了

npm install babel-polyfill --save

将其添加到我的项目中,然后在我的 app.js 中“require”它

"use strict";
require("babel-polyfill");

因为我想使用 async 关键字,所以我需要加载相应的 Babel 插件。为此,我在项目的根目录下创建了一个 .babelrc 文件,其中包含以下内容:

{
  "presets": ["stage-3", "es2015"]
}

预设在这里讨论。请查阅 Babel 的文档以了解其他可能的选项。
 
由于这些组件仅在开发应用程序时才需要,我使用以下命令将它们安装为“开发依赖项”

npm install babel-preset-stage-3 -D
npm install babel-preset-es2015 -D

然后我启动了 LiveSync 进程:

tns livesync --watch

并检查模板中的初始应用是否在模拟器中工作。我已准备好开始进行黑客攻击!
 
在开发应用程序时,我发现了一些问题。事实证明,1.5 版本的“应用程序”模块无法使用 ES6 import 语法导入。
 
因此,此语法

import * as application from "application";

尚不可用。我们将尝试 为即将发布的 1.6 版本解除此限制。在此期间,我使用

let application = require("application");

目前它可以完成任务。当我编写代码时,我能够使用不同的 ES6 结构,例如命名导出和默认导出,例如

export default class AppViewModel extends Observable { ....
 
稍后我使用以下方式使用它

import AppViewModel from "./reddit-app-view-model";

此代码还使用带有构造函数和继承的 ES6 类。我还使用了 `let` 和 `const`,以便编译器可以检查我的代码是否存在危险行为。
 
但这还不够。我想体验 ES7 async 结构的简单性和有效性。当我从 reddit 中获取数据时,出现了绝佳的机会。
 
代码变得像广告中所说的那样简洁和线性

try {
    const url = redditUrl + args.count + (after ? "&after=" + after : "");
    const response = await fetch(url);
    const result = await response.json();
    const itemsToLoad = result.data.children.map(i => new RedditViewModel(i.data));
    this._redditItems.load(args.index, itemsToLoad);
} catch (e) {
    // 不是生产代码
    console.log("Error fetching data: " + e.toString());
}

使用 Promise 的相同代码看起来也不错,但我发现它更难阅读,因此更难维护
 
fetch(url)
    .then(response => response.json())
    .then(result => {
        let itemsToLoad = result.data.children.map(i => new RedditViewModel(i.data));
        this._redditItems.load(args.index, itemsToLoad);
    }).catch(e => {
        // 不是生产代码
        console.log("Error fetching data: " + e.toString());
    });

如您所见,async 代码更易于阅读,错误处理使用的是传统的 try/catch(并且可靠)。
 
完整的示例应用程序可以在GitHub 上找到。请注意,要在 iOS 上运行它,您需要手动更改 info.plist。阅读这篇文章博客文章以获取说明。

结果很好

aww-1   Android image


总结我的实验,我发现我喜欢编写 ES6/ES7 风格的代码。现代 JavaScript 与几年前截然不同。它适合编写需要持续维护和改进的复杂应用程序。我对 NativeScript 和 Babel 的简单集成非常满意。
 
tns install babel && tns platform add android
tns install babel && tns platform add android
tns install babel && tns platform add android
tns install babel && tns platform add android