帶下拉選項的輸入框 (Textbox with Dropdown) 是既允許使用者從下拉選單中選擇輸入又允許使用者自由鍵入輸入值。這算是比較常見的一種 UI 元素,可以為使用者提供候選項節省操作時間,也可以給可能存在的少數情況提供適配的可能。
本來想著這個元件比較常見應該已經有比較多現成的例子可以直接應用,但是搜尋了一圈發現很多類似的元件都具備了太多的功能,例如搜尋,多選等等 (簡單說:太複雜了!)。於是就想著還是自己動手寫一個簡單易用的,此處要感謝肥老闆在我困惑時的鼎力相助。
這個 UI 元素將被用於 Common Bar Width App 中。
註冊元件
通過將封裝好的元件程式碼複製貼上來註冊全域性元件。
設計的時候有考慮到輸入框可能存在不同的型別,例如文字輸入框,數值輸入框,百分數輸入框等等。所以在封裝的程式碼中會通過函式 inputRule
來限制輸入。限制的方法是利用 Regex 進行過濾。如果有其他型別,也可以通過修改 inputRule
中的過濾條件。
<script type="text/x-template" id="dropdown">
<div class="dropdown" v-if="options">
<!-- Dropdown Input -->
<input :type="type"
:disabled="disabled"
v-model="input_value"
@focus="showOptions()"
@blur="exit()"
@keyup="keyMonitor"
@input="input_value = inputRule(type)" />
...
</script>
<script>
Vue.component('dropdown', {
template: '#dropdown',
props: {
type: String,
options: Array,
disabled: Boolean,
value: String
},
...
methods: {
inputRule:function(type){
var value;
switch(type){
case 'text':
value = this.input_value.replace(/[^a-zA-Z0-9]/g,'');
break;
case 'number':
value = this.input_value.replace(/^(?![+-]?\d+(\.\d+)?$)/g,'');
break;
case 'percentage':
value = this.input_value.replace(/[^\d]/g,'');
value = value > 100 ? '100' : value;
value = value < 0 ? '0' : value;
break;
default:
console.log("no limitation");
}
return value;
},
...
</script>
呼叫元件
新增自定義標籤呼叫元件。
<dropdown type = "text"
:options = "text_options"
:value = "text_value"
:disabled = "text_disabled"
@on_change_input_value = "onTextChange">
</dropdown>
傳遞資料
最後動態繫結資料到父級元件, props 中:
- type: 輸入框的型別,現支援 text, number 和 percentage。
- options: 輸入框下拉選單的選項
- value: 輸入框的值
- disabled: 是否禁止點選輸入框
另外我們還需要在父級例項中定義事情,用於更新輸入框的值
- on_change_input_value: 更新值
data: function () {
return {
text_value: 'ccc',
text_disabled: false,
text_options: [
{ id: 1, name: 'a' },
{ id: 2, name: 'bb' },
{ id: 3, name: 'ccc' },
{ id: 4, name: 'dddd' },
{ id: 5, name: 'eeeee' },
{ id: 6, name: 'fffff ' },
{ id: 7, name: 'gggggg' },
{ id: 8, name: 'hhhhhhh' },
{ id: 9, name: 'iiiiiiii' },
],
...
}
},
...
methods: {
onTextChange: function (new_text_value) {
this.text_value = new_text_value;
},
...
},