欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【翻译】Part 3 - FlickrView: Implementing FeedView

程序员文章站 2022-05-30 09:59:01
...
英文原链接:http://dojotoolkit.org/documentation/tutorials/1.9/mobile/flickrview/part3/
上一篇,开发一个移动应用程序,我们构建了通用布局模板和搭建了一个静态应用。本篇将静态内容更新为从Flickr动态获取数据和展示feeds.你会学到从JSON获取响应内容和处理异常,使用进度表表示在等待服务器的返回,动态填充队列,使用基本HTML模板创建队列和将数据格式化为特定的语言环境。准备好了吗?我们开始!
应用数据结构
我们要组织JSON请求结构,并通过JSON返回更新页面,我们在HTML文件声明一个合局范围的基本数据结构。该对象要求:
  • 包含查询参数的JSON请求,用于Feed view
  • 根据用户在Settings view的输入进行更新

require([
    //...
    ], function (parser) {
        flickrview = {};
        flickrview.QUERY = {
            tags: "famous,bridges",
            tagmode: "all",
            format: "json",
            lang: "en-us"
        };
        //...
    });

这就定义完成,任务组件都可以set和get flickrview.QUERY.
FeedView属性
Feed view负责获取和显示最新上传到Flickr上的照片,我们需要一个url和一些参数通过JSONP请求来取得Flickr公共服务:
// Flickr public feed URL to pull recent photo uploads from 
requestUrl: "http://api.flickr.com/services/feeds/photos_public.gne",
 
// JSONP request options and query parameters
requestOptions: {
    jsonp: "jsoncallback",
    preventCache: true,
    timeout: 10000,
    query: null
},

请求参数在调用之前将动态设置,更多的Dojo请求参数,参见Dojo request Reference Guide.
参见静态页面,你会发现照片列表需要特别格式化以包括标题、发布时间和任务信息。我们来创建一个适应照片feed模板的属性:
// Create a template string for a photo ListItem
flickrviewItemTemplateString:
    '<img src="${photo}" width="80px" height="80px" alt="${title}" style="float:left;"/>' +
    '<div class="photoSummary">' +
        '<div class="photoTitle">${title}</div>' +
        '<div class="publishedTime">${published}</div>' +
        '<div class="author troncatedText">${author}</div>' +
    '</div><div class="summaryClear"></div>',

我们也定义一个方法替代模板变量:
substitute: function(template,obj) {
    return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g, function(match,key){
        return obj[key];
    });
}

继续小部件的引用,初始化工作将在开始方法中完成
//...
refreshButton: null,
feedList: null,
feedHeading: null,
progressIndicator: null,
detailsContainer:null,
detailsHeading:null,
//...

