Dojo mobile TweetView 系列教程之四 —— 创建Setting视图

Dojo mobile TweetView 系列教程之四 —— 创建Setting视图

分类: Javascript Dojo扩展 (dojox) 综合 Dojo Mobile   1888人阅读  评论(0)  收藏  举报
 

目录(?)[+]

 

作者:David Walsh

翻译:Siqi ([email protected]

原文:TweetView: Creating the Settings View

在上一篇教程Dojo mobile TweetView 系列教程之三——Tweets和Mentions视图 中,我们夯实了TweetView应用程序的文件结构,回顾了创建TweetView的目标并通过编写tweetview._ViewMixin和tweetview.TweetView创建了Tweets和Mentions视图。本教程将重点介绍TweetView中的"Setting"视图:类的依赖关系、Setting视图是如何和Tweet、Mention视图联系在一起的、并编写Setting视图的代码。

版本:1.6

难度:中级

系列:TweetView

“Settings”视图的依赖关系

Settings视图是三个视图中最简单的。该视图包含两个标题(主标题和副标题),和一个Twitter账户列表,每一个Twitter账户都对应着一个开关用以控制该账户的信息是否需要在其他两个视图中显示。在看过下面的效果图之后,可以知道将会用到以下控件:

  • dojox.mobile.ScrollableView - 整个视图
  • dojox.mobile.Heading - 主标题"Setting"
  • dojox.mobile.RoundRectCategory - 副标题"Show"
  • dojox.mobile.RoundRectList - 账户列表容器
  • dojox.mobile.ListItem - 账户列表元素
  • dojox.mobile.Switch - 开关空间

该效果图还清楚的说明了我们将会需要从Twitter获取用户的头像信息,因此我们还需要一些其他的Dojo资源:

  • dojo.io.script - 使用JSONP从Twitter获取信息
  • dojo.DeferredList - 让我们可以一次处理多个Twitter信息请求所返回的数据

这些资源将帮助我们顺利完成Settings视图。与我们创建Tweets和Mentions视图的做法类似,我们将为Settings视图创建一个自定义类:SettingsView。

!如果我们不在Settings视图显示用户的头像信息,我们就不需要dojo.io.script和dojo.DeferredList。我们可以写死这些头像图片的路径,但是这样的话我们需要在每次用户更改他们头像时手动更新这些图片的路径。幸运的是我们之前创建的TweetView视图的代码已经包含了这些资源,所以在Settings视图中使用它们不会导致代码膨胀——这些资源提供的类已经可以用啦!

开发Setting视图

我们的SettingsView类和TweetView类非常相似,他们都继承dojox.mobile.ScrollableView和tweetview.ViewMixin。很重要的一点是SettingView类只是一个包装了整个应用程序用以获取账户信息的tweetview.ACCOUNTS对象的容器。在明白了这一点之后让我们看一下Settings视图的具体实现吧。

新的类:Settings视图

我们新的类叫做SettingsView,它的基础结构和TweetView一样:

[javascript]  view plain copy
 
  1. // 提供UI类dojo.provide("tweetview.SettingsView"); // 导入依赖项dojo.require("dojox.mobile.ScrollableView");dojo.require("dojo.DeferredList");dojo.require("dojo.io.script");dojo.require("tweetview._ViewMixin"); // 声明类;它继承自ScrollableViewdojo.declare("tweetview.SettingsView", [dojox.mobile.ScrollableView, tweetview._ViewMixin], { // 这里将添加方法和属性 });  

依赖项已经被导入,我们的类也已经声明完毕。

!该类将被被放在TweetView和_ViewMixin同一个文件夹下:js/tweetview

SettingsView的属性

SettingsView将有三个自定义属性。第一个是accountTemplateString:一个包含HTML标签的字符串,用以表示帐号列表中每一个列表元素的布局。

[javascript]  view plain copy
 
  1. // 模板字符串accountTemplateString: '<img src="${avatar}" mce_src="${avatar}" alt="${user}" class="tweetviewAvatar" />' +'<div class="tweetviewContent">' +'<div class="tweetviewUser">${user}</div>' +'</div><div class="tweetviewClear"></div>',  

第二个属性是views,它代表TweetView实例。为什么SettingsView需要知道TweetView实例的ID呢?因为SettingsView需要根据每一个账户的开关状态调整其对应的TweetsView实例中的tweets。views属性接受一个由多个TweetView实例的ID所组成的字符串,每个ID以逗号分隔开。

[javascript]  view plain copy
 
  1. // SettingsView所引用到的TweetView视图views: "",  

最后一个自定义属性是serviceUrl:

[javascript]  view plain copy
 
  1. // 用以获取用户信息的URL,这里已经提供了一个简单的URL模板serviceUrl: "http://api.twitter.com/1/users/show/${account}.json",  

serviceURL属性代表用来获取用户信息的Twitter服务URL。对于SettingsView来说,我们只需要获取用户的头像。

实现SettingsView

现在SettingsView的框架已经搭好(尽管它现在还干不了什么),是时候更新Settings视图的HTML部分了:

[xhtml]  view plain copy
 
  1. <!-- settings 视图 --><div id="settings" dojoType="tweetview.SettingsView" views="tweets,mentions">    <h1 dojoType="dojox.mobile.Heading" fixed="top">Settings</h1>    <h2 dojoType="dojox.mobile.RoundRectCategory">Show</h2>    <ul dojoType="dojox.mobile.RoundRectList" class="tweetviewList"></ul></div>  

下面是我们所做的改动:

  • 该控件的dojoType已经改成了我们的新类:tweetview.SettingsView。
  • 设置views属性为“tweets, mentions”;即TweetView和MentionView的ID。
  • 为RoundRectList节点添加了tweetviewList CSS类,这样该控件可以被分辨出来,并获取其引用

当然我们需要在我们的app.html页面顶部导入tweetview.SettingsView类

[javascript]  view plain copy
 
  1. // 使用轻量级的parserdojo.require("dojox.mobile.parser");// 导入Dojo mobiledojo.require("dojox.mobile");// 导入额外的、非标准的dojox.mobile控件dojo.require("dojox.mobile.TabBar");// 导入兼容包dojo.requireIf(!dojo.isWebKit,"dojox.mobile.compat");// 导入TweetViewUIdojo.require("tweetview.TweetView");dojo.require("tweetview.SettingsView");// 直接在命名空间下设置tweetview账户信息tweetview.ACCOUNTS = {    dojo: { enabled: true },    sitepen: { enabled: true }};  

在将SettingsView添加到app.html页面之后,是时候创建JavaScript部分了。

SettingsView _startup()

SettingsView类的startup方法是SettingsView工作的关键。让我们一步步看下去。首先是调用父类(dojox.mobile.ScrollableView)的startup方法来获取原本的功能:

[javascript]  view plain copy
 
  1. // 获取 dojox.mobile.ScrollableView 的startup功能this.inherited(arguments);  

获取视图中list控件的引用,并在添加列表元素之前隐藏它。

[javascript]  view plain copy
 
  1. // 获取list子控件this.listNode = this.getListNode();// 隐藏list控件,因为它还没被填充this.showListNode(false);  

创建一个账户数组并将它们排序,这样他们就能按字母顺序在视图中显示了

[c-sharp]  view plain copy
 
  1. // 将帐号排序var accounts = [];for(var account in tweetview.ACCOUNTS) {    accounts.push(account);}accounts.sort();  

创建以请求Twitter用户信息返回的Deferred组成的数组:

[javascript]  view plain copy
 
  1. // 创建一个容纳deferred的数组var defs = [];// 处理每个账户dojo.forEach(accounts, function(account){    // 请求用户信息    defs.push(dojo.io.script.get({        callbackParamName: "callback",        timeout: 3000,        // "substitute"继承自_ViewMixin        url: this.substitute(this.serviceUrl, { account: account })    }));},this);  

!你将会看到根据serviceUrl参数和一个包含账户名的对象生成URL。substitue方法继承自_ViewMixin,SettingsView也继承自该类。

在Twitter请求触发之后,获取TweetView空间的引用:

[javascript]  view plain copy
 
  1. // 获取视图控件this.viewWidgets = dojo.map(this.views.split(","), function(id) {    return dijit.byId(id);});  

剩下的功能在所有用户信息获取完毕后在dojo.DeferredList的回调函数中实现。对于每一个我们要获取信息的账户,如果账户存在并没有设置保护:

[javascript]  view plain copy
 
  1. // 创建一个deferred列表以添加进行格式化的回调函数new dojo.DeferredList(defs).then(dojo.hitch(this, function(results) {     // 对于每个返回的用户数组...    dojo.forEach(results, function(def,i) {         // 如果deferred失败,那么用户帐号不存在或者不可用        if(!def[0]) {            // 移除该帐号防止发生更多问题            // 同时从我们本地经过排序的账户列表中删除该账户            delete tweetview.ACCOUNTS[accounts[i]];            delete accounts[i];            return;        }         // 获取用户数组        var user = def[1];         // 如果用户存在并且没有被冻结或是保护...        if(user.id && !user["protected"]) { // Protected是一个保留字             // 之后这里会有更多代码         }     },this); }));  

创建一个新的dojox.mobile.ListItem并使用我们的用户信息模板填充它:

[javascript]  view plain copy
 
  1. // 为用户创建一个新的列表元素,附带一个开关var item = new dojox.mobile.ListItem({}).placeAt(this.listNode, "last"); // 使用我们的模板更新元素列表内容item.containerNode.innerHTML = this.substitute(this.accountTemplateString, {    user: user.screen_name,    avatar: user.profile_image_url,    user_id: user.id});  

为列表元素创建一个dojox.mobileSwitch控件,我们需要考虑账户的启用状态:

[javascript]  view plain copy
 
  1. // 创建开关var userSwitch = new dojox.mobile.Switch({    "class": "tweetviewSwitch",    value: tweetview.ACCOUNTS[user.screen_name].enabled ? "on" : "off"}).placeAt(item.containerNode, "first");  

为Switch控件添加onStateChange事件,在该事件中将会更新tweetview.ACCOUNTS对象的启用状态。另外,通知TweetView实例帐户的启用状态:

[javascript]  view plain copy
 
  1. // 为开关添加change事件dojo.connect(userSwitch, "onStateChanged", this, function(newState) {    // 获取 true/false 值    var isOn = newState == "on";         // 更新ACCOUNTS表    tweetview.ACCOUNTS[user.screen_name].enabled = isOn;         // 调用每一个Pane控件的onUserChange方法    dojo.forEach(this.viewWidgets, function(viewWidget) {        viewWidget.onUserChange(user.screen_name,isOn);    });});  

最后,如果我们收到了任何有效帐号,显示Settings列表节点(因为现在它已经有内容了)并刷新每一个视图。

[javascript]  view plain copy
 
  1. // 如果我们有任何有效账户...if(accounts.length) {    // 显示有内容的列表    this.showListNode(true);    // 出发每个视图的refresh方法    dojo.forEach(this.viewWidgets, function(view) {        view.refresh();    });}  

tweetview.Setting的JavaScript代码完成了 ——这个控件现在可以正确工作啦!不过我们还没有完成所有的JavaScript代码!我们还需要为TweetView类实现onUserChange方法。

TweetView更新:onUserChange并从startup()中移除refresh()

我们之所以在SettingsView中调用每个视图的refresh方法,是因为我们不想为那些确定无效的账户向Twitter发出请求。但不幸的是我们之前已经在TweetView的startup中调用了refresh方法。现在让我们移除它:

[javascript]  view plain copy
 
  1. // 获取tweets//this.refresh();  

SettingsView实例将会在确认一个账户是有效的时调用视图的refresh方法。

onUserChange方法在某个账户被启用或者禁用时被SettingsView调用。我们有几种处理启用/禁用的方式:

刷新整个控件 - 会浪费资源和Twitter API的使用率

销毁ListItem控件,并重建它们 - 开销太大,如果用户马上又启用了账户怎么办呢? 那样会导致重新获取所有用户的tweets。这样干的话还会破坏我们的缓存功能。

使用CSS显示/隐藏列表元素 - 就是它了!开销很小,我们已经获取了需要的数据,不需要重复获取它们!

在TweetView中实现这一方法:

[javascript]  view plain copy
 
  1. // 根据用户的账户启用属性更新一个tweet的显示属性onUserChange: function(account,isOn) {    dojo.forEach(this.getElements("user-" + account,this.domNode), function(node){        dojo[(isOn ? "remove" : "add") + "Class"](node, "tweetviewHidden");    });}  
 

还记得user-{screenName} CSS类已经被分配给了tweetview.TweetView中的列表元素么?我们将使用这个CSS类来找出需要被启用/禁用的用户,并为它们移除/添加一个新的名为tweetviewHidden的CSS类,用以将一个列表元素设置为display:none或者display:block。

设置SettingsView样式

HTML和JavaScript部分都已经完成了,现在为我们的样式表添加一些CSS类来使得列表看起来和效果图里的一样:

[css]  view plain copy
 
  1. /* 开关在右边 */.tweetviewSwitch {    right:10px;    top:10px;    float:right;} /* 为禁用的用户隐藏对应的tweet */.tweetviewHidden {    display:none;}  

TweetView 完成了!

tweetview.TweetView在上一篇教程中已经完成,本教程又完成了tweetview.SettingsView,我们的控件已经大功告成了!点这里来查看我们的控件。

在本系列最后一篇教程中我们将使用Dojo的打包系统来压缩TweetView所用的JavaScript,HTML和CSS,使得整个程序更紧凑。

http://blog.csdn.net/dojotoolkit/article/details/6535813

猜你喜欢

转载自lishuaishuai.iteye.com/blog/1953282
今日推荐