最新版本我将会放在:这里的示例里面,这里不会再做更新
代码:
1 /* 2 *模仿且改进NavigationView 3 *返回时自动销毁视图,节约内存 4 */ 5 Ext.define('ux.CardPanel', { 6 extend: 'Ext.Container', 7 xtype: 'cardPanel', 8 requires: ['Ext.TitleBar'], 9 config: { 10 //顶部导航条 11 navBar: { 12 docked: 'top' 13 }, 14 //布局,type不可更改 15 layout: { 16 type: 'card', 17 animation: { 18 duration: 300, 19 easing: 'ease-out', 20 type: 'slide', 21 direction: 'left' 22 } 23 }, 24 //顶部控件组,在子项中配置 25 navBarItems: null, 26 //返回按钮 27 backBtn: { 28 align: 'left', 29 ui: 'back' 30 }, 31 //返回按钮显示状态,在子项中配置 32 backHide: false, 33 //临时cls,在子项中配置 34 pCls: null, 35 //底部导航栏、可选格式btmBar:'xtype',在子项中配置 36 btmBar: null, 37 //当子项被激活后移除除了指定项之外的项,在子项中配置 38 nRemove: null 39 }, 40 //初始化 41 initialize: function () { 42 var layout = this.getLayout(); 43 if (layout && !layout.isCard) { 44 Ext.Logger.error('CardPanel中layout的布局只能是card布局'); 45 } 46 this.initStatus(); 47 }, 48 //初始化历史记录 49 initStatus: function () { 50 if (!this.viewStack) { 51 //历史记录 52 this.viewStack = []; 53 //视图加载状态 54 this.viewStatus = {}; 55 } 56 }, 57 //更新返回按钮显示状态 58 updateBackHide: function (newItem, oldItem) { 59 var backBtn = this.getBackBtn(); 60 if (newItem) { 61 backBtn.hide(); 62 } else { 63 backBtn.show(); 64 } 65 }, 66 //更新底部导航栏 67 updateBtmBar: function (newItem, oldItem) { 68 if (oldItem) { 69 oldItem = this.down(oldItem); 70 this.remove(oldItem); 71 } 72 if (newItem) { 73 newItem = Ext.create(newItem); 74 this.add(newItem); 75 } 76 }, 77 //创建导航栏控件组 78 applyNavBarItems: function (newItems) { 79 if (!newItems) return false; 80 var me = this, 81 navItems = [], 82 i, 83 ln; 84 newItems = Ext.Array.from(newItems); 85 for (i = 0, ln = newItems.length; i < ln; i++) { 86 navItems.push(me.factoryItem(newItems[i])); 87 } 88 return navItems; 89 }, 90 //更新导航栏控件组 91 updateNavBarItems: function (newItem, oldItem) { 92 var navBar = this.getNavBar(); 93 if (oldItem) { 94 var i, ln; 95 for (i = 0, ln = oldItem.length; i < ln; i++) { 96 navBar.remove(oldItem[i]); 97 } 98 } 99 if (newItem) {100 navBar.add(newItem);101 }102 },103 //创建顶部导航栏104 applyNavBar: function (config) {105 return Ext.factory(config, Ext.TitleBar, this.getNavBar());106 },107 //更新顶部导航栏108 updateNavBar: function (newItem, oldItem) {109 if (oldItem) {110 this.remove(oldItem);111 }112 if (newItem) {113 this.add(newItem);114 }115 },116 //更新临时cls117 updatePCls: function (newItem, oldItem) {118 if (oldItem) {119 this.removeCls(oldItem);120 }121 if (newItem) {122 this.addCls(newItem);123 }124 },125 //创建返回按钮126 applyBackBtn: function (config) {127 return Ext.factory(config, Ext.Button, this.getBackBtn());128 },129 //更新返回按钮130 updateBackBtn: function (newItem, oldItem) {131 if (oldItem) {132 this.getNavBar().remove(oldItem);133 }134 if (newItem) {135 this.getNavBar().add(newItem);136 newItem.on({137 scope: this,138 tap: this.onBackButtonTap139 });140 }141 },142 //更新移除143 updateNRemove: function (newItem, oldItem) {144 var animation = this.getLayout().getAnimation();145 if (oldItem) {146 //移除动画结束监听147 animation.un({148 scope: this,149 animationend: 'onAnimationend'150 });151 }152 if (newItem) {153 //添加动画结束监听154 animation.on({155 scope: this,156 animationend: 'onAnimationend'157 });158 }159 },160 /**161 * 移除历史记录162 * @private163 */164 viewStackPop: function (count) {165 for (var i = 0; i < count; i++) {166 this.viewStack.pop();167 }168 },169 //添加视图170 //注意xtype是指alternateClassName171 push: function (xtype, params) {172 var me = this,173 view = this.getActiveItem(),174 oldXtype = view && (view.config.xtype || view.getItemId());175 /*过滤已经添加的视图*/176 if (!this.viewStatus[xtype]) {177 params = params || {};178 params.itemId = xtype;179 view = Ext.create(xtype, params);180 this.add(view);181 } else if (oldXtype != xtype) {182 this.viewStack.push(xtype);183 this.setActiveItem(xtype);184 }185 },186 //当动画效果结束时,子项配置了nRemove属性将会激活187 onAnimationend: function () {188 // console.log('animationend');189 this.popAll(this.getNRemove());190 },191 //项被激活192 onActivate: function (view) {193 var config = view.config;194 // console.log('activate', config.xtype || view.getItemId());195 //更新后退按钮196 // console.log('setBackHide', this.viewStack);197 this.setBackHide(config.backHide || this.viewStack.length == 1);198 //更新按钮组199 var items = config.navBarItems || false;200 this.setNavBarItems(items);201 //更新cls202 var pCls = config.pCls || false;203 this.setPCls(pCls);204 //更新标题205 var title = config.title || '';206 this.getNavBar().setTitle(title);207 //更新底部导航栏208 var btmBar = config.btmBar || false;209 this.setBtmBar(btmBar);210 //更新移除211 var nRemove = config.nRemove || false;212 this.setNRemove(nRemove);213 },214 //项被销毁215 onDestroy: function (view) {216 // console.log('onDestroy', view.config.xtype || view.getItemId());217 this.viewStatus[view.config.xtype || view.getItemId()] = false;218 },219 /**220 * 不填写参数时,移除当前项,返回到上一项221 * 如果参数是数字,则从最后一项开始移除指定数目的项222 * 如果参数是string,则移除指定类型的项223 * 如果参数是项,则移除传入的项224 * 不论参数如何,都会保留一个活动项225 * @return {Ext.Component} 当前活动项226 */227 pop: function (count) {228 if (this.beforePop(count)) {229 return this.doPop();230 }231 },232 /**233 * @private234 *删除指定项235 */236 beforePop: function (count) {237 var me = this,238 innerItems = me.getInnerItems();239 if (Ext.isString(count) || Ext.isObject(count)) {240 var last = innerItems.length - 1,241 i;242 for (i = last; i >= 0; i--) {243 if ((Ext.isString(count) && Ext.ComponentQuery.is(innerItems[i], count)) || (Ext.isObject(count) && count == innerItems[i])) {244 //获得移除项序号245 count = last - i;246 break;247 }248 }249 if (!Ext.isNumber(count)) {250 return false;251 }252 }253 var ln = innerItems.length,254 toRemove;255 //默认移除一项256 if (!Ext.isNumber(count) || count < 1) {257 count = 1;258 }259 //当我们试图移除更多视图时260 count = Math.min(count, ln - 1);261 if (count) {262 this.viewStackPop(count);263 //开始移除视图264 toRemove = innerItems.splice(-count, count - 1);265 for (i = 0; i < toRemove.length; i++) {266 this.remove(toRemove[i]);267 }268 return true;269 }270 return false;271 },272 /**273 * @private274 *移除最后一项275 */276 doPop: function () {277 var me = this,278 innerItems = this.getInnerItems(),279 ord = innerItems[innerItems.length - 1];280 me.remove(ord);281 //触发被移除项的事件282 return this.getActiveItem();283 },284 doResetActiveItem: function (innerIndex) {285 var me = this,286 innerItems = me.getInnerItems(),287 animation = me.getLayout().getAnimation();288 if (innerIndex > 0) {289 if (animation && animation.isAnimation) {290 animation.setReverse(true);291 }292 me.setActiveItem(innerIndex - 1);293 }294 },295 /**296 * @private 297 *执行移除项,调用remove方法后自动执行298 */299 doRemove: function () {300 var animation = this.getLayout().getAnimation();301 if (animation && animation.isAnimation) {302 animation.setReverse(false);303 }304 this.callParent(arguments);305 },306 /**307 * @private 308 *执行添加项,调用add方法后自动执行309 */310 onItemAdd: function (item, index) {311 if (item.isInnerItem()) {312 var xtype = item.config.xtype || item.getItemId();313 //如果配置了items,会先于initialize执行,所以需要初始化历史纪录314 this.initStatus();315 this.viewStatus[xtype] = true;316 this.viewStack.push(xtype);317 //添加监听318 item.on({319 scope: this,320 activate: 'onActivate',321 destroy: 'onDestroy'322 });323 }324 this.doItemLayoutAdd(item, index);325 if (!this.isItemsInitializing && item.isInnerItem()) {326 this.setActiveItem(item);327 }328 if (this.initialized) {329 this.fireEvent('add', this, item, index);330 }331 },332 /**333 * 移除第一项和最后项之间的所有项(包括最后项)334 * @return {Ext.Component} 当前活动视图335 */336 reset: function (noUp) {337 return this.pop(this.getInnerItems().length);338 },339 //除了指定项,从倒数第二项开始移除340 popAll: function (xtype) {341 var me = this,342 innerItems = this.getInnerItems(),343 length = innerItems.length - 1,344 oldXtype,345 ord,346 i;347 this.viewStack = [xtype];348 for (i = length; i > -1; i--) {349 /*过滤掉需要显示的视图*/350 ord = innerItems[i];351 oldXtype = ord.config.xtype || ord.getItemId();352 if (i == length) {353 me.viewStack.push(oldXtype);354 } else if (oldXtype != xtype) {355 me.remove(ord, true);356 }357 }358 },359 //返回上一个历史记录360 onBackButtonTap: function () {361 this.pop();362 this.fireEvent('back', this);363 }364 });
主视图js:
1 /* 2 *主视图,负责视图切换 3 */ 4 Ext.define('app.view.Main', { 5 extend: 'ux.CardPanel', 6 requires: ['app.view.Home', 'Ext.picker.Picker', 'app.view.uitl.MyBar', 'app.view.user.Site'], 7 xtype: 'main', 8 config: { 9 id: 'main',10 cls: 'cardPanel',11 backBtn: {12 iconCls: 'reply',13 iconMask: true,14 cls: 'replyBtn'15 },16 //items只能配置一项17 items: [{18 xtype: 'home'19 }]20 }21 });
子视图js:
1 Ext.define('app.view.message.List', { 2 alternateClassName: 'messageList', 3 extend: 'Ext.List', 4 xtype: 'messageList', 5 requires: ['Ext.plugin.ListPaging'], 6 config: { 7 cls: 'list', 8 //标题 9 title: '校园资讯',10 //用于控制navBarItems中的css11 pCls: '',12 //底部导航栏,直接填写alternateClassName13 btmBar: 'myBar',16 //额外的按钮组,只能是按钮组。不能添加其他属性17 navBarItems: [{18 itemId: 'mBtn',19 xtype: 'button',20 align: 'right',21 iconMask: true,22 cls: 'nBg',23 iconCls: 'search',24 action: 'show',25 show: 'messageSearch'26 }],27 plugins: [{28 xclass: 'Ext.plugin.ListPaging'29 }],30 itemTpl: '{Title}时间 {Time} 发布来源:{Auth}',31 store: 'messageList'32 }33 });0
2013.9.6
更改CardPanel
优化navBarItems结构,itemId不再必须设置
优化for循环结果
修复popAll方法中ord为全局变量的问题
2013.9.6
更改push方法,可以在传入配置参数(只在第一次创建视图时有效)
2013.10.7
优化代码细节
2013.10.10
更改pop方法,将代码this.setActiveItem(this.getLateViewStack());移动到onBackButtonTap方法中,以解决pop后再push无动画效果的问题
2013.10.18
参照NavigationView大幅度修改代码,去除一些无用代码
2013.10.22
更新push方法,更好的配置自定义参数
移除debug标签,解决cmd压缩后出错的问题。感谢@低碳哥指出
2013.10.23
优化代码,移除了除了back之外的所有自定义事件。如需使用可以考虑用 activate与deactivate事件代替
相关代码: