起源
需求是需要在前端輸入一個陣列,該陣列作為引數請求後端介面。專案前端UI框架採用element-ui, 筆者實現的方式是 "巧用" 了 <el-select> 標籤,並新增了多選等一系列屬性,程式碼如下:
<el-select
v-model.trim="scope.row.query"
multiple // 多選
filterable
default-first-option
allow-create
placeholder="請輸入變數查詢語句">
</el-select>
複製程式碼
這樣的話使用者通過迴圈 輸入 -> 回車 動作,即可在一個輸入框內為陣列新增元素。示例如下:
( 該專案詳細資訊可參閱專案起源 )
可以看到無論是考慮互動體驗還是前端美觀性,這種實現方式都是非常良好的。
但是,遇到了下面的問題。
問題
當陣列中存在同樣的引數時, 這種方法就行不通了,因為 el-select 會幫你自動去重,示例如下:
這 ... ...
好吧 ... ...
因為筆者專案中是會存在這種應用場景的(詳情請參閱 筆者這篇作文中 dict_get 函式中的 locators 引數),所以並不能預設陣列中不會出現同樣的元素。
行吧那怎麼解決呢???
解決思路
筆者認為,任何偉大的問題的解決思路一定是 簡潔且清晰明瞭 的。
首先,我需要對自己進行一次深刻的靈魂拷問。
- Q:是改前端/後端,還是一起都改呢?
A:(os : 後端怎麼都不能因為這個情況去做任何改動,太不合理了。)好的,那就修改前端。 - Q:前端具體怎麼改呢,是自己實現一個元件還是在原有元件上做一些處理呢?
A:(os : 我才不要自己再實現一個元件呢,現在這個多好看。)好的,那就做一些處理。
經過深刻的靈魂拷問後,筆者決定在原有基礎上嘗試進行一些處理,看能否解決問題。
查閱官方文件後,我發現 el-select 標籤中可自定義 change 事件,如下所示:
那看來可以拿這個事件做點文章了嘿。
最終方案
筆者經過 深思熟慮 後,決定利用 el-select 中的 change 事件,給陣列中各個元素分別加上一個 字尾,這樣的話即可達到 陣列中無重複元素 的目的。
因考慮到字尾唯一性、複雜性以及前端觀賞性,並且因筆者基本沒見過帶括號的鍵名, 故 字尾 採用 括號加數字的形式 新增 ( 如:(1) )。
這裡主要運用了 search 函式進行 字尾查詢,如果字尾不存在的話則新增字尾,存在的話則校準字尾。 具體實現程式碼如下(js水平不高請輕噴 = =):
// 新增字尾
addSuffix(query){
const isValidQuery = query.constructor === Array && query.length > 0;
if (isValidQuery){
query.forEach((item, index) => {
const suffixStartIndex = item.search(/\([0-9]+\)/);
const expectedSuffix = '(' + (index + 1).toString() + ')';
if (suffixStartIndex === -1){
query[index] = item + expectedSuffix;
}else{
query[index] = item.substring(0, suffixStartIndex) + expectedSuffix;
}
})
}
return query
}
複製程式碼
然後在 el-select 標籤中新增 change 事件:
<el-select
v-model.trim="scope.row.query"
@change="addSuffix(scope.row.query)"
multiple // 多選
filterable
default-first-option
allow-create
placeholder="請輸入變數查詢語句">
</el-select>
複製程式碼
具體效果還是交給動圖去說話:
這樣的話,除非你特意去輸入帶有 (number) 的鍵(我是沒見過),不然基本可以 無公害 解決問題。
收拾爛攤子
接下來,我們需要在向後端傳遞引數時將 字尾 去除,這裡運用了 replace 函式,示例程式碼如下:
// 刪除字尾
self.form.setGlobalVars.forEach((setGlobalVar) => {
setGlobalVar.query.forEach((query, index) => {
setGlobalVar.query[index] = query.replace(/\([0-9]+\)/, "");
})
});
複製程式碼
然而事情到這裡就結束了嗎? 我們還需要在獲取後端資料時,將字尾加上,以供前端展示,這裡直接運用了之前封裝好的 addSuffix 函式。程式碼如下:
// 加字尾
data.setGlobalVars.forEach((setGlobalVar) => {
setGlobalVar.query = this.addSuffix(setGlobalVar.query)
});
複製程式碼
至此。這個問題算是 “完美” 解決了。
記錄了一下,從發現問題到解決問題共耗時 2小時 。
從解決問題到完成這篇文章共耗時 1整天。
感謝你能耐心看完這篇文章, 覺得有意思的小夥伴請點個贊哦! 有任何問題歡迎隨時討論~
-- 2019-5-12
複製程式碼