如何寫一個拖拽日曆組件(附源碼)

做者簡介 Kid 螞蟻金服·數據體驗技術團隊css

本文會介紹如何寫一個可拖拽日曆組件,偏重點在於日曆組件的功能挖掘以及對於開發過程的一些思考,編碼部分會介紹核心部分的實現。代碼在最後也會放出來給你們。react

效果演示

先看下項目最後的實現效果: jquery

running.gif | left | 663x480

前期調研

要作一個可拖拽日曆組件,先得去看一圈市場上已有的日曆組件作成什麼樣了。主要是爲了收集功能以及避免重複造輪子。我調研了google日曆,tower,fullcalendar,teambition,webmail等的日曆控件。其中google日曆和fullcalendar算是使用感覺比較好的了,如下是他們的使用動圖:git

google日曆

google.gif | left | 464x372

fullcalendar

QQ20180402-115350-HD.gif | left | 470x397

功能對比

如下是功能細節的對比列表:github

拖拽已有事件
(拖拽默認起始位置)
拖拽已有事件拖拽中效果
(產生遮擋)
左右拖拽事件
(只實現了單方向,而且產生遮擋)
拖拽空白區域新建
事件智能佈局
(跨周後事件佈局亂了)

從表格的對比能夠看到,這幾家實現的還算不錯的日曆組件功能都沒有實現全,並且在一些細節上都沒作好。能找到的開源的只有fullcalendar,不過他是jquery版本的,並且功能實現的並很差,細節上也有很多錯誤,因此就打算本身寫一個了(終於找到重複造輪子的理由了~)。web

功能

根據以前的調研,一個較好的可拖拽日曆控件須要實現的功能:編程

  • 拖拽已有事件
  • 雙擊添加事件
  • 左右拖拽事件
  • 拖拽空白區域新建事件

除了功能以外,還有用戶可用性上的細節打磨:佈局

  • 拖拽已有事件的陰影效果
  • 拖拽已有事件拖拽中隱藏
  • 左右拖拽的預覽以及陰影效果
  • 事件智能佈局,包括堆疊和換行後的冗餘清理
  • 拖拽態的處理(偏移量計算以及dragLayer的重寫)

編碼

需求調研完了進入到編碼過程,項目主要基於react和react-dnd。編碼的總體步驟包括:測試

  • 繪製日曆
  • 根據事件列表繪製事件
  • 事件佈局整理,堆疊效果和換行清理
  • 讓事件可拖動
  • 讓事件可左右拖動
  • 讓空白區域可拖動勾選
  • 拖拽陰影處理 細講的話文章太長,你們看着累,我講一下關鍵實現點。

可拖拽區域

image.png | left | 463x253

主要是用了react-dnd的拖拽能力,圖裏的4種顏色的圈分別對應了4種可拖拽組件的source。google

  • 紫色是事件自己
  • 紅色是向左拖拽區域
  • 黑色是向右拖拽區域
  • 綠色是拖拽空白的區域(這個設計最有意思,用拖拽的行爲來模擬選中~)

爲這4種source分別處理好對應的拖拽事件。爲每一個source定義好各自的hover事件能夠處理不一樣的陰影效果。定義好layer能夠處理拖拽時鼠標的預覽效果。

事件智能佈局

image.png | left | 334x193

事件分類

就是把一天的事件分爲如圖所示的5種:

  • 1是有前一天,有後一天
  • 2是無前一天,有後一天
  • 3是有前一天,無後一天
  • 4是無前一天,無後一天
  • 5是空白的填充事件

渲染某一天的時候,先渲染1和3這種有前一天的,由於他們有個穩定的index,而後按照優先級渲染事件2,而後是4,填不滿空白的渲染事件5。而後將1和2的index傳到下一天。這樣就能較好的佈局了。

新周事件清理

image.png | left | 503x180

如圖,檢測到新一週開始的時候,我會先清理中間的空白。而後再根據優先級排序事件。

整個開心的代碼編碼過程結束後,竟然發現本身心裏有些拒絕這份代碼..爲啥寫完代碼,調試完成後,本身不肯意再回頭看了呢。哦,是由於真的寫的很差看啊!很差看換句話說就是代碼的內在質量差。

