side project
一開始是跟著VueMastery一個教學做的project,上完後覺得裡面用的HTML內建drag and drop API太複雜,不好用且難維護,就試著抽換成vuedraggable,順便學了Tailwind.css,意外發現還蠻好用的。
另外也整理vue-fontawesome的使用方法。
vuedraggable 是一款以Sortable.js為基礎建立的Vue套件,輕鬆讓你實現拖拉功能並同步變動data,可以到他的playground去玩看看
npm i vuedraggable
直接在component中 import
在template中使用:
加入transition效果:
將transition-group包住你要拖拉的component就可以了
draggable之後一定要直接寫入你要拖拉的component或是transition-group
Vuex:
在兩個(或更多)lists之間拖拉:
只要在lists的draggable上,設定相同的group name,vuedraggable就會知道這些lists是同一組的,可以相互拖拉。
set options:
在draggable tag 上v-bind option,然後在data中設定客製的options,在Sortable.js的文件中可以找到所有options。
例如我在project有使用的options:
在手動測試的時候,發現有時在兩個list之間會有閃爍的情形,goole後發現有人發過issue,作者表示似乎是Sortable.js的問題,但尚未解決,我也暫時想不到解法,先放著待優化了。
problem: 原先只commit state裡面的board然後存到localstorage裡,就算dragging改變board的list順序,只要透過commit
去覆蓋先前的board即可。與後端串接後,先前的做法無法改變db中lists的順序。
solution: 根據sortable的文件,用onSort, 可以在list有任何change發生時去觸發綁定的function。
接著在methods
problem: 希望board title的input 可以像trello的board title一樣隨著內容寬度變化。
solution:
爬了許多文後發現,共通點都是在input旁建立一個sibling element,讓這個element 隱形,但它的textContent跟input同步更新,input再去參照element的寬度,並依據element寬度改變input 寬度。
透過offsetWidth可以取得span的寬度。而用offsetWidth的原因:
offsetWidth
/ offsetHeight
: 是「元素本身」的寬度/高度,並完整了包含了邊界、捲軸及padding。
clientWidth
/ clientHeight
: 則是元素所包含的「子元素」的寬度/高度,其中包含了padding,但不包含邊界及捲軸。
我希望取得的寬度可以包含一些空間,否則input看起來會緊貼著文字,還要自己另外加一些空間,因此使用offsetWidth
。不考慮scrollWidth
是因為這裡不需要overflow。
offsetWidth
有包含padding,所以在span裡也有設定px-4
。如此一來取得的寬度就不用另外加上magic number去調整。
ref:
hide span
offsetWidth
offsetWidth(MDN)
vue lifecycle
基本上全部都按照文章的教學去寫,原理和上面的input很像,建立一個invisible textarea,再根據他的scrollHeight去調整真正textarea的高度。
problem: 編輯list title時,若按住滑鼠選取textarea內的文字,
會觸發dragging
solution:
接著在你希望觸發拖曳的div加入handle的class,如此一來便只能透過該div去拖曳。
但我希望的是input or textarea focus時可以排除,用handle會比較麻煩
Sortable.js的文件寫到:
preventOnFilter = Event.preventDefault()
根據MDN, Event.preventDefault():如果事件可以被取消,就取消事件(即取消事件的預設行為)。 但不會影響事件的傳遞,事件仍會繼續傳遞。
如此一來,當focus在textarea or input時,選取文字的click就不會觸發預設的dragging。
Tailwind似乎推出一陣子,最近才知道有這個css framework,剛好這個教學專案有用到,我就去邊查文件邊用,結果發現教案用的是0.x.x版本,現在已經到1.x.x,還好官方有教學如何update,花了一番工夫才完成,但通常應該不會需要那麼大幅度的update,因此這邊我只記錄如何install and setting。
Create a new file inside src/assets/css/tailwind.css with the following content:
import this file inside your main.js file:
optional:Run npx tailwind init to create a tailwind configuration file:
npx tailwind init
在這裡可以設定custom css settings
purge是設定讓PurgeCSS管理的檔案
Using Tailwind with PostCSS:
根目錄建立postcss.config.js,由 PostCSS 啟動 Tailwind 與 AutoPrefixer。
到這裡為止,應該就可以使用tailwind的utilities了
以下為在專案中建立一個reusable font awesome icon compoenet的步驟
free font awesome user:
安裝這些之後,fas, fab, far開頭的icon都能使用,當然也可以視你的需求去install
在這專案中我另外建立的一個plugins資料夾,新增fontawesome.js,再從App.vue import進去。官方是推薦直接在App.vue中import和設定。
./plugins/fontawesome.js
這裡做幾件事:
兩種方法:
bind an array:
property:
在fontawesome網站上,html如下
可以發現trash-alt的前綴fa-是不需要寫的
如此一來,就可以使用fontawesome網站上所有的icons,也可以把它當作 vue component一樣操作。
ref:
https://www.binarcode.com/blog/building-animated-draggable-interfaces-with-vuejs-and-tailwind/
https://fpjs.fun/tailwind/general/vue/
problem: 在Home中的 board card,想實現hover改變background,以下寫法無法生效
結果:hover時background color會改變但transition效果沒有出現
solution:
card用@apply, hover也要使用@apply
先在tailwind.config.js設定custom color #005B8F之後
problem: 如題,v-for的ListCard在card的被建立時,沒有呈現在列表中,使用Vue devtool觀察,store中確實有增加卡片,在BoardList中也能夠取得,v-for用到的cards
也是放在computed中,一有變動應該會讓v-for去render new element。
solution: 只要v-for element的key值有變化,就會render新的element,但前提是cards
不能為undefined,否則v-for就無法得知element的key值有變動。因此在create list 的mutation中加入cards的空array。