FeedView启动
在解析和创建的子部件都完成之后,Dojo小部件启动任务被调用一次,下面我们来一行行解读:
startup: function() {this.inherited(arguments);

startup方法继承自dojox/mobile/ScrollableView,进而继承自dijit/_WidgetBase.所以我们调用this.inherited(arguments).
Startup是Dojo小部件生命周期的一部分,参见这里更多Dojo小部件生命周期:dijit/_WidgetBase Reference Guide.(http://dojotoolkit.org/reference-guide/dijit/_WidgetBase.html)
来自dijit/registry的byId方法用于查找组件引用:
// retain widgets references
this.refreshButton = registry.byId("refreshButton");
this.feedList = registry.byId("feedList");
this.feedHeading = registry.byId("feedHeading");
this.detailsContainer = registry.byId("detailsContainer");
this.detailsHeading = registry.byId("detailsHeading");

ProgressIndicator是用于表明当前任务正在进行的图像,我们在等视图刷新时会用到。
this.progressIndicator = ProgressIndicator.getInstance();


这里可参考更多使用和自定义ProgressIndicator的信息:Reference Guide.(http://dojotoolkit.org/reference-guide/dojox/mobile/ProgressIndicator.html)

我们给刷新按钮增加点击事件,这里声明的this.refresh方法我们在下一篇定义。注意,使用lang.hitch方法用于确保回调函数this.refresh将在小部件实例的上下文中被调用:
// add click handler to the button that call refresh
this.refreshButton.on("click", lang.hitch(this, this.refresh) );

FeedView刷新
刷新方法负责从Flickr取得照片和更新视图。首先,我们移动列表中的任何内容,然后显示等待动画:
// remove all list items
this.feedList.destroyDescendants();
// reset scroll to make sur progress indicator is visible
this.scrollTo({x:0,y:0});
// add progress indicator
this.feedHeading.set('label',"loading...");
this.feedList.domNode.appendChild(this.progressIndicator.domNode);
this.progressIndicator.start();

现在我们发送一个JSON请求给Flickr:
// request feed from Flickr
this.requestOptions.query = flickrview.QUERY;
scriptRequest.get(this.requestUrl, this.requestOptions).then(lang.hitch(this, this.onFlickrResponse), lang.hitch(this, this.onFlickrError));

真正更新列表的工作是我们的两个回调函数完成的:onFlickrResponse(成功响应)和onFlickrError(异常).
你可以在浏览器中输入这个请求,获取详细数据:http://api.flickr.com/services/feeds/photos_public.gne?tags=famous,bridge&lang=en-us&format=json
处理JSON响应
onFlickrResponse方法处理成功响应,我们一行行了解。首先停止进度示意动画然后更新标题:
// remove progress indicator
this.progressIndicator.stop();
this.feedList.destroyDescendants();
// restore the title
this.feedHeading.set('label','Feeds');

遍历结果项:
// populate the list
array.forEach(result.items, lang.hitch(this, function (resultItem)

为每一项创建dojox/mobile/ListItem并加到队列的末尾:
// Create a new ListItem at the end of the list
var listItem = new ListItem({}).placeAt(this.feedList, "last");

设置样式,使用简单HTML模板注入列表项内容:
// set custom style
domClass.add(listItem.domNode, "photoListItem");
// create and insert content from template and JSON response
listItem.containerNode.innerHTML = this.substitute(this.flickrviewItemTemplateString, {
    photo: resultItem.media.m,
    title: resultItem.title,
    published: locale.format(new Date(resultItem.published), {locale:flickrview.QUERY.lang}),
    author: resultItem.author
});

先不理会published属性的格式化,我们在谈到本地化环节会详细说明。
点击列表项会触发切换到详情视图,切换之前我们需要更新详情视图的内容。所以我们给列表项增加点击处理函数:
listItem.onClick = lang.hitch(this, function(){
    // update details view before transitioning to it
    this.detailsContainer.domNode.innerHTML = resultItem.description.replace(/href=/ig,"target=\"_blank\" href=");
    listItem.set("transition","slide");
    listItem.transitionTo("details");
});

注意,我们加入target属性来强制所有的链接都打开新浏览页。这在链接到外网站时是最佳的实践方式。
因为我们以编程方式实现跳转,所以设置moveTo属性为#,这样小部件就不会使用自身的跳转动作。
listItem.set("moveTo","#");

异常处理比较简单:停止进度示意动画,在标题栏显示异常信息通知用户。
onFlickrError: function(error) {
    // remove progress indicator
    this.progressIndicator.stop();
    this.feedList.destroyDescendants();
    // display error message
    this.feedHeading.set('label',error);
    alert(error);
}

接下就要测试第一个“可执行版本”的应用了!就差配置应用的本地化日期格式。
使用本地化日期格式
在JSON请求,我们指定返回数据本地化要求,但返回的数据是没有格式化的(像这样原始的形式:2013-09-15T07:57:04Z)。Dojo提供很多功能来本地化你的应用,这里我们使用一个方法来格式化:
published: locale.format(new Date(resultItem.published),{locale:flickrview.QUERY.lang}),

因为我们强制本地化(默认情况下,Dojo使用浏览器的本地化设置),所以需要指定本地化列表,Dojo必须能从配置中加载起来。我们会用到配置参数extraLocale:
dojoConfig = {
    async: true,
    baseUrl: './',
    parseOnLoad: false,
    mblHideAddressBar: true,
    extraLocale: ["en-us", "fr-fr", "de-de", "it-it", "ko-kr", "pt-br", "es-us", "zh-hk"],
    packages: [{
        name: "flickrview",
        location: "js"
    }]
};

最后就是应用启动时的自动刷新:
// Parse the page for widgets
parser.parse();
// refresh at startup
registry.byId("feed").refresh();

所有代码完成,FeedView现在从Flickr获取内容了!点击下面链接查看效果和浏览全部代码。下一节将要实现Settings view修改请求参数。
VIEW DEMO

下载源代码

下载 Part 3 - FlickrView: Implementing FeedView.

============================================
Part 3 END
next Part 4 - FlickrView: Implementing SettingsView