Chapter 3—Application Logic 应用逻辑

    • View(视图):视图代表UI,在 NativeScript 是写在XML文件里的。视图常与视图模型数据绑定,使得在JavaScript里对视图模型作的改动立即触发UI组件的视觉效果变化。

    • View Model(视图模型): 视图模型包含应用逻辑(通常包括模型),并把数据暴露给视图。NativeScript提供一个叫做“ Observable ”的模块,这有助于创建一个可以绑定到视图的视图模型对象。

    独立划分模型、视图和视图模型的最大好处是,你可以使用双向数据绑定;就是说,模型里面的数据变化会立即影响反应在视图上,反之亦然。另一个好处是代码重用,所以你经常可以跨视图使用模型和视图。

    杂货店里,目前你只接触了视图 (),在本章你将要创建一个视图模型。为此,我们首先需要向你介绍另外一种文件: code-behind(后台代码文件)。

    NativeScript里后台代码文件就是一份和视图有相同名字的JavaScript文件。比如,登录页面的视图叫作 login.xml,那么它的 台代码 文件就叫作 login.js。代码后置文件是你放置所有与视图本身进行交互的代码的地方。

    我们通过一个例子来看你在后台代码文件里能做什么。

    更改之后运行app, NativeScript 触发了你在后台代码文件里创建的 loaded() 方法,就会在命令行记录里看到“hello”。

    这个简单的例子展示了你如何能向UI组件添加属性来运行视图的伴生JS文件里的方法。我们来添加这些属性里的另外一个: tap

    操作: 激活按钮


    你可以添加一个能在用户点击或触摸按钮时触发的 tap 属性。在app/views/login/login.xml文件里,替换屏幕底部的两个按钮为使用此标记:

    <Button text="Sign in" tap="signIn" />

    <Button text="Sign up for Groceries" class="link" tap="register" />

    接着,在app/views/login/login.js 文件底部,粘贴下面的signIn() andregister() 方法:

    exports.signIn = function() {

    alert("Signing in");

    };

    exports.register = function() {

    };

    到此, 如果你运行app 并点击任一个按钮,你会看到相应的警告框弹出:

    既然你能看到点击手势生效,那就让它们做一些比弹出警告更有意思的事情吧。

    当你点击 “Sign up for Groceries” 按钮,你期望一个导航切换到注册页面。这在 NativeScript 里是非常简单就办到的。

    该方法使用了 frame 模块, 这个 NativeScript 模块在你的app里 负责导航。现在,你通知顶层 frame ,或者用户看到的 frame ,导航到注册视图。

    如果你运行app并点击 “Sign up for Groceries” 按钮,你会被带到我们已经为你预先搭建好的 注册界面。

    应用逻辑 - 图4

    既然你能进入注册界面,就跟着注册一个账户用于后面的的教程。

    操作: 注册一个账户


    打开杂货店点击 “Sign up for Groceries” 按钮进入注册页面。填写email地址和密码,点击 “Sign up” 按钮创建一个账户。

    你可以使用一个虚假的邮件地址和密码,一定记住你的登录凭据,因为后面会用到。

    提示:


    虽然我们的杂货店app不使用复杂的导航策略,你还有几种可能来跳出这个框框,比如**SegmentedBar。 SideDrawer 组件也可免费用在 Telerik公司的 **产品上。

    是时候看下数据如何在前段和后端之间来回流动的形式了。


    最后,编辑 signIn() 方法获取文本域 TextField 组件的引用并log它的内容:

    email = page.getViewById("email");

    console.log(email.text);

    所有的 NativeScript UI组件,包括 <Page>,都继承于 View 类,这赋予它们很多操作UI的方法。在本例你使用 getViewById() 方法通过其 id 属性来获取email文本域的引用。

    要看看这是如何实际工作的,启动app,在email文本域输入一些文本,然后点击 “Sign in” 按钮。如果一切正常,你会看到输入的文本记录在你的命令行了。

    应用逻辑 - 图6

    通过在 JavaScript 里获取UI组件,你能操作这些组件在前端的外观和行为。然而,单个地获取这些UI组件是非常手动的程序,也使得跟踪UI状态比较困难。这里就该视图模型出马了。

    NativeScript 通过一个叫做 ‘Observable’的模块 提供视图模型功能 。

    Observable就是 MVVM 设计模式里的视图模型。它提供了一个机制用于双向数据绑定,能够让UI和后台代码文件直接通讯。这意味着如果用户改变了UI里的数据,这个改变会自动反馈到视图模型,反之亦然。

    操作: 创建一个视图模型并绑定到视图

    要实现双向数据绑定需要使用 Observable ,打开 login.xml ,把现有的 TextField UI组件替换为下面的两个,每个都包含一个新的 text 属性:

    <TextField id="email" text="{{ email }}" hint="Email Address" keyboardType="email" autocorrect="false" autocapitalizationType="none" />

    <TextField secure="true" text="{{ password }}" hint="Password" />

    两对花括号包裹 text 属性值的用法界定了一个数据绑定值。你将在视图模型里用同样的名字设置相应的属性。

    添加下面的代码到 app/views/login/login.js 顶部。该代码从 observable 模块获得了 Observable 构造器的引用,并调用构造器定义了一个新的user对象,这就是你在本页使用到的视图模型

    现在,用下面的代码替换现有的 loaded()方法,它 user 设置为该页面绑定的上下文。

    exports.loaded = function(args) {

    page = args.object;

    page.bindingContext = user;

    };

    刚才发生了什么?

    1. 你正在基于 NativeScript的 Observable 模块创建一个 user 视图模型。你创这个视图模型带有两个属性: email and password,它们预先设置了些杂乱的值。

    简言之,放置在page的 binding context 里的属性可以由XML元素使用{ {属性名} }语法获取到。因为 JavaScript 设置了视图模型的 email 为 ,又因为你使用 <TextField text="{{ email }}"> 绑定了这个email地址 text field 到属性,所以运行app就会看到 “” 出现在前端。

    应用逻辑 - 图8

    真正酷的是这个绑定是双向的。这意味着,用户在文本域输入文本的时候,这些改动会立即反映到你的视图模型。