質量

軟件質量能夠分爲外在的和內在的。外在質量包括:

  • 可用性
  • 正確性
  • 健壯性
  • ....

外在質量是用戶關心的惟一軟件特性,我上面一直追求和打磨的其實都屬於軟件的外在質量。用戶是爽的~

可我心裏有些拒絕這份剛寫的代碼的緣由是由於軟件的內在質量出了問題,內在質量包括:

  • 可讀性(多是最重要的了)
  • 可維護性
  • 可接入性(如今支持自定義form,感受仍是不錯的~)
  • ....

寫着寫着發現代碼很差理解了,耐下心細看一下發現:

  • 代碼有冗餘
  • 子程序命名沒有起好
  • 代碼結構混亂
  • 瞎定義css名
  • ....

接着幹嗎,先重構咯~

  • 整理代碼結構,抽抽抽,讓總體流程清晰
  • 從新思考子程序命名,寫註釋
  • 思考對外提供的接口,增強可接入性
  • .....

重構完成一波後思考爲何內在質量會出現問題呢?

質量上的追求是無窮盡的,不管是內在的仍是外在的。不少技術均可以提高質量:補充測試用例,良好的編程風格,合理的註釋,分層抽象,合理的接口...讓全部的特性都表現的盡善盡美絕無可能。根據一組互相競爭的目標找出一套解決方案,正是這種狀況讓軟件成爲一個真正的工程學科

設計

爲何質量會差呢?固然是由於設計的有問題,纔會在開發中發現設計不符合而不斷調整設計,致使破壞了軟件中很是重要的「系統完整性」(人月神話至關推崇的重點)。最終就致使了質量差。

那麼爲何沒有好好設計呢?我估計是由於沒有抵擋住「趕忙開始編碼」的誘惑! 在思考了如何拖拽已有事件以後我就火燒眉毛的開始編碼。沒有進行更爲詳細的設計。其實這個階段我在大腦裏已經隔絕了後續的需求了(爲了智力上可管理採起的自我保護吧~)。而在實現完拖拽已有事件以後,我開始思考如何拖拽空白區域新建,發現已有的設計須要調整。而後在想到了一個還不錯的點子以後就又開始了編碼。設計不完備的循環致使了質量的降低。

其實軟件的產生與現實中的食物鏈同樣,需求->設計->編碼。一環套一環,越靠近上游出了問題影響面越大。概括就是我每次的設計都是基於並不完整的需求來作的。

應該怎麼作呢,應該在最開始的時候儘量的設計全才行。應該加大在初期投入的設計時間。

迭代式開發

可能有朋友看到這裏感受,不對啊,設計原本就是「險惡的問題」(也就是必須被解決或者部分解決才能定義的問題)。因此開發過程採用迭代式開發沒問題啊。迭代式的好處在於有利於規避風險。不斷小成本的嘗試來下降失敗的風險。因此原本迭代式的開發就必須配備不斷的重構來保證質量的。

對於這個問題。我以爲應該看項目的規模。看咱們腦海中可控的複雜度。可能更好的方式是進行原型的開發進行試驗,試驗發現可能以後馬上從新總體設計,而後再編碼,這樣的成本會更小些。

就是在初次迭代進行了一些難點的驗證以後,進行總體設計,這樣能夠減小迭代式開發後必不可少的重構環節,減小總體的開發成本,也提升了項目的質量。

總結

本文分享了可拖拽日曆組件的實現過程,編碼細節以及對於總體開發的思考。之因此會探討對於開發的思考是由於各類方法論都被用於大小不一樣的項目,對於小項目,方法論的應用顯得很不經意且趨於本能。若是咱們有選擇的使用一些方法論的話是可以減小開發時間以及提高產品質量的。最後附上代碼的傳送門,具體的接入使用能夠看下項目的README,仍是有至關多缺陷的,歡迎提PR~

對咱們團隊感興趣的能夠關注專欄,關注github或者發送簡歷至'tao.qit####alibaba-inc.com'.replace('####', '@'),歡迎有志之士加入~

原文地址:github.com/ProtoTeam/b…

相關文章
相關標籤/搜索