使用 NativeScript 基于 JavaScript 构建原生应用 已翻译 100%

oschina 投递于 2015/06/10 17:29 (共 5 段, 翻译完成于 06-11)
阅读 13419
收藏 130
3
加载中

有很多可供利用 HTML CSS 和 JavaScript,来创建跨平台的应用程序,我已经在这些之前找到了很多。在这篇文章中我将讨论 Telerik 所说的比许多现有的更容易创建跨平台的应用程序 ——nativescript。

从官方文档来看

开发者使用 nativescript 对 iOS、Android、Windows 建立通用本地应用程序,跨平台共享应用程序代码。构建应用程序 UI 时,开发者使用我们的库文件,它抽象出本地平台之间的差异。

创建一个图片搜索 flicker app

本教程中,我们将创建一个简单的 APP,用 flickr 搜索图片并且显示结果,我们将利用 flicker 开发者 API 搜索图片。

本教程源码在 GitHub

一一叶
一一叶
翻译于 2015/06/10 18:05
1

入门

安装 nodejs 并使用 node 包管理器 (npm) 安装 native script。

npm install -g nativescript

装好之后,创建一个新的项目,叫做 NativeApp

tns create NativeApp

导航至项目路径,使用命令行添加移动开发平台。

tns platform add android

在 android 模拟器上运行应用程序。

tns run android --emulator

NativeApp default preview

    项目结构

Project Structure

项目目录里面有 3 个子目录:applib 和 platforms。应用程序代码位于 app 目录。应用程序代码是使用 JavaScript 写的,而用户界面则使用 XML 进行设计。

app 目录里面是一个叫做 main-page.xml  的文件,它是用户界面的默认代码。在 main-view-model.js 中是默认的模型代码,而 main-page.js 定义了应用程序逻辑。最后 app.js 包含了使用定义好的模型启动应用程序的代码。

LeoXu
LeoXu
翻译于 2015/06/11 08:52
2

设计应用

让我们先从使用 XML 设计应用开始吧。打开 main-page.xml 并观察默认代码。除了 page 标记以外其它都删除。page 标记有一个叫做 loaded 的属性,它会在应用一加载就执行 pageLoaded 函数。pageLoaded 函数位于 main-page.js 文件中。

本项目使用了一个栈布局来设计我们的应用。还有许多的 NativeScript布局

在page标记中添加栈布局。

<StackLayout orientation="vertical">
 
</StackLayout>

使用一个竖向(vertical)的 orientation 定义栈布局。在栈布局立面加入一个文本框和一个按钮。

<TextField width="300px" hint="search keyword" />
 
<Button text="Search" height="50px" style="background-color:green;width:300px;border:none;font-size:20px;" />

保存并运行应用。看起来一个像下面这样。

App Preview

LeoXu
LeoXu
翻译于 2015/06/11 08:58
2

从 flickr 获取数据

在搜索按钮中加入一个叫做 tap 的属性

tap="signin"

现在,当用户触摸搜索按钮时,signin 函数就会被调用。让我们在 main-page.js 中定义 signin 函数。

exports.signin = function() {
  // Code would be here !
};

为了能使用 flickr 的开发者 API,你需要一个免费的 flickr 账户。请求一个 API key 以发起 API 请求。

在 main-page.js 定义 API key。

var api_key = 'replacewithyourkey';

调用 API 需要用到 http 模块,所以把模块导入 main-page.js

var http = require("http");

在 sigin 函数里面,使用 http 模块,发起 API 调用请求。

http.getJSON("https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=" + api_key + "&text=hello&format=json&nojsoncallback=1&per_page=5").then(function(r) {
 
    console.log(JSON.stringify(r));
 
}, function(e) {
 
    console.log(e);
 
});

上面代码暂时使用硬编码的搜索文本发起 API 调用请求,教程中稍后会变成动态获取的文本.

在模拟器运行应用时,你会需要运行 ‘adb logcat’ 来检查日志消息。

保存并运行. 点击搜索按钮,从 Flickr 返回的结果应该在终端上可见了.

接下来使用返回的响应创建图像的 url,并将其放入图像数组.

可观察的数据被用来创建一些事物的集合,并监听变化的发生。将相同的同一个可观察的数组绑定到视图,那样变化发生时视图就会更新了。

要创建可观察数据,可以在 main-page.js 中添加如下的变量声明 :

var observableArray = require("data/observable-array");
var images = new observableArray.ObservableArray([]);

基于从 API 请求返回的响应,下一步是创建 flickr 图片 URL。可以从这儿找到有关创建 flickr URL 的相关信息。

接下来我们对返回的数据进行遍历, 创建图像 URL 并放入图像数组。在 signin 函数中放入这些代码。

