用离子创造器从静态走向动态


正如我已经不止一次提到的,我事实上满意多少Ionic Creator最近有所改善。对于这篇博文,我认为演示如何从“静态”的离子创建器概念证明到使用真正的应用编程接口的动态证明可能是有用的。对于铁杆开发者来说,这可能不会有太大帮助。但我认为Creator会吸引那些可能没有太多使用JavaScript和API经验的人,所以我认为一个具体的例子会有所帮助。一如既往,如果有什么说不通的地方,给我留言,我会尽力帮忙的。

让我们从讨论我们要构建的应用程序类型开始。这将是一个简单的“主/细节”示例,其中初始页面是一个项目列表,细节提供了非常详细的信息。作为一个完全随机的“与最近的任何事情都无关”的想法,让我们用星球大战电影作为我们的数据。

碰巧有一个应用编程接口存在,SWAPI,提供有关星球大战电影的信息。事实上,我已经为这个应用编程接口发布了一个助手库:SWAPI-Wrapper。我们不会在这篇博文中使用这个助手,但是如果你决定在一个真实的应用程序中使用这些数据,请记住这一点。

创建概念的静态证明

我们将从创建一个新的应用程序开始。请记住,这是100%免费的尝试。如果你想要额外的项目,你只需要支付。(您可以在他们的Pricing Page)。

首先创建一个新项目,名称无关紧要,并使用空白模板:

shot1

这将使您进入编辑界面,并显示一个空白页。在这一页,我们将做两件事。首先,我们将编辑标题,使其对应用程序有意义。

shot2

然后我们将列表组件拖到页面上:

shot3

请注意它如何自动添加3个列表项。如果你愿意,你可以去掉一些,或者增加一些,但是现在,三个就可以了。如果您单击每一个,您可以给它们一个唯一的文本值。虽然没有必要,但我会继续这样做,这样你就可以在心里记住我们实际在建造什么。

shot4

请注意,列表项具有“链接”属性。我们可以用它来给我们的演示添加基本的交互,但是现在,我们还没有一个页面来真正针对这个链接。让我们通过添加一个新页面来解决这个问题。请务必再次使用空白模板。我也给了它一个简单的标题:

shot5

这一页是这部电影的细节图。现在我们不一定知道我们要展示什么,所以让我们保持简单,想象我们将只展示开始爬行。我的读者可能从未看过《星球大战》电影(真遗憾),这是我的意思的一个例子:

crawl

现在,让我们只使用一点静态文本。将段落组件拖到页面上,然后将内容编辑为描述文本块用途的内容。

shot6

现在让我们把列表从第一页连接到细节。现在,在实际的应用程序中,每个列表项都会链接到一个页面,根据选择显示不同的文本。然而,动态方面将由我们稍后添加的代码来处理。如果你要向客户演示这个虚拟应用程序,你可能需要制作3个不同的页面,这样他们就不会混淆。如果你这样做了,别忘了你可以在左边的导航中选择页面,然后点击“复制”图标。

现在,单击返回第一页,并选择第一个列表项。请注意,您现在可以选择指向新页面的链接。

shot7

继续,对所有三个列表项都这样做(同样,你没有事实上需要),然后点击顶部的预览图标来测试你的美丽,如果假的,应用程序。

shot8

Woot!原型完成了!

创建应用程序-第1部分

好了,现在,我们有了一个工作原型。我们需要做的第一件事是获取代码的副本。您可以使用“导出”菜单选项打开一个窗口,显示四种不同的代码处理方式。我建议使用压缩文件。虽然我们可以直接用命令行界面从原型的代码创建一个新的应用程序,但我认为最好在本地拥有一个原型的副本,以便在处理新版本时进行比较和对比。

shot9

我建议为这个项目创建一个新文件夹,然后将zip解压到一个文件夹中。(我为这个博客条目编写的所有代码都在GitHub中,这也是我在那里布局的方式。)假设您在一个名为creator_version,我们可以使用离子键命令行界面根据内容创建新的应用程序。那个命令是:

ionic start v1 ./creator_version

