摘要:以上就是狀態(tài)模式在實(shí)際開發(fā)中得應(yīng)用,我們結(jié)合了綜合應(yīng)用狀態(tài)模式。
在vue.js之類的mvvm的框架大行其道的當(dāng)下,開發(fā)中最常見的場(chǎng)景就是通過(guò)改變數(shù)據(jù)來(lái)展示頁(yè)面或模塊的不同狀態(tài),當(dāng)我們把mvvm玩的不亦樂(lè)乎的時(shí)候,有時(shí)也會(huì)停下了想想:在某些項(xiàng)目中不能用vuejs之類的框架時(shí),我們?cè)趺赐ㄟ^(guò)改變數(shù)據(jù)來(lái)修改頁(yè)面或者模塊的狀態(tài)呢。
嗯。說(shuō)到狀態(tài),就想到了狀態(tài)模式
狀態(tài)模式:
在很多情況下,一個(gè)對(duì)象的行為取決于一個(gè)或多個(gè)動(dòng)態(tài)變化的狀態(tài)屬性,這樣的對(duì)象叫做有狀態(tài)的(stateful)對(duì)象,對(duì)象的狀態(tài)是從事先定義好的一系列狀態(tài)值中取出的。當(dāng)狀態(tài)對(duì)象與外部事件產(chǎn)生互動(dòng)時(shí),其內(nèi)部狀態(tài)就會(huì)改變,從而使得系統(tǒng)的行為也隨之發(fā)生變化。
狀態(tài)模式主要解決的問(wèn)題:
當(dāng)控制對(duì)象狀態(tài)的條件表達(dá)式過(guò)于復(fù)雜時(shí)的情況,把狀態(tài)的判斷邏輯轉(zhuǎn)移到表示不同的狀態(tài)的一系列類或者方法當(dāng)中,可以把復(fù)雜的邏輯判斷簡(jiǎn)單化
下面我們看看狀態(tài)模式在web前端開發(fā)中得一些常見應(yīng)用場(chǎng)景
tab標(biāo)簽的切換tab標(biāo)簽切換是web開發(fā)中最常見的交互了,交互順序大致是這樣子:
1.一般會(huì)有2-3個(gè)標(biāo)簽,對(duì)應(yīng)了2-3個(gè)tab內(nèi)容塊。其中一個(gè)默認(rèn)tab會(huì)是active狀態(tài)
2.點(diǎn)擊其他tab標(biāo)簽,則:去掉active的tab標(biāo)簽樣式,隱藏對(duì)應(yīng)的區(qū)塊,給點(diǎn)擊的tab添加active樣式,顯示這個(gè)tab對(duì)應(yīng)的區(qū)塊。
哎。。想想需要挨個(gè)tab找對(duì)應(yīng)的元素然后去remove掉class再add一個(gè)class。。。好繁瑣。。能不能少寫點(diǎn)js,簡(jiǎn)簡(jiǎn)單單的實(shí)現(xiàn)tab切換呢。。。
應(yīng)用狀態(tài)模式解決tab切換示例如下:
html 代碼
- 我是tab01
- 我是tab02
- 我是tab03
我是tab01 的內(nèi)容我是tab02的內(nèi)容我是tab03的內(nèi)容
css代碼
.tab-box-wrap { height: 500px; width: 900px; margin: 0 auto; } .tab-list { list-style: none;; height: 32px; border-bottom: 1px solid #6856f9; position: relative; padding: 0 50px; margin: 0; } .tab-list li { float: left; height: 20px; padding: 5px; border: 1px solid #6856f9; line-height: 20px; font-size: 14px; margin-right: -1px; border-bottom: 1px solid transparent; background: #fff; cursor: pointer; } [data-tab-index="tab01"] [tab-index="tab01"] { border-bottom: 2px solid #fff; } [data-tab-index="tab02"] [tab-index="tab02"] { border-bottom: 2px solid #fff; } [data-tab-index="tab03"] [tab-index="tab03"] { border-bottom: 2px solid #fff; } .tab-box { padding: 20px; height: 500px; border: 1px solid #6856f9; border-top: 0 none; display: none; } [data-tab-index="tab01"] [tab-box="tab01"] { display: block; } [data-tab-index="tab02"] [tab-box="tab02"] { display: block; } [data-tab-index="tab03"] [tab-box="tab03"] { display: block; }
js代碼如下
var tab_box_wrap = document.getElementById("tab_box_wrap"); tab_box_wrap.addEventListener("click",function(event){ var ele = event.target; var tab = ele.getAttribute("tab-index"); if(tab){ var t = tab_box_wrap.getAttribute("data-tab-index"); if(t!==tab){ tab_box_wrap.setAttribute("data-tab-index",tab); } } },false)
點(diǎn)擊查看demo
下面我們看一個(gè)復(fù)雜的例子代碼很少,主要的代碼其實(shí)在css里面, 我們用屬性選擇器[data-tab-index="xxx"]來(lái)控制頁(yè)面的tab切換,js里只需要獲取對(duì)應(yīng)的tab點(diǎn)擊然后更改屬性的值就好了。
缺點(diǎn):css有點(diǎn)多,需要枚舉每個(gè)tab的狀態(tài),css屬性選擇器ie8+才支持,
優(yōu)點(diǎn):js代碼很少,邏輯控制全在css里,有什么改動(dòng) (比如添加tab) 我們只需要改css就好了。一聽只改css,是不是很開森^_^
global物流查詢
主要是物流詳情狀態(tài)的動(dòng)畫,這個(gè)動(dòng)畫會(huì)根據(jù)對(duì)應(yīng)的運(yùn)單號(hào)的狀態(tài)來(lái)展示對(duì)應(yīng)的動(dòng)畫節(jié)點(diǎn)。那么我們一共有10個(gè)運(yùn)單狀態(tài),如下:
{statusDesc: "攬收", status: "PICKEDUP",} {statusDesc: "運(yùn)輸中", status: "SHIPPING"}, {statusDesc: "離開發(fā)件國(guó)", status: "DEPART_FROM_ORIGINAL_COUNTRY"}, {statusDesc: "到達(dá)目的國(guó)", status: "ARRIVED_AT_DEST_COUNTRY"}, {statusDesc: "妥投", status: "SIGNIN"} {statusDesc: "待攬收", status: "WAIT4PICKUP"}, {statusDesc: "到達(dá)待取", status: "WAIT4SIGNIN"} {statusDesc: "妥投失敗", status: "SIGNIN_EXC"}, {statusDesc: "交航失敗", status: "DEPART_FROM_ORIGINAL_COUNTRY_EXC"}, {statusDesc: "清關(guān)失敗", status: "ARRIVED_AT_DEST_COUNTRY_EXC"}
無(wú)狀態(tài)的時(shí)候動(dòng)畫狀態(tài)如下:
妥投狀態(tài)動(dòng)畫截圖如下:
每一個(gè)正常節(jié)點(diǎn)中間都會(huì)有一個(gè)異常節(jié)點(diǎn),【到達(dá)目的國(guó)】和【妥投】之間會(huì)有一個(gè)【到達(dá)待取】狀態(tài),
【攬收】和【離開發(fā)件國(guó)】之間會(huì)有一個(gè)【運(yùn)輸中】狀態(tài)
下面我們來(lái)思考我們的代碼應(yīng)該怎么寫。。。
無(wú)狀態(tài)灰色div里放一個(gè)背景圖片,上面的文字是html節(jié)點(diǎn)。
灰色模塊上面附一層紫色block,文字也是html節(jié)點(diǎn),不同狀態(tài)設(shè)置不同的div的width就好了。
狀態(tài)文字多帶帶是節(jié)點(diǎn)一共10個(gè)狀態(tài)文字節(jié)點(diǎn)
我期望改變一個(gè)div屬性整個(gè)動(dòng)畫都會(huì)相應(yīng)的變化
html代碼如下
攬收 離開發(fā)件國(guó) 到達(dá)目的國(guó) 妥投 攬收 離開發(fā)件國(guó) 到達(dá)目的國(guó) 妥投 到達(dá)待取 運(yùn)輸中
我們給#waybill_img_box 這個(gè)div添加一個(gè)img-animate的屬性,用來(lái)控制他的子節(jié)點(diǎn)的展示。
waybill-img01這個(gè)div用來(lái)放灰色的圖片
waybill_img_color 這個(gè)div放的是彩色圖片,我們更改她的width來(lái)實(shí)現(xiàn)動(dòng)畫,它是絕對(duì)定位的
剩下的一堆b標(biāo)簽都是文字內(nèi)容的定位。當(dāng)然他們也是絕對(duì)定位的
css代碼如下:為了簡(jiǎn)短,我只列舉了兩種狀態(tài)
/*初始化的時(shí)候所有的紫色模塊的字全都應(yīng)該隱藏*/ [img-animate="init"] .waybill-color-01, [img-animate="init"] .waybill-color-02, [img-animate="init"] .waybill-color-03, [img-animate="init"] .waybill-color-04, [img-animate="init"] .waybill-color-05, [img-animate="init"] .waybill-color-06 { z-index: -1; } [img-animate="init"] .waybill-img02 { width: 0; } /*紫色元素的字的默認(rèn)狀態(tài)*/ .waybill-color-01, .waybill-color-02, .waybill-color-03, .waybill-color-04, .waybill-color-05, .waybill-color-06 { text-align: center; font-weight: 500; position: absolute; top: 78px; left: 12px; z-index: 20; color: #fff; background: #4b4ebe; padding: 4px 5px; height: 12px; line-height: 12px; border-radius: 3px; display: none9; -moz-transform: scale(0); -webkit-transform: scale(0); -o-transform: scale(0); -ms-transform: scale(0); transform: scale(0); } .waybill-color-02 { left: 208px; top: 28px; min-width: 35px; } .waybill-color-03 { left: 419px; top: 30px; min-width: 70px; } .waybill-color-04 { left: 636px; top: 75px; min-width: 50px; } .waybill-color-05 { left: 562px; top: 50px; min-width: 50px; } .waybill-color-06 { left: 105px; top: 42px; min-width: 50px; } /* *下面寫攬收狀態(tài)的樣式 *PICKEDUP */ [img-animate="PICKEDUP"] .waybill-no-color-01, [img-animate="DEPART_FROM_ORIGINAL_COUNTRY"] .waybill-no-color-01 { -moz-transition: all 0.3s ease-in 0s; -webkit-transition: all 0.3s ease-in 0s; -o-transition: all 0.3s ease-in 0s; transition: all 0.3s ease-in 0s; -moz-transform: translate(8px, 95px) scale(0); -webkit-transform: translate(8px, 95px) scale(0); -o-transform: translate(8px, 95px) scale(0); -ms-transform: translate(8px, 95px) scale(0); transform: translate(8px, 95px) scale(0); } [img-animate="PICKEDUP"] .waybill-color-01, [img-animate="DEPART_FROM_ORIGINAL_COUNTRY"] .waybill-no-color-02{ -moz-transition: all 0.3s ease-in 0s; -webkit-transition: all 0.3s ease-in 0s; -o-transition: all 0.3s ease-in 0s; transition: all 0.3s ease-in 0s; -moz-transform: scale(1); -webkit-transform: scale(1); -o-transform: scale(1); -ms-transform: scale(1); transform: scale(1); z-index: 20; } [img-animate="PICKEDUP"] .waybill-color-02, [img-animate="PICKEDUP"] .waybill-color-03, [img-animate="PICKEDUP"] .waybill-color-04, [img-animate="PICKEDUP"] .waybill-color-06, [img-animate="PICKEDUP"] .waybill-color-05 { z-index: -1; } /*寫一個(gè)離開發(fā)件國(guó)的狀態(tài) * DEPART_FROM_ORIGINAL_COUNTRY */ [img-animate="DEPART_FROM_ORIGINAL_COUNTRY"] .waybill-color-03, [img-animate="DEPART_FROM_ORIGINAL_COUNTRY"] .waybill-color-04{ z-index: -1; } [img-animate="DEPART_FROM_ORIGINAL_COUNTRY"] .waybill-no-color-01{ -moz-transform: translate(8px, 85px) scale(0); -webkit-transform: translate(8px, 85px) scale(0); -o-transform: translate(8px, 85px) scale(0); -ms-transform: translate(8px, 85px) scale(0); transform: translate(8px, 85px) scale(0); } [img-animate="DEPART_FROM_ORIGINAL_COUNTRY"] .waybill-color-01{ -moz-transition: all 0.3s ease-in 0s; -webkit-transition: all 0.3s ease-in 0s; -o-transition: all 0.3s ease-in 0s; transition: all 0.3s ease-in 0s; -moz-transform: scale(1); -webkit-transform: scale(1); -o-transform: scale(1); -ms-transform: scale(1); transform: scale(1); z-index: 20; } [img-animate="DEPART_FROM_ORIGINAL_COUNTRY"] .waybill-no-color-02{ -moz-transition: all 0.3s ease-in 0s; -webkit-transition: all 0.3s ease-in 0s; -o-transition: all 0.3s ease-in 0s; transition: all 0.3s ease-in 0s; -moz-transform: translate(8px, 20px) scale(0); -webkit-transform: translate(8px, 20px) scale(0); -o-transform: translate(8px, 20px) scale(0); -ms-transform: translate(8px, 20px) scale(0); transform: translate(8px, 20px) scale(0); } [img-animate="DEPART_FROM_ORIGINAL_COUNTRY"] .waybill-color-02{ -moz-transition: all 0.3s ease-in 0s; -webkit-transition: all 0.3s ease-in 0s; -o-transition: all 0.3s ease-in 0s; transition: all 0.3s ease-in 0s; -moz-transform: scale(1); -webkit-transform: scale(1); -o-transform: scale(1); -ms-transform: scale(1); transform: scale(1); z-index: 20; }
大致思路和tab的實(shí)現(xiàn)是一樣的,我們?cè)赾ss里面枚舉了每個(gè)狀態(tài)下每個(gè)模塊應(yīng)該對(duì)應(yīng)的狀態(tài)。 我們把c通用的css寫在一個(gè)樣式里,其他的每個(gè)狀態(tài)只需要重置特定的樣式就可以了
接下來(lái)看狀態(tài)模式在js里的應(yīng)用
js里面我們把狀態(tài)對(duì)應(yīng)到每一個(gè)函數(shù)里面就好了。動(dòng)畫使用了jquery的動(dòng)畫。js代碼如下
var statusAnimateMap={ PICKEDUP: function(callback){ var self = waybillDetail; //更具對(duì)應(yīng)的狀態(tài)設(shè)置動(dòng)畫 //var w = ONEWAYBILL?32:32; self.waybill_img_colorBox.animate( { width:32 },500,function(){ self.waybill_img_box.attr("img-animate","PICKEDUP"); if(callback&&typeof callback==="function"){ callback(); } }); }, DEPART_FROM_ORIGINAL_COUNTRY: function(callback){ var self = waybillDetail; //更具對(duì)應(yīng)的狀態(tài)設(shè)置動(dòng)畫 var w = ONEWAYBILL?345:243; this.PICKEDUP(function(){ self.waybill_img_colorBox.animate( { width:w },800,function(){ self.waybill_img_box.attr("img-animate","DEPART_FROM_ORIGINAL_COUNTRY"); if(callback&&typeof callback==="function"){ callback(); } }); }); }, } //使用的時(shí)候很簡(jiǎn)單 function statusAnimate(status){ if(status&& statusAnimateMap[status]){ statusAnimateMap[status](); } } statusAnimate("PICKEDUP");
這里用到了jquery的animate動(dòng)畫。并且業(yè)務(wù)要求:
每個(gè)狀態(tài)結(jié)束才能執(zhí)行下一個(gè)狀態(tài)的動(dòng)畫,比如DEPART_FROM_ORIGINAL_COUNTRY這個(gè)狀態(tài)就需要
1.先執(zhí)行PICKEDUP的動(dòng)畫
2.再執(zhí)行DEPART_FROM_ORIGINAL_COUNTRY的動(dòng)畫,
聽起來(lái)是不是很耳熟,嗯有點(diǎn)promise的感覺。。額不過(guò)這么一個(gè)簡(jiǎn)單的場(chǎng)景當(dāng)然不需要?jiǎng)跓﹑romise的大駕了。。。我們給animate綁定一個(gè)回調(diào)方法就好了。
嗯,具體的實(shí)現(xiàn)見這個(gè)demo
這個(gè)頁(yè)面還有個(gè)單條查詢的詳情狀態(tài),頁(yè)面結(jié)構(gòu)會(huì)不一樣,左側(cè)列表會(huì)隱藏。。。。查看示例,圖片會(huì)拉長(zhǎng),也就是說(shuō)每個(gè)狀態(tài)都需要多帶帶寫一個(gè)單條的查詢的樣式。。。額還好我們的狀態(tài)都寫在css里我們只需要給頁(yè)面加一個(gè)屬性[oneMailNo]然后重置一下每個(gè)狀態(tài)下各個(gè)節(jié)點(diǎn)的位置就好了,js只需要修改一下waybill_img_color的寬度就好了。嗯改css的成本很低的。。bingo
以上就是狀態(tài)模式在實(shí)際開發(fā)中得應(yīng)用,我們結(jié)合了css html js 綜合應(yīng)用狀態(tài)模式。可以大大減少項(xiàng)目里面的邏輯代碼。提高開發(fā)效率,剩下的時(shí)間可以去和設(shè)計(jì)師美眉聊聊生活。。談?wù)勅松硐搿!!!?/p>
詳見我的博客https://www.56way.com
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/86449.html
摘要:前端每周清單半年盤點(diǎn)之與篇前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn)分為新聞熱點(diǎn)開發(fā)教程工程實(shí)踐深度閱讀開源項(xiàng)目巔峰人生等欄目。與求同存異近日,宣布將的構(gòu)建工具由遷移到,引發(fā)了很多開發(fā)者的討論。 前端每周清單半年盤點(diǎn)之 React 與 ReactNative 篇 前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為...
摘要:是文檔的一種表示結(jié)構(gòu)。這些任務(wù)大部分都是基于它。這個(gè)實(shí)踐的重點(diǎn)是把你在前端練級(jí)攻略第部分中學(xué)到的一些東西和結(jié)合起來(lái)。一旦你進(jìn)入框架部分,你將更好地理解并使用它們。到目前為止,你一直在使用進(jìn)行操作。它是在前端系統(tǒng)像今天這樣復(fù)雜之前編寫的。 本文是 前端練級(jí)攻略 第二部分,第一部分請(qǐng)看下面: 前端練級(jí)攻略(第一部分) 在第二部分,我們將重點(diǎn)學(xué)習(xí) JavaScript 作為一種獨(dú)立的語(yǔ)言,如...
摘要:前端每周清單第期與模式變遷與優(yōu)化界面生成作者王下邀月熊編輯徐川前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn)分為新聞熱點(diǎn)開發(fā)教程工程實(shí)踐深度閱讀開源項(xiàng)目巔峰人生等欄目。 showImg(https://segmentfault.com/img/remote/1460000013279448); 前端每周清單第 51 期: React Context A...
摘要:延伸閱讀學(xué)習(xí)與實(shí)踐資料索引與前端工程化實(shí)踐前端每周清單半年盤點(diǎn)之篇前端每周清單半年盤點(diǎn)之與篇前端每周清單半年盤點(diǎn)之篇 前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為新聞熱點(diǎn)、開發(fā)教程、工程實(shí)踐、深度閱讀、開源項(xiàng)目、巔峰人生等欄目。歡迎關(guān)注【前端之巔】微信公眾號(hào)(ID:frontshow),及時(shí)獲取前端每周清單;本文則是對(duì)于半年來(lái)發(fā)布的前端每周清單...
摘要:前端進(jìn)階進(jìn)階構(gòu)建項(xiàng)目一配置最佳實(shí)踐狀態(tài)管理之痛點(diǎn)分析與改良開發(fā)中所謂狀態(tài)淺析從時(shí)間旅行的烏托邦,看狀態(tài)管理的設(shè)計(jì)誤區(qū)使用更好地處理數(shù)據(jù)愛彼迎房源詳情頁(yè)中的性能優(yōu)化從零開始,在中構(gòu)建時(shí)間旅行式調(diào)試用輕松管理復(fù)雜狀態(tài)如何把業(yè)務(wù)邏輯這個(gè)故事講好和 前端進(jìn)階 webpack webpack進(jìn)階構(gòu)建項(xiàng)目(一) Webpack 4 配置最佳實(shí)踐 react Redux狀態(tài)管理之痛點(diǎn)、分析與...
閱讀 888·2021-09-22 15:17
閱讀 1917·2021-09-22 15:06
閱讀 2211·2021-09-08 09:35
閱讀 5099·2021-09-01 11:43
閱讀 3476·2019-08-30 15:55
閱讀 2150·2019-08-30 12:48
閱讀 3150·2019-08-30 12:45
閱讀 1782·2019-08-29 17:31