var imgUrl = '';
 
var photoList = r.photos.photo;
 
for (var i = 0; i < photoList.length; i++) {
    imgUrl = "https://farm" + photoList[i].farm + ".staticflickr.com/" + photoList[i].server + "/" + photoList[i].id + "_" + photoList[i].secret + ".jpg";
 
    images.push({
        img: imgUrl
    });
 
}
LeoXu
LeoXu
翻译于 2015/06/11 09:09
1

将数据绑定到 UI

图像数组里面有了数据,就可以绑定到UI了。为了能展现数据,在 main-page.xml 中创建一个 ListView , 就在现有的 Button 元素底下。

<ListView>
    <ListView.itemTemplate>
 
        <Image stretch="fill" height="200px" />
 
    </ListView.itemTemplate>
</ListView>

将图像数组绑定到 list 视图,设置图片的来源(src)。

 <ListView items="{{ images }}">
    <ListView.itemTemplate>
 
        <Image stretch="fill" height="200px" src="{{img}}" />
 
    </ListView.itemTemplate>
</ListView>

为了让图像数组在整个视图上可用,在 observable 模块中设置图像数组。为此导入 observable 模块,并用它来创建一个 observable 对象。

var observableModule = require("data/observable");
var pageData = new observableModule.Observable();

在 pageLoaded 函数中将图像数组设置到 observable 模块,并将模块添加到页面上下文中。

function pageLoaded(args) {
    var page = args.object;
    pageData.set("images", images);
    page.bindingContext = pageData;
}

使用相同的 pageData observable 对象,来自搜索文本框的值就可以被读取。修改文本域,加入 text 属性。

<TextField width="300px" text="{{txtKeyword}}"  hint="search keyword"/>

signin 函数中要删除硬编码的 hello 搜索文本,并像下面这样替换它:

pageData.get('txtKeyword')

保存并运行。点击搜索按钮,从 Flickr API 收到的图像就可以被看到了。请求返回了 5 张图片,因此向下滑动应该能看到所有的图片。

Images loaded from Flickr

总结

教程展示了如何开始使用 NativeScript 创建一个简单的移动应用。有关使用 NatieScript 的详细信息,我建议阅读 官方文档

你有使用 NativeScript 进行移动开发的经历吗? 使用它时你有什么感想 ? 让我们在评论中知道你的观点,建议以及修改意见。

LeoXu
LeoXu
翻译于 2015/06/11 09:21
1
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(35)

_icode
_icode

引用来自“Rango”的评论

我就想知道,为毛native script在最后发布APP的时候,如果选择release,他会告诉你:”payment required“???能不能不要钱?
哎呦,好像很久的帖子了,不过还是要回复下啦。你用的是web ide环境吧?那个就是收费的,native script和你用的那个在线编辑环境不是一个东西,那个是主要收费来源,这个ns是一个扩大它那个环境和竞争力的开源框架
来吧
来吧
之前听过他的讲座,这个是用XML写界面,另外就是没有成熟的APP做靠山了
Rango
Rango
我就想知道,为毛native script在最后发布APP的时候,如果选择release,他会告诉你:”payment required“???能不能不要钱?
libinqq
libinqq

引用来自“libinqq”的评论

但是 native script 学习环境是硬伤, 博客园等学习的文章都很少,反之react native 就一堆,QQ群,react native 就很多人也非常多, native script Q群和人太少。 真要写项目,不会的问题,react native Q群 论坛,很多人帮你, native script 就...
这是硬伤。 react native 至少有天猫团队戳着,github 1万多星,论坛,Q群帮助的人很多。
宋小康
宋小康
我觉得吧难度系数超过直接用java
_icode
_icode

引用来自“libinqq”的评论

React Native 它是将js 和 自定义控件编译为苹果的obj-c语言,最终还是原生态。还有一个好处就是,如果不满足,需要引用第三方程序,你也可以用xcode附加其他obj-c项目,扩展性强。
但是 React Native 目的是,让ios开发更简单,而不是一份代码多平台使用。

NativeScript 目的是一份代码多平台使用,但是就是太js了,无法附加其他原生态语言模块。

引用来自“张立鑫”的评论

很多部分是vdom理念,完全的react式,使用jsx,css解释器等构成,后端还是靠js执行,并没有解释成objc,你这个有点搞,不然就是我太久没关注了?记得这个项目还是我提交到OSC上的,之前一直在关注,后来看了实现兴趣骤减

引用来自“libinqq”的评论

React Native 运行原理我看是这样的,每个React Native 项目都会附带十几个obj-c语言写的解析模块,系统运行的时候,先加载你所有的项目js文件,然后合并为1个文件输出,在初始化时可以Chrome调试,初始化后它会把最终的js结果,给馈React Native 解析项目组,它们来负责将js结果转换为原生态的实现方式。

引用来自“张立鑫”的评论

我是这样理解的,js就是后端的server端,中间采用异步的通讯方式(可以理解为类似websocket,必须可以服务端主动推送的),UI层必须完成某些接口(可以理解为必须符和websocket协议),这些都是为了VDOM的实现。接下来,ui请求server,server缓存调整vdom,每隔60毫秒计算变更(diif),主动推送变化命令。你写的并不是什么解析,而是符合vdom计算的接口
所谓的直接拿第三方原生控件来用还是无法做到的,需要一层薄封装,让server感知/实施变化
_icode
_icode

引用来自“libinqq”的评论

React Native 它是将js 和 自定义控件编译为苹果的obj-c语言,最终还是原生态。还有一个好处就是,如果不满足,需要引用第三方程序,你也可以用xcode附加其他obj-c项目,扩展性强。
但是 React Native 目的是,让ios开发更简单,而不是一份代码多平台使用。

NativeScript 目的是一份代码多平台使用,但是就是太js了,无法附加其他原生态语言模块。

引用来自“张立鑫”的评论

很多部分是vdom理念,完全的react式,使用jsx,css解释器等构成,后端还是靠js执行,并没有解释成objc,你这个有点搞,不然就是我太久没关注了?记得这个项目还是我提交到OSC上的,之前一直在关注,后来看了实现兴趣骤减

引用来自“libinqq”的评论

React Native 运行原理我看是这样的,每个React Native 项目都会附带十几个obj-c语言写的解析模块,系统运行的时候,先加载你所有的项目js文件,然后合并为1个文件输出,在初始化时可以Chrome调试,初始化后它会把最终的js结果,给馈React Native 解析项目组,它们来负责将js结果转换为原生态的实现方式。
我是这样理解的,js就是后端的server端,中间采用异步的通讯方式(可以理解为类似websocket,必须可以服务端主动推送的),UI层必须完成某些接口(可以理解为必须符和websocket协议),这些都是为了VDOM的实现。接下来,ui请求server,server缓存调整vdom,每隔60毫秒计算变更(diif),主动推送变化命令。你写的并不是什么解析,而是符合vdom计算的接口
libinqq
libinqq

引用来自“libinqq”的评论

React Native 它是将js 和 自定义控件编译为苹果的obj-c语言,最终还是原生态。还有一个好处就是,如果不满足,需要引用第三方程序,你也可以用xcode附加其他obj-c项目,扩展性强。
但是 React Native 目的是,让ios开发更简单,而不是一份代码多平台使用。

NativeScript 目的是一份代码多平台使用,但是就是太js了,无法附加其他原生态语言模块。

引用来自“张立鑫”的评论

很多部分是vdom理念,完全的react式,使用jsx,css解释器等构成,后端还是靠js执行,并没有解释成objc,你这个有点搞,不然就是我太久没关注了?记得这个项目还是我提交到OSC上的,之前一直在关注,后来看了实现兴趣骤减
React Native 运行原理我看是这样的,每个React Native 项目都会附带十几个obj-c语言写的解析模块,系统运行的时候,先加载你所有的项目js文件,然后合并为1个文件输出,在初始化时可以Chrome调试,初始化后它会把最终的js结果,给馈React Native 解析项目组,它们来负责将js结果转换为原生态的实现方式。
libinqq
libinqq
但是 native script 学习环境是硬伤, 博客园等学习的文章都很少,反之react native 就一堆,QQ群,react native 就很多人也非常多, native script Q群和人太少。 真要写项目,不会的问题,react native Q群 论坛,很多人帮你, native script 就...
_icode
_icode

引用来自“libinqq”的评论

React Native 它是将js 和 自定义控件编译为苹果的obj-c语言,最终还是原生态。还有一个好处就是,如果不满足,需要引用第三方程序,你也可以用xcode附加其他obj-c项目,扩展性强。
但是 React Native 目的是,让ios开发更简单,而不是一份代码多平台使用。

NativeScript 目的是一份代码多平台使用,但是就是太js了,无法附加其他原生态语言模块。

引用来自“张立鑫”的评论

关于native script的评论我想说的是:恰恰相反,react native需要满足一套react接口才可以实现新的控件或第三方控件调用,而native script利用反射,如果你喜欢你可以直接在js里调用objc和java,你只需要按照命名规则写两个ui的js,当然,你完全可以直接写objc和java然后在用js调用,搞搞清楚,不要瞎说哦~
Native Script理念就是复用之前的类库不论是js还是native的,这个看下官方说明就知道了,github上代码也很明确的体现了这个特点
返回顶部
顶部