“v1”部分是子目录的名称。正如您所猜测的,我们将从最初的创建者版本到最终版本进行一点迭代。为什么?

我们目前有一个静态版本的应用程序。它不使用任何“真实”数据。我们的第一次迭代将使应用程序动态化,但它将使用假的静态数据。

好吧,那听起来可能有点混乱。我再解释一下。

现在,我们的电影列表是3部电影的硬编码列表。

我们将在我们的应用程序中创建一个“服务”,负责返回电影列表。我们的计划是使用SWAPI远程服务,但为了保持简单,我们现在将建立一个返回3个“假”电影的服务。然后,我们将编辑第一页,将这些电影渲染成好像它们来自某个远程服务。本质上我们将从静态走向“有假数据的动态”。在我们运行良好之后,我们将使用“真正的”服务。(这部分流程很重要。所以如果说不通,在评论里告诉我。(

好了,进入v1文件夹,用你喜欢的编辑器打开。我们需要修改三件事来使初始页面动态化。先说模板。现在它是三部电影的硬编码:


<ion-view title="Star Wars Films">
    <ion-content overflow-scroll="true" padding="true" class="has-header">
        <ion-list>
            <ion-item href="#/page4">A New Hope</ion-item>
            <ion-item href="#/page4">The Empire Strikes Back</ion-item>
            <ion-item href="#/page4">Return of the Jedi</ion-item>
        </ion-list>
    </ion-content>
</ion-view>

我们将从移除两个离子项目开始,并使第三个动态化。


<ion-view title="Star Wars Films">
    <ion-content overflow-scroll="true" padding="true" class="has-header">
        <ion-list>
<ion-item ng-repeat="film in films" ui-sref="filmTitle({id:film.id})">{{film.title}}</ion-item>
        </ion-list>
    </ion-content>
</ion-view>

这里有两件重要的事情。首先,我们在重复“电影”而不是“影片”。我们还没有数据,但我知道当我建立它时,我会让它返回一系列的电影。我还猜想我会有一个标题值和一个唯一标识它的标识。(这其实会是个错误,不过没关系,是个好错误!(

现在我们来看看控制器。默认情况下,Creator为我们制作了一个名为starWarsFilmCtrl的空白。我们需要编辑它来处理数据。


.controller('starWarsFilmsCtrl', function($scope,FilmService) {
$scope.films = [];

FilmService.getFilms().then(function(res) {
$scope.films = res;
});

})

好吧,那电影服务到底是什么?我们还没写呢!基本上,我们将控制器设置为与一个服务一起工作,稍后我们将编写这个服务来返回我们的数据数组。注意我们使用$scope.films来设置初始的空数组。然后我们可以调用服务并设置结果。

让我们先更新另一个视图。详细信息页面是这样开始的:


<ion-view title="Film Title">
    <ion-content overflow-scroll="true" padding="true" class="has-header">
        <div>
            <p>The opening crawl would go here.</p>
        </div>
    </ion-content>
</ion-view>

我们需要使标题和文本动态化。以下是更新版本:


<ion-view>
<ion-nav-title>{{film.title}}</ion-nav-title>
    <ion-content overflow-scroll="true" padding="true" class="has-header">
        <div>
            <p>{{film.crawl}}</p>
        </div>
    </ion-content>
</ion-view>

为什么我们切换到离子导航标题?看见this blog post为了解释。基本上,我们需要使用该指令来处理动态标题。

好了,现在我们去更新控制器。


.controller('filmTitleCtrl', function($scope,$stateParams,FilmService) {
$scope.film = {};

FilmService.getFilm($stateParams.id).then(function(res) {
$scope.film = res;
});

})

像以前一样,我们正在使用一个尚不存在的电影服务。我以一种对我有意义的方式调用服务(首先是GetFilms,然后是GetFilms)。$stateParams部分涉及到我们如何处理导航。在第一个视图中,记下ui-sref部分。这处理改变到一个新的状态和传递一个唯一的id。为了做到这一点,我们需要对routes.js文件做一个小的修改。现在它有这个硬编码的路线:


    .state('filmTitle', {
      url: '/page4',
      templateUrl: 'templates/filmTitle.html',
      controller: 'filmTitleCtrl'
    })

为了处理识别身份,我们将其修改为:


    .state('filmTitle', {
      url: '/page4/:id',
      templateUrl: 'templates/filmTitle.html',
      controller: 'filmTitleCtrl'
    })

好了,现在是最后一部分,我们构建服务。我们将把它写成“同意”控制器所期望的。下面是完整的代码:


angular.module('app.services', [])

.factory('FilmService', ['$q',function($q){

return {
getFilms:function() {
var deferred = $q.defer();

//temp 
var films = [
{
id:1,
title:"A New Hope",
crawl:"ANH crawl"
},
        {
            id:2,
            title:"The Empire Strikes Back",
            crawl:"ESB crawl"
        },
        {
          id:3,
          title:"Return of the Jedi",
          crawl:"ROTJ crawl"
        }
];

  deferred.resolve(films);
  return deferred.promise;
},

getFilm:function(id) {
  var deferred = $q.defer();

  //temp
  var film = {
      id:id,
      title:"Film "+id,
      crawl:"Crawl for "+id
};

  deferred.resolve(film);
  return deferred.promise;
}
};

}]);

让我们快速回顾一下我们在这里做了什么。我们将完全静态的应用程序更新为部分地动态。初始页面(列表)和细节现在都是动态的。控制器与服务对话以请求数据,返回数据并使其可用于模板。数据本身可能是静态的,但是应用程序的其他方面现在都是动态的!呜。

在这一点上,我建议将该应用程序进行试驾,以确保其正常工作。这是它的运行ionic serve -l

shot10

如果需要,编辑服务文件以添加新影片。当你重新加载时,你会看到新的项目出现。

创建应用程序–第2部分

好的——所以理论上现在我们唯一需要做的就是更新服务文件来使用SWAPI。理论上。正如我之前提到的,我们会遇到一个小问题,但没关系——我们是专业人士,我们可以处理它。使用SWAPI非常容易(您可以阅读docs为了得到完整的解释),所以让我们从调用真实数据来获取电影开始。

以下是更新版本:


getFilms:function() {
var deferred = $q.defer();

$http.get("http://swapi.co/api/films").then(function(res) {
//console.dir(res.data.results);
deferred.resolve(res.data.results);
});
return deferred.promise;
},

对,就是这样。字面上只是对一个网址的调用。首先,我们修改了注入文件的服务:


.factory('FilmService', ['$http','$q',function($http,$q){

所以理论上,一旦你测试了这个,它就起作用了。你应该看到一个完整的电影列表:

shot11

然而,点击细节将不起作用。为什么?SWAPI实际上并不返回“id”值。注意上面代码片段中结果的console.dir?它目前已被注释掉,但如果您删除注释,您可以自己查看数据。这也有完整的记录。

那我们该怎么办?我们需要一种“独特的”方法来识别电影,这样我们就可以获取细节。原来有一个url电影的属性。这表明了这部电影在美国电影学会上的细节。我们有两个选择。我们实际上可以修改服务文件中的数据存在并使用网址。或者我们可以简单地修改模板以使用新属性。我更喜欢保持模板不变并修改服务。基本上,我的代码可以假装SWAPI按照我的预期返回了数据:


$http.get("http://swapi.co/api/films").then(function(res) {
//console.dir(res.data.results);
var results = res.data.results.map(function(result) {
result.id = result.url;
return result;
});
deferred.resolve(results);
});

最后的修改是为了获得影片细节。我们正在传递网址值,所以这里的代码相当简单:


getFilm:function(url) {
var deferred = $q.defer();

$http.get(url).then(function(res) {
//console.dir(res.data);
deferred.resolve(res.data);
});

return deferred.promise;

}

结果是:

结束

显然,每个应用程序都是不同的,我们的应用编程接口特别简单,但我希望这个演示是有用的。如果你想看代码,你可以在这里找到它:https://github.com/cfjedimaster/Cordova-Examples/tree/master/statictodynamic。如我所说,如果有什么说不通的,请告诉我。

你已经看过帖子了,现在看视频!