vant+vue在静态页面实现车牌号软键盘
1.因为是在html静态页面中使用,所以要先引入vant.css、vant.js、vue.js到需要使用的html页面;2.将实现好的车牌软键盘功能放到一个js里面,再将该组件使用js方式引入到html界面,同样该组件的css代码也要引入;2. 当在多个静态页面需要使用该组件时,如何封装成组件?1、如何将选中的车牌号回显在需要显示的表单中?
·
一、效果图
vant+vue软键盘
二、实现
1.因为是在html静态页面中使用,所以要先引入vant.css、vant.js、vue.js到需要使用的html页面;
2.将实现好的车牌软键盘功能放到一个js里面,再将该组件使用js方式引入到html界面,同样该组件的css代码也要引入;
3.这里的车牌号软键盘实现方式是借鉴的该方法:vue.js - vant-number-plate基于vue+vant+less的车牌号输入组件(车牌号虚拟键盘)_个人文章 - SegmentFault 思否
我这里稍微改进了一下,车牌号小于7位数时不能点击完成。新建一个keyboard.js文件夹,注册一个成对象,直接上代码:
// 车牌号软键盘
var keyboardVm = Vue.component('VanCardBoard', {
template: `<van-action-sheet v-model="visible" get-container="body">
<div class="vnp-header">
<button type="button" class="vnp-btn-finish" @click="finish">完成</button>
</div>
<div class="vnp-input-box-outer">
<div class="vnp-input-box" :class="{'vnp-red':activeIndex<=6}">
<ul>
<li v-for="(item, index) in val" :key="index"
:class="{ active: activeIndex === index }" @click="handleClickItem(index)">
<span>{{ item }}</span>
</li>
</ul>
</div>
</div>
<div class="vnp-keys">
<div class="vnp-keys-row" v-for="(item, index) in keyboardList" :key="index">
<div class="vnp-btn-key-wrapper" v-for="(val, index) in item" :key="index" :class="{
'vnp-del-wrapper': val === 'del',
'vnp-type-wrapper': val === 'type',
}">
<van-button v-if="val === 'type'" class="vnp-btn-key" @click="handleChangeType">
<span v-if="type === 'cn'">中/<span class="vnp-smaller">英</span></span>
<span v-else><span class="vnp-smaller">中</span>/英</span>
</van-button>
<van-button v-else-if="val === 'del'" class="vnp-btn-key" @click="handleDel">
<svg viewBox="0 0 32 22" xmlns="http://www.w3.org/2000/svg" class="vnp-delete-icon">
<path
d="M28.016 0A3.991 3.991 0 0132 3.987v14.026c0 2.2-1.787 3.987-3.98 3.987H10.382c-.509 0-.996-.206-1.374-.585L.89 13.09C.33 12.62 0 11.84 0 11.006c0-.86.325-1.62.887-2.08L9.01.585A1.936 1.936 0 0110.383 0zm0 1.947H10.368L2.24 10.28c-.224.226-.312.432-.312.73 0 .287.094.51.312.729l8.128 8.333h17.648a2.041 2.041 0 002.037-2.04V3.987c0-1.127-.915-2.04-2.037-2.04zM23.028 6a.96.96 0 01.678.292.95.95 0 01-.003 1.377l-3.342 3.348 3.326 3.333c.189.188.292.43.292.679 0 .248-.103.49-.292.679a.96.96 0 01-.678.292.959.959 0 01-.677-.292L18.99 12.36l-3.343 3.345a.96.96 0 01-.677.292.96.96 0 01-.678-.292.962.962 0 01-.292-.68c0-.248.104-.49.292-.679l3.342-3.348-3.342-3.348A.963.963 0 0114 6.971c0-.248.104-.49.292-.679A.96.96 0 0114.97 6a.96.96 0 01.677.292l3.358 3.348 3.345-3.348A.96.96 0 0123.028 6z"
fill="currentColor"></path>
</svg>
</van-button>
<van-button v-else class="vnp-btn-key" :class="{ 'vnp-btn-empty': !val }"
@click="handleClickKey(val)">
{{ val }}
</van-button>
</div>
</div>
</div>
</van-action-sheet>`,
model: {
prop: 'value',
},
props: {
show: {
type: Boolean,
default: false,
},
value: {
type: String,
default: '',
},
},
data() {
return {
value: '', //当前输入的车牌
val: ['', '', '', '', '', '', '', ''], //固定八位
activeIndex: 0, //当前活动的软键盘按钮
type: 'cn',
cn: [
['京', '津', '沪', '渝', '冀', '豫', '云', '辽', '黑', '湘'],
['皖', '鲁', '新', '苏', '浙', '赣', '鄂', '桂', '甘', '晋'],
['蒙', '陕', '吉', '闽', '贵', '粤', '青', '藏', '川', '宁'],
['type', '琼', '使', '领', '学', '警 ', '挂', '', 'del'],
],
en: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['type', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', 'del'],
],
};
},
computed: {
visible: {
set(val) {
this.$emit('update:show', val);
},
get() {
return this.show;
},
},
keyboardList() {
return this.type === 'en' ? this.en : this.cn;
},
},
watch: {
activeIndex() {
this.handleActiveChange(this.activeIndex);
},
value: {
immediate: true,
handler() {
if (this.val.join('') === this.value) {
return;
}
const val = this.value.split('');
while (val.length < 8) {
val.push('');
}
this.val = val;
},
},
},
methods: {
// 点击某个输入框
handleClickItem(index) {
this.activeIndex = index;
},
// 中英文切换
handleChangeType() {
this.type = this.type === 'en' ? 'cn' : 'en';
},
// 选中某个键盘按钮值
handleClickKey(val) {
if (val) {
this.$set(this.val, this.activeIndex, val);
if (this.activeIndex < 7) {
this.activeIndex += 1;
}
}
},
// 获焦顶部要填入的单元格
handleActiveChange(activeIndex) {
if (activeIndex === 0) {
this.type = 'cn';
} else {
this.type = 'en';
}
},
handleDel() {
this.$set(this.val, this.activeIndex, '');
if (this.activeIndex > 0) {
this.activeIndex -= 1;
}
},
finish() {
const _val = this.val.join('');
if (_val.length <= 6) return;
this.$emit('input', _val);
this.visible = false;
},
},
});
keyboard.css样式:
.vnp-header {
height: 40px;
padding-top: 6px;
position: relative;
}
.vnp-header .vnp-btn-finish {
position: absolute;
right: 0;
height: 100%;
padding: 0 16px;
color: #576b95;
font-size: 14px;
background-color: transparent;
border: none;
cursor: pointer;
}
.vnp-input-box-outer {
width: 82%;
max-width: 600px;
margin: 0 auto;
padding: 10px;
}
.vnp-input-box {
padding: 10px 0;
border: 1px solid #d8d8d8;
border-radius: 2px;
color: #8d8d8d;
font-size: 15px;
text-align: center;
}
.vnp-input-box ul {
display: flex;
}
.vnp-input-box li {
flex: 1;
border-right: 1px solid #eaeaea;
height: 28px;
line-height: 28px;
}
.vnp-input-box li:first-child {
border-right: 0;
}
.vnp-input-box li:last-child {
border: none;
}
.vnp-input-box li.active {
color: #1989fa;
}
.vnp-input-box li.active>span {
height: 100%;
width: 20px;
display: inline-block;
border-bottom: 1px solid #1989fa;
}
.vnp-red {
border: 1px solid red;
}
.vnp-keys {
padding: 3px;
background: #f2f3f5;
padding-bottom: 22px;
}
.vnp-keys .vnp-keys-row {
display: flex;
justify-content: center;
}
.vnp-keys .vnp-btn-key-wrapper {
flex: 0 1 calc((100% - 6px * 10) / 10);
padding: 3px;
box-sizing: content-box;
}
.vnp-keys .vnp-btn-key-wrapper.vnp-del-wrapper,
.vnp-keys .vnp-btn-key-wrapper.vnp-type-wrapper {
flex: 1;
}
.vnp-keys .vnp-btn-key-wrapper.vnp-type-wrapper .vnp-smaller {
color: #999;
font-size: 12px;
}
.vnp-keys .vnp-btn-key-wrapper .vnp-btn-key {
padding: 0;
width: 100%;
border-radius: 4px;
}
.vnp-keys .vnp-btn-key-wrapper .vnp-btn-empty {
background: transparent;
border: none;
}
.vnp-keys .vnp-btn-key-wrapper .vnp-delete-icon {
width: 18px;
vertical-align: middle;
}
4.在表单中使用:
<van-form>
<van-field label="车牌号" required :value="form.cardNumber" is-link placeholder="请选择" @click="showCardBoard=true"></van-field>
<!-- 车牌号软键盘 -->
<van-card-board v-model="form.cardNumber" :show.sync="showCardBoard"></van-card-board>
</van-form>
<script type="text/javascript">
var vm = new Vue({
el: '#vehicleAuditAdd',
data: {
form: {
cardNumber: ''
},
showCardBoard: false, //控制车牌号软键盘显示隐藏
}
})
</script>
三、知识点总结
1、如何将选中的车牌号回显在需要显示的表单中?
this.$emit('input',this.val)
解答:
- 子组件在传值的时候,选用input,如this.$emit(‘input’,this.val),在父组件直接用v-model绑定,就可以获取到了 。
- 子组件也可以通过$emit(‘input’,false),去改变父组件中v-model 和 子组件中 value 的值 。
因此,值在input中回显时,可以不用写自定义事件。
2. 当在多个静态页面需要使用该组件时,如何封装成组件?
解答:
- 因为已经在静态页面引入了vue.js,所以我们可以使用 Vue 应用实例的
app.component()
方法,让组件在当前 Vue 应用中全局可用。 - 语法:
- 如果同时传递一个组件名字符串及其定义,则注册一个全局组件;如果只传递一个名字,则会返回用该名字注册组件 (如果存在的话)。
- Vue 支持将模板中使用 kebab-case 的标签解析为使用 PascalCase 注册的组件。例如VanCardBoard为名注册的组件,在模板中可以通过
<VanCardBoard>
或<van-card-board>
引用。
更多推荐
已为社区贡献9条内容
所有评论(0)