摘要:以上就是狀態(tài)模式在實際開發(fā)中得應(yīng)用,我們結(jié)合了綜合應(yīng)用狀態(tài)模式。
在vue.js之類的mvvm的框架大行其道的當(dāng)下,開發(fā)中最常見的場景就是通過改變數(shù)據(jù)來展示頁面或模塊的不同狀態(tài),當(dāng)我們把mvvm玩的不亦樂乎的時候,有時也會停下了想想:在某些項目中不能用vuejs之類的框架時,我們怎么通過改變數(shù)據(jù)來修改頁面或者模塊的狀態(tài)呢。
嗯。說到狀態(tài),就想到了狀態(tài)模式
狀態(tài)模式:
在很多情況下,一個對象的行為取決于一個或多個動態(tài)變化的狀態(tài)屬性,這樣的對象叫做有狀態(tài)的(stateful)對象,對象的狀態(tài)是從事先定義好的一系列狀態(tài)值中取出的。當(dāng)狀態(tài)對象與外部事件產(chǎn)生互動時,其內(nèi)部狀態(tài)就會改變,從而使得系統(tǒng)的行為也隨之發(fā)生變化。
狀態(tài)模式主要解決的問題:
當(dāng)控制對象狀態(tài)的條件表達(dá)式過于復(fù)雜時的情況,把狀態(tài)的判斷邏輯轉(zhuǎn)移到表示不同的狀態(tài)的一系列類或者方法當(dāng)中,可以把復(fù)雜的邏輯判斷簡單化
下面我們看看狀態(tài)模式在web前端開發(fā)中得一些常見應(yīng)用場景
tab標(biāo)簽的切換tab標(biāo)簽切換是web開發(fā)中最常見的交互了,交互順序大致是這樣子:
1.一般會有2-3個標(biāo)簽,對應(yīng)了2-3個tab內(nèi)容塊。其中一個默認(rèn)tab會是active狀態(tài)
2.點擊其他tab標(biāo)簽,則:去掉active的tab標(biāo)簽樣式,隱藏對應(yīng)的區(qū)塊,給點擊的tab添加active樣式,顯示這個tab對應(yīng)的區(qū)塊。
哎。。想想需要挨個tab找對應(yīng)的元素然后去remove掉class再add一個class。。。好繁瑣。。能不能少寫點js,簡簡單單的實現(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)
點擊查看demo
下面我們看一個復(fù)雜的例子代碼很少,主要的代碼其實在css里面, 我們用屬性選擇器[data-tab-index="xxx"]來控制頁面的tab切換,js里只需要獲取對應(yīng)的tab點擊然后更改屬性的值就好了。
缺點:css有點多,需要枚舉每個tab的狀態(tài),css屬性選擇器ie8+才支持,
優(yōu)點:js代碼很少,邏輯控制全在css里,有什么改動 (比如添加tab) 我們只需要改css就好了。一聽只改css,是不是很開森^_^
global物流查詢
主要是物流詳情狀態(tài)的動畫,這個動畫會根據(jù)對應(yīng)的運單號的狀態(tài)來展示對應(yīng)的動畫節(jié)點。那么我們一共有10個運單狀態(tài),如下:
{statusDesc: "攬收", status: "PICKEDUP",} {statusDesc: "運輸中", status: "SHIPPING"}, {statusDesc: "離開發(fā)件國", status: "DEPART_FROM_ORIGINAL_COUNTRY"}, {statusDesc: "到達(dá)目的國", 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"}
無狀態(tài)的時候動畫狀態(tài)如下:
妥投狀態(tài)動畫截圖如下:
每一個正常節(jié)點中間都會有一個異常節(jié)點,【到達(dá)目的國】和【妥投】之間會有一個【到達(dá)待取】狀態(tài),
【攬收】和【離開發(fā)件國】之間會有一個【運輸中】狀態(tài)
下面我們來思考我們的代碼應(yīng)該怎么寫。。。
無狀態(tài)灰色div里放一個背景圖片,上面的文字是html節(jié)點。
灰色模塊上面附一層紫色block,文字也是html節(jié)點,不同狀態(tài)設(shè)置不同的div的width就好了。
狀態(tài)文字多帶帶是節(jié)點一共10個狀態(tài)文字節(jié)點
我期望改變一個div屬性整個動畫都會相應(yīng)的變化
html代碼如下
攬收 離開發(fā)件國 到達(dá)目的國 妥投 攬收 離開發(fā)件國 到達(dá)目的國 妥投 到達(dá)待取 運輸中
我們給#waybill_img_box 這個div添加一個img-animate的屬性,用來控制他的子節(jié)點的展示。
waybill-img01這個div用來放灰色的圖片
waybill_img_color 這個div放的是彩色圖片,我們更改她的width來實現(xiàn)動畫,它是絕對定位的
剩下的一堆b標(biāo)簽都是文字內(nèi)容的定位。當(dāng)然他們也是絕對定位的
css代碼如下:為了簡短,我只列舉了兩種狀態(tài)
/*初始化的時候所有的紫色模塊的字全都應(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; } /*寫一個離開發(fā)件國的狀態(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的實現(xiàn)是一樣的,我們在css里面枚舉了每個狀態(tài)下每個模塊應(yīng)該對應(yīng)的狀態(tài)。 我們把c通用的css寫在一個樣式里,其他的每個狀態(tài)只需要重置特定的樣式就可以了
接下來看狀態(tài)模式在js里的應(yīng)用
js里面我們把狀態(tài)對應(yīng)到每一個函數(shù)里面就好了。動畫使用了jquery的動畫。js代碼如下
var statusAnimateMap={ PICKEDUP: function(callback){ var self = waybillDetail; //更具對應(yīng)的狀態(tài)設(shè)置動畫 //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; //更具對應(yīng)的狀態(tài)設(shè)置動畫 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(); } }); }); }, } //使用的時候很簡單 function statusAnimate(status){ if(status&& statusAnimateMap[status]){ statusAnimateMap[status](); } } statusAnimate("PICKEDUP");
這里用到了jquery的animate動畫。并且業(yè)務(wù)要求:
每個狀態(tài)結(jié)束才能執(zhí)行下一個狀態(tài)的動畫,比如DEPART_FROM_ORIGINAL_COUNTRY這個狀態(tài)就需要
1.先執(zhí)行PICKEDUP的動畫
2.再執(zhí)行DEPART_FROM_ORIGINAL_COUNTRY的動畫,
聽起來是不是很耳熟,嗯有點promise的感覺。。額不過這么一個簡單的場景當(dāng)然不需要勞煩promise的大駕了。。。我們給animate綁定一個回調(diào)方法就好了。
嗯,具體的實現(xiàn)見這個demo
這個頁面還有個單條查詢的詳情狀態(tài),頁面結(jié)構(gòu)會不一樣,左側(cè)列表會隱藏。。。。查看示例,圖片會拉長,也就是說每個狀態(tài)都需要多帶帶寫一個單條的查詢的樣式。。。額還好我們的狀態(tài)都寫在css里我們只需要給頁面加一個屬性[oneMailNo]然后重置一下每個狀態(tài)下各個節(jié)點的位置就好了,js只需要修改一下waybill_img_color的寬度就好了。嗯改css的成本很低的。。bingo
以上就是狀態(tài)模式在實際開發(fā)中得應(yīng)用,我們結(jié)合了css html js 綜合應(yīng)用狀態(tài)模式。可以大大減少項目里面的邏輯代碼。提高開發(fā)效率,剩下的時間可以去和設(shè)計師美眉聊聊生活。。談?wù)勅松硐?。。?!?/p>
詳見我的博客https://www.56way.com
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/49938.html
摘要:前端每周清單半年盤點之與篇前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點分為新聞熱點開發(fā)教程工程實踐深度閱讀開源項目巔峰人生等欄目。與求同存異近日,宣布將的構(gòu)建工具由遷移到,引發(fā)了很多開發(fā)者的討論。 前端每周清單半年盤點之 React 與 ReactNative 篇 前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點;分為...
摘要:是文檔的一種表示結(jié)構(gòu)。這些任務(wù)大部分都是基于它。這個實踐的重點是把你在前端練級攻略第部分中學(xué)到的一些東西和結(jié)合起來。一旦你進(jìn)入框架部分,你將更好地理解并使用它們。到目前為止,你一直在使用進(jìn)行操作。它是在前端系統(tǒng)像今天這樣復(fù)雜之前編寫的。 本文是 前端練級攻略 第二部分,第一部分請看下面: 前端練級攻略(第一部分) 在第二部分,我們將重點學(xué)習(xí) JavaScript 作為一種獨立的語言,如...
摘要:前端每周清單第期與模式變遷與優(yōu)化界面生成作者王下邀月熊編輯徐川前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點分為新聞熱點開發(fā)教程工程實踐深度閱讀開源項目巔峰人生等欄目。 showImg(https://segmentfault.com/img/remote/1460000013279448); 前端每周清單第 51 期: React Context A...
摘要:延伸閱讀學(xué)習(xí)與實踐資料索引與前端工程化實踐前端每周清單半年盤點之篇前端每周清單半年盤點之與篇前端每周清單半年盤點之篇 前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點;分為新聞熱點、開發(fā)教程、工程實踐、深度閱讀、開源項目、巔峰人生等欄目。歡迎關(guān)注【前端之巔】微信公眾號(ID:frontshow),及時獲取前端每周清單;本文則是對于半年來發(fā)布的前端每周清單...
摘要:前端進(jìn)階進(jìn)階構(gòu)建項目一配置最佳實踐狀態(tài)管理之痛點分析與改良開發(fā)中所謂狀態(tài)淺析從時間旅行的烏托邦,看狀態(tài)管理的設(shè)計誤區(qū)使用更好地處理數(shù)據(jù)愛彼迎房源詳情頁中的性能優(yōu)化從零開始,在中構(gòu)建時間旅行式調(diào)試用輕松管理復(fù)雜狀態(tài)如何把業(yè)務(wù)邏輯這個故事講好和 前端進(jìn)階 webpack webpack進(jìn)階構(gòu)建項目(一) Webpack 4 配置最佳實踐 react Redux狀態(tài)管理之痛點、分析與...
閱讀 3861·2021-09-22 15:49
閱讀 3345·2021-09-08 09:35
閱讀 1447·2019-08-30 15:55
閱讀 2348·2019-08-30 15:44
閱讀 742·2019-08-29 16:59
閱讀 1629·2019-08-29 16:16
閱讀 514·2019-08-28 18:06
閱讀 924·2019-08-27 10:55