問題分析
前端開發告訴我說【tree組件因為存了后台存儲了全部的節點,頁面回顯時,因為父節點的關系,把子節點也全部勾上了,現在沒法處理,必須要改接口加上半選節點的參數保存起來,再在回顯時調用接口獲取到半選的節點】。
不得不說,這的確是一個解決方案,但並不是一個好的解決方案。該接口固然能實現這個需求,但是要知道接口的改動會帶來一系列意想不到的變化,比如數據庫,緩存,接口參數和返回值,而且在已經集成好的接口上拓展新的變化,根據螺旋式開發規則的風險變化,BUG會隨着螺旋的增大而急劇增大。雖然這個問題比較小,只是多存儲了一些Service端用不上屬性而已,但只是因為組件升級或bug,就需要改動功能無問題的接口,這並不是好的開發模式。作為一名優秀的開發者,首先想到的是應該用自己的辦法去解決對接的問題,如果實在沒有辦法,再考慮兩端協調的修改。
從業務分析來看 Service不論是check還是halfCheck都是必要的數據。但view端需要區分check,halfCheck來顯示不同的圖標,這就很矛盾了,可目的也很明確前端需要區分出半選節點。
那么怎么改才是最合理的呢?當然是利用JS處理回顯的邏輯,這樣即使組件變化或BUG依舊不會去改變接口。如果通過改接口修正好了,那若控件升級或bug,難道還要一改再改接口嗎,當然不能。接口的設計不可能滿足所有組件的需求,但它一定滿足業務。既然可以通過自己控制,就沒有必要去做一些更繁瑣的工作,不是嗎?
廢話不多說了,下面看代碼!
解決方案
new Vue({
el: '#app',
data: function() {
return {
data: [{
id: "1",
label: '1',
children: [{
id: "2",
label: '2-1',
children: [{
id: "21",
label: '2-1-1'
}, {
id: "22",
label: '2-1-2'
}]
}, {
id: "3",
label: '2-2',
children: [{
id: "31",
label: '2-2-1'
}, {
id: "32",
label: ' 2-2-2'
}]
}]
}],
checkStrictly: true,
defaultProps: {
children: 'children',
label: 'label'
}
}
},
mounted() {
var that = this;
["1", "2", "22", "3", "31","32"].forEach((i,n) => {
var node = that.$refs.menuListTree.getNode(i);
console.log(node.isLeaf)
if(node.isLeaf){
that.$refs.menuListTree.setChecked(node, true);
}
});
}
});
實現原理
利用tree組件渲染后帶有的isLeaf(是否為葉子節點)屬性,如果為葉子節點就選中。這樣利用tree的API就實現了正確的回顯效果。並沒有過多的邏輯,只是利用tree本身的API 出BUG的概率也不會變高。手動設置node其實和prop的default-checked-keys原理是一樣的,其實內部也都是循環,也不會出現效率的問題。所處理的也只是多了一層isLeaf的判斷而已。
總結
我走過的彎路
看到的第一反應是之前遇到過,早些年在做ztree的時候也有這個問題,當時用API就解決了,el-tree應該也有。於是查了一大圈,發現有個函數叫setCheckedKeys(keys, leafOnly),設置leafOnly = false,就可以只設置子節點選中。以為有用,於是試了一下,發現果然是【子節點】選中啊…父節點一個都沒選,於是失敗了。
又找到一個屬性叫做 check-strictly,設置check-strictly = true,賦值結束后再重置check-strictly = false表面上看起來是好試了,但仔細點看發現【父節點】不是半選的!!!又失敗了…
說心里話,這點其實el-tree可能可以優化一下會更好,這個需求早在jquery的階段就有了,ztree就解決過。el做為更新的vue組件,應該早就能設想到這種情況了,但卻沒有提供回顯半選這樣的設置屬性或者函數,這也是美中不足的地方。
可愛的地方是即使如此,依然通過API的函數組合,可以達到想要的效果,雖然看起來不是特別優雅,好在沒有花太多力氣。
如果一個問題困擾自己很久,有幾種可能:
API了解不夠深入,並不熟練
走了彎路還不肯放棄,非要一條路走到黑,掉入自己畫的圈中無法跳出
確實無法通過現有的方法實現
正確的解決問題的方式是應該靈活多變的,開發更多的提倡解耦,面向對象,而不是面向過程。就好比考試的時候遇到一個問題,答案可能有很多種。但再多的答案,都需要自己作答,而並不是去修改題目、添加條件,當然若題目出錯了自然另當別論。答案的好壞才會關系到得分的高低,再多字數,再華麗的詞匯,卻沒有得分點,那依舊是不得分的。
就我自己而言,也經常一條路跑到黑,很容易掉進坑里。一般這時候會選擇仔細的查API和代碼,終會有所發現。要么就換思路,要么就換組件。引用一句不知道誰說的話“妄圖用代碼解決一切問題的人,最終都會失敗。”因為你所使用的庫,不可能全部是自己寫的,總會有自己的邏輯無法觸及的地方,難道遇到一個就要改一份源碼嗎?當然不能。^_^
