网上一搜一大堆类似但大多都相对简单,适用的场景并不多。多数也不支持赋值 不支持单个删除更改
我就借鉴了一下网上文章的思路,为了达到自己想要的效果做了相对应的更改。
效果图如下:
直接上代码!
WXML代码:
点击查看代码- <view wx:if="{{isSplit}}" >
- <view wx:for="{{carNum}}" wx:key="id" bind:tap='openKeyboard'>
-
- <text wx:if="{{ index === 2 }}" >.</text>
-
- <input wx:if="{{ index !== 7 }}" value="{{ item.value }}" data-index="{{index}}" disabled bindinput="updateCarNum" />
-
- <input wx:else value="{{!showNewPower ? '+' : item.value }}" data-index="{{index}}" disabled bindinput="updateCarNum" />
- </view>
- </view>
- <view wx:else>
- <input model:value="{{ vehicleNo }}" maxlength="8" placeholder="请输入车牌号" disabled="{{inputDisabled}}" focus="{{inputFocus}}" cursor="{{inputCursor}}" bind:tap='openKeyboard' bindinput="updateVehicleNo" />
- </view>
- <view hidden='{{!KeyboardState}}'>
- <view >
- <text >请输入车牌号</text>
- <view ></view>
- <view wx:if="{{!isSplit}}" bindtap='switchKeyboard'>切换键盘</view>
- <view bindtap='closeKeyboard'>关闭</view>
- </view>
-
- <view hidden="{{ focusIndex !== 0 }}">
- <view wx:for="{{provinces}}" wx:key="index" >
- <view wx:for="{{item}}" wx:key="index" wx:for-item="char" data-val="{{char}}" bindtap='bindChoose'>{{char}}</view>
- </view>
- </view>
-
- <view hidden="{{focusIndex === 0}}">
-
- <view wx:for="{{numbers}}" wx:key="index" >
- <view wx:for="{{item}}" wx:key="index" wx:for-item="char" data-val="{{char}}" bindtap="{{ focusIndex !== 1 ? 'bindChoose' : '' }}">{{char}}</view>
- </view>
-
- <view wx:for="{{letters}}" wx:key="index" >
- <view wx:for="{{item}}" wx:key="index" wx:for-item="char" data-val="{{char}}" bindtap="bindChoose">{{char}}</view>
- </view>
- <view bindtap='bindDelChoose'>
- <text >删除</text>
- </view>
- </view>
- </view>
复制代码 JS代码:
点击查看代码- import { isEmpty } from '../../utils/util';
- const icon = 'none', duration = 3000
- const component = {
- externalClasses: ['car-number-item'], // 提供给父组件外部设置样式
- properties: {
- vehicleNo: { type: String, value: undefined }, // 车牌号
- isSplit: { type: Boolean, value: false } // 是否将车牌拆分为单个字符
- },
- data: {
- provinces: [ // 省份键盘
- ['京', '沪', '粤', '津', '冀', '晋', '蒙', '辽', '吉', '黑'],
- ['苏', '浙', '皖', '闽', '赣', '鲁', '豫', '鄂', '湘'],
- ['桂', '琼', '渝', '川', '贵', '云', '藏'],
- ['陕', '甘', '青', '宁', '新']
- ],
- numbers: [ // 数字键盘
- ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
- ],
- letters: [ // 字母键盘
- ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K'],
- ['L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V'],
- ['W', 'X', 'Y', 'Z', '挂', '港', '澳', '学']
- ],
- specialChar: ['挂', '港', '澳', '学'], // 特殊字符
- carNum: Array(8).fill({ value: undefined, focus: false }),
- inputDisabled: true, // 虚拟键盘时禁用input。避免弹出系统键盘
- inputFocus: false, // input操作时获取焦点(车牌不拆分单个字符,显示为input输入框时)
- inputCursor: true, // input获取焦点弹出系统键盘时光标所在位置
- focusIndex: 0, // 输入时焦点索引(车牌拆分为单个字符时)
- showNewPower: false, // 是否新能源车牌
- KeyboardState: false // 是否弹出虚拟键盘
- },
- attached() {
- const v = this
- const vehcles = v.data.vehicleNo.split('')
- const carNum = v.data.carNum
- let showNewPower = v.data.showNewPower
- vehcles.forEach((m, i) => { carNum[i].value = m })
- if (!isEmpty(carNum[7].value)) showNewPower = true
- v.setData({ carNum, showNewPower })
- },
- /**
- * 组件的方法列表
- */
- methods: {
- // 车牌输入框点击展开车牌键盘
- openKeyboard(e) {
- const v = this
- // 车牌不拆分为单个字符时 只弹出键盘
- if (!v.data.isSplit) {
- v.setData({ KeyboardState: true, focusIndex: v.data.vehicleNo.length, inputDisabled: true, inputFocus: false })
- wx.hideKeyboard()
- }
- // 车牌拆分为单个字符
- else {
- const focusIndex = e.target.dataset.index
- let carNum = v.data.carNum
- let showNewPower = v.data.showNewPower
- // 添加新能源尾数
- if (focusIndex === 7) {
- if (isEmpty(carNum[6].value)) return wx.showToast({ title: '为新能源车牌时,前几位车牌号不能为空', icon, duration })
- if (v.data.specialChar.includes(carNum[6].value)) return wx.showToast({ title: `为新能源车牌时,第6位车牌号不能为'${carNum[6].value}'`, icon, duration })
- showNewPower = true
- v.setData({ showNewPower, KeyboardState: true })
- }
- // 当前点击获得焦点,其余失去焦点
- carNum[focusIndex].focus = true
- carNum = carNum.map((item, index) => {
- return { ...item, focus: index === focusIndex ? item.focus : false }
- })
- // 点击索引不为新能源且新能源无值时
- if (focusIndex !== 7 && isEmpty(carNum[7].value)) showNewPower = false
- v.setData({ KeyboardState: true, focusIndex, carNum, showNewPower })
- }
- },
- // 键盘选中点击设置
- bindChoose(e) {
- const v = this
- const val = e.target.dataset.val
- // 车牌不拆分为单个字符时
- if (!v.data.isSplit) {
- if (v.data.vehicleNo.length < 8) {
- const vehicleNo = v.data.vehicleNo.concat(val)
- v.setData({ vehicleNo, focusIndex: vehicleNo.length })
- v.triggerEvent('change', { vehicleNo })
- }
- }
- // 车牌拆分为单个字符
- else {
- const carNum = v.data.carNum
- let focusIndex = v.data.focusIndex
- if (focusIndex !== 6 && v.data.specialChar.includes(val)) return
- // 当前选中车牌无值时更新为输入值
- if (isEmpty(carNum[focusIndex].value)) {
- carNum[focusIndex].value = val
- carNum[focusIndex].focus = false
- const validate = v.data.showNewPower ? 7 : 6
- // 上一位车牌取消聚焦
- if (focusIndex < validate) focusIndex++
- carNum[focusIndex].focus = true
- v.setData({ carNum, focusIndex })
- }
- const vehicleNo = carNum.map(m => m.value).join('')
- v.triggerEvent('change', { vehicleNo })
- }
- },
- // 删除
- bindDelChoose() {
- const v = this
- // 车牌不拆分为单个字符时
- if (!v.data.isSplit) {
- const vehicleNo = v.data.vehicleNo.slice(0, -1)
- v.setData({ vehicleNo, focusIndex: vehicleNo.length })
- v.triggerEvent('change', { vehicleNo })
- }
- // 车牌拆分为单个字符
- else {
- const carNum = v.data.carNum
- let focusIndex = v.data.focusIndex
- let showNewPower = v.data.showNewPower
- // 如果删除第6位后继续删除 则focusIndex后退一位并删除第5位车牌 依此类推
- // 当删除至省份位车牌时,界面会控制取消删除按钮
- if (isEmpty(carNum[focusIndex].value)) {
- // 如果当前索引是新能源车牌
- if (focusIndex == 7) showNewPower = false
- focusIndex--
- carNum[focusIndex].value = undefined
- carNum[focusIndex].focus = true
- // 后一位车牌取消聚焦
- carNum[focusIndex + 1].focus = false
- }
- else {
- carNum[v.data.focusIndex].value = undefined
- carNum[v.data.focusIndex].focus = true
- }
- v.setData({ carNum, focusIndex, showNewPower })
- const vehicleNo = carNum.map(m => m.value).join('')
- v.triggerEvent('change', { vehicleNo })
- }
- },
- // 切换键盘
- switchKeyboard() {
- this.setData({ KeyboardState: false, inputDisabled: false }, () => {
- setTimeout(() => {
- this.setData({ inputFocus: true, inputCursor: this.data.vehicleNo.length })
- }, 50)
- })
- },
- // 关闭虚拟键盘
- closeKeyboard() {
- const v = this
- // 车牌不拆分为单个字符时
- if (!v.data.isSplit) v.setData({ inputDisabled: true, inputFocus: false })
- v.setData({ KeyboardState: false })
- },
- // 车牌不拆分为单个字符时,更新车牌
- updateCarNum(e) {
- const index = e.currentTarget.dataset.index
- const value = e.detail.value
- this.setData({ [`carNum[${index}].value`]: value })
- },
- // 系统键盘输入时
- updateVehicleNo() { this.triggerEvent('change', { vehicleNo: this.data.vehicleNo }) }
- }
- }
- Component(component);
复制代码 WXSS代码:
点击查看代码公用样式代码(app.wxss):
点击查看代码- .text-center {
- text-align: center;
- }
- .inline-block {
- display: inline-block;
- }
- .ml-5 {
- margin-left: 5rpx;
- }
- .mr-5 {
- margin-right: 5;
- }
- .fs-40 {
- font-size: 40rpx;
- }
- .bold {
- font-weight: bold;
- }
- .flex-center {
- display: flex;
- align-items: center;
- justify-content: center;
- }
复制代码 公用JS代码:
点击查看代码- /**
- * 是否都是空数据(类型:字符串,数值,对象,数组,布尔)
- */
- const isEmpty = (...values) => {
- const isEmptyFunc = (val) => {
- switch (typeof val) {
- case 'string':
- case 'number': return !val // 数值0为空
- case 'object':
- // 数组
- if (Array.isArray(val)) return val.length === 0
- // null/对象
- return val === null || Object.keys(val).length === 0
- case 'boolean': return false // 布尔类型即非空
- // undefined / function
- default: return true
- }
- }
- let result = true
- values.forEach(m => { result = result && isEmptyFunc(m) })
- return result
- }
- /**
- * 验证
- */
- const validate = {
- /** 是车牌号 */
- vehicle(value) {
- let result = false
- if (value && [7, 8].includes(value.length)) {
- const express = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4,5}[A-Z0-9挂学警港澳]{1}$/
- result = express.test(value)
- }
- return result
- }
- }
复制代码 调用方式:
json文件:
点击查看代码- {
- "navigationBarTitleText": "车牌号输入",
- "usingComponents": {
- "vehicle-keyboard": "../../../../components/vehicle-keyboard/index"
- }
- }
复制代码 js:
点击查看代码- // 车牌输入组件完成
- confirmVehicle(e) { this.setData({ shipNo: e.detail.vheicleNo }) }
复制代码 wxml:
点击查看代码[code][/code]上面gif生成是用 Windows 系统 Win+Shift+S 将操作截图成视频,再去这个网站 https://www.aconvert.com/cn/video/mp4-to-gif/ 将视频转成GIF
预览的时候把图片下载下来
录制gif的时候有个小bug,已被我修复。
两种模式 isSplit为true 车牌拆分成一个个小框显示,否则文本框显示同时可以切换系统键盘
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |