摘要:接下來,由簡入繁依次實現提示組件的各個功能。那么第一個提示的定時器依然會錯誤的關閉新提示。增強靈活性最后則是讓提示組件更靈活。
這次的教程里,我們要把組件化進行到底!最近半年的幾個項目中,都遇到了需要使用Toast或者Notification組件的情況。在目前已有的一些基于Vue.js開發的組件庫,都沒有找到太合適的,所以自己重頭實現了一個。歷經幾個項目的磨練,這個提示組件的功能已經越來越完善,這次就分享一下組件以及其實現思路吧。
深入組件化,組件的拆分、整合與復用GitHub 倉庫:https://github.com/Yuyz0112/vue-notie
Demo 地址:http://lab.myriptide.com/vue-notie/
Vue.js的組件化可以說是其招牌特性之一,而在實際應用時,并非一味地追求組件顆粒越小越好,而是需要根據項目的實際需求,來分析自己需要什么級別的組件。
例如在一個SPA中,我可能有主頁、文章列表頁、文章頁、個人中心頁4個主要的視圖,于是我將其分別對應的寫成4個組件。
但是在實際編寫的過程中,發現他們共用了同一套側邊欄,而側邊欄對應的代碼也在4個組件中重復書寫了4次。所以可以將側邊欄多帶帶寫成一個組件進行復用。
之后,我們可能發現可以復用的還有一些表單、按鈕之類的內容我們都可以復用成組件。但實際上,我們也會發現過度的組件化會導致代碼量上升、開發時間增加以及額外的數據傳遞等等。所以如果不打算制作一個完整的組件庫,那么在實際項目中做到按需拆分、整合即可,不用過分的追求每個可復用的部分都寫成單個組件。
為什么需要一個提示組件因為alert大部分時間不能滿足我們的需求啊。往往項目里需要一個類似于alert的東西,用美觀、可定制的方式提示用戶一些信息,因此這樣一個提示組件很有必要。
同時,我們也不希望同一時間出現多個提示混淆用戶,因此在設計上,我們將提示組件設定為具有唯一性,整個應用中各個視圖調用的都是同一個提示組件。
Show me the code接下來,由簡入繁依次實現提示組件的各個功能。
基本功能最基本的功能當然是觸發后顯示,并且能夠以某種方式關閉。唯一需要自定義的部分,就是具體顯示的內容。所以最開始組件長這樣:
{{ options.content }}
思路很簡單,props傳遞兩個數據,show用于控制顯示,options傳入包括內容在內的自定義內容。為了讓提示的顯示更加自然,添加了一個滑動進入和離開的transition。
注意:這里的關閉按鈕是通過css實現的,如果在你的項目中有對應的icon,可以將其替換掉。
在此處,也可以使用slot來進行內容的傳遞,但考慮到之后還有別的參數需要傳遞至組件內,一次用一個統一的對象options進行傳遞。
自定義樣式通常提示的內容種類很多,有的是成功提示,有的是警告,有的則是報錯。因此我們需要定義不同的樣式以表達不同的內容。
方法很簡單,在options中傳入背景色和文字顏色兩個參數,如果組件中檢測到了傳入的樣式參數,就用其替換默認樣式。
Vue.js在處理動態樣式時非常靈活,為了讓代碼更清晰,我沒有選擇將動態樣式內聯,而是多帶帶使用一個計算屬性setStyle進行設定:
computed: { setStyle () { return { color: this.options.textColor || "#fff", background: this.options.backgroundColor || "#21e7b6" } } }
這樣一來,只要在options中一并傳入textColor和backgroundColor兩個屬性,就可以輕松自定義提示樣式了。
自動關閉很多時候,我們希望提示在一定時間之后可以自動關閉,因此組件也需要擴展出一個自動關閉的模式。同樣的,在“數據驅動”的思想下,我們應該提供一個數據,用來表明這個提示是否自動關閉。
options中的autoClose屬性就是這個作用。同樣的,自動關閉的延遲時間顯然也要能夠自定義,因此還一同添加了showTime這一屬性。
自動關閉本身不太復雜,我們只需要使用setTimeout,定義一個計時器即可。
首先是監聽提示組件的顯示。
在這里,我通過watch監聽options的變化來處罰計時器。由于我們已經定義了一個close方法用于關閉計時器,并且在關閉時重置了show和options的值,所以在options變化時,只需要判斷options中的autoClose是否為true,就能知道是否需要啟動計時器了。這里多帶帶使用一個countdown方法來處理定時器相關的操作。
新增代碼如下:
data () { return { timers: [] } }, methods: { countdown () { if (this.options.autoClose) { const t = setTimeout(() => { this.close() }, this.options.showTime || 3000) this.timers.push(t) } } }, watch: { options () { this.timers.forEach((timer) => { window.clearTimeout(timer) }) this.timers = [] this.countdown() } }
細心地你肯定會發現,這段代碼中,有一些奇怪的處理。我們定義了一個空數組timers,并且每次開始一個計時器的時候,就把計時器存入數組中,而每次options變化時,我們也從timers中遍歷所有計時器并取消,之后清空timers。
這個做法,主要是為了避免一個計時器還沒有結束時,又開始一個新的提示所引發的提示被提前關閉的清空。舉個例子,如果沒有這樣的處理,那么先發出一個自動關閉的提示,在其沒自動關閉之前,就再發出一個新的提示。那么第一個提示的定時器依然會錯誤的關閉新提示。
這樣的問題主要是由于我們所有的計時器都是在同一個組件中,本質上都是同一個提示,因此需要清除計時器,避免沖突。許多組件庫中類似的功能組件,是采用每一條提示就新生成一個提示組件的方式來實現的。但是那樣在多個提示連續出現時,就會出現堆疊在一起,又各自離開的情況。
之前的版本中,我的提示組件也采用了類似的設計方式,但是在最近的一個項目中,需要實現半透明的提示組件,就出現了堆疊后看不清提示文字的現象,才使用了現在新的模式。
進一步擴展緊接著,我拓展了一個自動關閉模式下的倒計時條功能。思路上沒有使用Vue.js的transition系統,而是采用了Css3本身的動畫系統。在一個自動關閉的提示被初始化時,為計時條添加一個樣式,效果是向X軸負方向移動100%,transition時間則通過計算屬性對應設定。具體實現可以參考源代碼,這里不多做贅述。
增強靈活性最后則是讓提示組件更靈活。有的時候,我們想展示的可能是可以自定義樣式的文本、亦或是一個超鏈接甚至更多。而Vue.js實現起來不要太簡單。我們只需要將組件中用于渲染的{{ options.content }}變為{{{ options.content }}}即可,對于3重花括號的模板,Vue.js會將其中的HTML標簽按照正常內容渲染。
如此一來,我們就可以將任何HTML內容放入提示中了。當然一定要注意避免將用戶輸入的內容渲染到3重花括號的模板中,避免XSS攻擊。
結合vuex很多時候,我們會把提示組件引入到App.vue這個根組件中,但是發出提示的可能是組件樹中的任何一個組件。如果不想代碼中遍布各種dispatch和broadcast,那么引入vuex來進行管理是個很好的方案。
大致的思路如下:
// store.js const state = { show: false, options: { autoClose: false, content: "notice content" } } const mutations = { NEW_NOTICE (state, options) { state.show = true state.options = options }, CLOSE_NOTICE (state) { state.show = false state.options = {} } } // actions.js export const newNotice = ({dispatch}, options) => { dispatch("NEW_NOTICE", options) } export const closeNotice = ({dispatch}) => { dispatch("CLOSE_NOTICE") } // Notification.vue vuex: { getters: { show: state => state.show options: state => state.options }, actions: { close: closeNotice } } // 任意調用notice的組件 vuex: { actions: { notice: newNotice } }
引入vuex后,按上述代碼進行配置,就可以在任意一處組件中,使用this.notice({options})傳遞數據。不過由于vuex的單項數據流動特性,所有對state數據的操作都必須經過actions調用mutations實現,包括提示組件中的close方法也要替換成actions中的closeNotice方法。
綜述通過這個提示組件,我們更熟練的掌握了Vue.js的組件系統、數據傳遞、計算屬性、transition動畫等特性。另外此組件已經可以直接用于生產環境中,歡迎star、fork、pr。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79994.html
摘要:前端每周清單第期現狀分析與優化策略單元測試爬蟲作者王下邀月熊編輯徐川前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點分為新聞熱點開發教程工程實踐深度閱讀開源項目巔峰人生等欄目。 showImg(https://segmentfault.com/img/remote/1460000011008022); 前端每周清單第 29 期:Web 現狀分析與優化策略...
摘要:在引起狀態變化的時刻,框架自動觸發臟檢查,也可以手動執行臟檢查,直接操作更新視圖。最后,說了這么多,大家在具體選型時還是要首先分析自己的需求和現狀,然后再做選擇。 作為一個軟件開發者,最大的挑戰就是在不斷涌現的新技術中進行取舍,持續學習是從事這一行業的必備技能。在這個領域里,技術更新最快地又非前端莫屬了。各種框架的出現、版本的更新此起彼伏,呈現出一派欣欣向榮之景。 在項目中必不可少的便...
摘要:在引起狀態變化的時刻,框架自動觸發臟檢查,也可以手動執行臟檢查,直接操作更新視圖。最后,說了這么多,大家在具體選型時還是要首先分析自己的需求和現狀,然后再做選擇。 作為一個軟件開發者,最大的挑戰就是在不斷涌現的新技術中進行取舍,持續學習是從事這一行業的必備技能。在這個領域里,技術更新最快地又非前端莫屬了。各種框架的出現、版本的更新此起彼伏,呈現出一派欣欣向榮之景。 在項目中必不可少的便...
摘要:在引起狀態變化的時刻,框架自動觸發臟檢查,也可以手動執行臟檢查,直接操作更新視圖。最后,說了這么多,大家在具體選型時還是要首先分析自己的需求和現狀,然后再做選擇。 作為一個軟件開發者,最大的挑戰就是在不斷涌現的新技術中進行取舍,持續學習是從事這一行業的必備技能。在這個領域里,技術更新最快地又非前端莫屬了。各種框架的出現、版本的更新此起彼伏,呈現出一派欣欣向榮之景。 在項目中必不可少的便...
閱讀 2025·2023-04-26 00:16
閱讀 3475·2021-11-15 11:38
閱讀 3168·2019-08-30 12:50
閱讀 3178·2019-08-29 13:59
閱讀 750·2019-08-29 13:54
閱讀 2496·2019-08-29 13:42
閱讀 3305·2019-08-26 11:45
閱讀 2187·2019-08-26 11:36