受限于项目的要求,在前端不能使用诸如iview-ui和element-ui这类组件,只能使用原生html标签,但可以使用vue2。在项目中有一个功能需要输入车牌号,如果仅仅使用普通输入框,输入操作比较繁琐,并且容易出错,对用户体验不是很友好。于是我编辑了一个简单的车牌号选择器组件,使用vue2+html5标签实现。效果图展示:

如何使用vue2+html简单实现车牌号选择功能_选择器

如何使用vue2+html简单实现车牌号选择功能_字符串_02

效果图展示的组件样式比较简单,组件代码如下:

var ChooseCarno = {
    template: `<div class="license-plate-selector">
        <input type="text" class="form-control" v-model="selectedPlate" @focus="showPopup = true" placeholder="请选择车牌号码" />
        <div v-if="showPopup" class="popup">
            <div class="selected-keys">
                <span>已选择: </span>
                <span v-if="selectedProvince">{{ selectedProvince }} </span>
                <span v-for="(char, index) in selectedChars" :key="index">{{ char }} </span>
                <div class="button-group">
                    <button class="confirm-button" @click="generatePlate">确认</button>
                    <button class="clear-button" @click="clearSelection">清除</button>
                    <button class="back-button" @click="undoSelection">回退</button>
                    <button class="close-button" @click="hidePopup">关闭</button>
                </div>
            </div>
            <div class="keyboard">
                <div v-for="province in provinces" :key="province" class="key" :class="{ selected: selectedProvince === province }" @click="selectProvince(province)">
                    {{ province }}
                </div>
            </div>
            <div class="keyboard">
                <div v-for="letter in letters" :key="letter" class="key" :class="{ selected: selectedChars.includes(letter) }" @click="addChar(letter)">
                    {{ letter }}
                </div>
            </div>
            <div class="keyboard">
                <div v-for="number in numbers" :key="number" class="key" :class="{ selected: selectedChars.includes(number) }" @click="addChar(number)">
                    {{ number }}
                </div>
            </div>
        </div>
    </div>`,
    data: function () {
        return {
            selectedPlate: '',
            showPopup: false,
            selectedProvince: '',
            selectedChars: [],
            provinces: '京沪津渝冀晋蒙辽吉黑苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云藏陕甘青宁新'.split(''),
            letters: 'ABCDEFGHJKLMNPQRSTUVWXYZ'.split(''), // 排除 I 和 O
            numbers: '0123456789'.split('') // 只有 0 到 9
        }
    },
    props:{
        carNo:{type:String, default:"" },
    },
    watch: {
        carNo: function (newval) {
            this.selectedPlate = newval;
            this.selectedProvince = this.selectedPlate.split('')[0];
            this.selectedChars = this.selectedPlate.substr(1).split('');
        }
    },
    methods: {
        hidePopup() {
            this.showPopup = false;
        },
        selectProvince(province) {
            this.selectedProvince = province;
        },
        addChar(char) {
            this.selectedChars.push(char);
        },
        generatePlate() {
            if (this.selectedProvince && this.selectedChars.length > 0) {
                this.selectedPlate = `${this.selectedProvince}${this.selectedChars.join('')}`;
                this.showPopup = false;

                this.$emit("sure", this.selectedPlate);
            } else {
                $.Dialog.error("请选择车牌号");
            }
        },
        clearSelection() {
            this.selectedProvince = '';
            this.selectedChars = [];
        },
        undoSelection() {
            if (this.selectedChars.length > 0) {
                this.selectedChars.pop();
            }
        }
    }
}

对上述代码的一些关键点,我简单做下说明:定义了provinces、letters和numbers属性,分别对应省份、大写字母和数字,字母排除I和O,因为车牌号不包含这两个字母,split方法将字符串拆分成字符数组,方便便利。

定义carNo属性,用来接收父组件传递的车牌号回显。监听carNo属性,当carNo属性变化时,从传递过来的车牌号拆分出省份和字母数字的字符串,打到回显的目的。

hidePopup方法关闭组件弹出窗,selectProvince方法提供选择省份并赋值到车牌号字符串功能,addChar方法按点击按键先后顺序组成车牌号字符串,generatePlate方法将省份和字母数字组合成车牌号字符串,并向父组件抛出一个携带车牌号码的确认方法,clearSelection方法用于清除已选择的车牌号,undoSelection方法回退上一次车牌号选择。

这个组件的功能相对简单,样式控制略微复杂,下面是样式代码:

.license-plate-selector {
    position: relative;
    display: inline-block;
    background: white;
    /*padding: 20px;*/
    border-radius: 8px;
    /*box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);*/
    text-align: center;
    width: 100%; /* 进一步增加宽度 */
}

.popup {
    position: absolute;
    top: -300px; /* 放在输入框上方 */
    left: 0;
    right: 0;
    background: white;
    border: 1px solid #ccc;
    box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
    z-index: 1000;
    width: 100%;
    padding: 10px;
    max-height: 350px; /* 增加最大高度 */
    overflow-y: auto; /* 允许垂直滚动 */
    overflow-x: hidden; /* 避免水平滚动条 */
}

.keyboard {
    display: flex;
    flex-wrap: wrap; /* 允许换行 */
    gap: 5px;
    justify-content: center;
    margin-bottom: 20px; /* 增加底部间距 */
}

.key {
    padding: 10px;
    text-align: center;
    cursor: pointer;
    background-color: #f0f0f0;
    border: 1px solid #ccc;
    flex: 0 0 auto; /* 固定宽度 */
    min-width: 30px; /* 设置最小宽度 */
    max-width: calc(100% / 20 - 5px); /* 每行最多20个 */
}

.key:hover {
    background-color: #e0e0e0;
}

.key.selected {
    background-color: #007bff;
    color: white;
}

input {
    width: 100%;
    padding: 5px;
    box-sizing: border-box;
    margin-bottom: 10px;
}

.selected-keys {
    margin-bottom: 10px;
    font-size: 16px;
    font-weight: bold;
    display: flex;
    align-items: center;
    justify-content: center; /* 居中对齐 */
}

.button-group {
    display: flex;
    justify-content: center;
    margin-top: 10px;
}

.button-group button {
    padding: 10px;
    background-color: #007bff;
    color: white;
    border: none;
    cursor: pointer;
    margin: 0 5px; /* 增加左右边距 */
}

.button-group button:hover {
    background-color: #0056b3;
}

组合上面的代码,就能得到一个简单的车牌号选择器组件了。当然,我这里的组件功能很简单,大家也可以发挥主观能动性,拓展组件,例如增加车牌号长度判定,新能源车牌号和燃油车牌号控制,样式优化等。

欢迎大家交流...