<template> <transition :name="transition ? 'van-slide-bottom' : ''"> <div v-show="show" :class="cusClass" class="keyboard-backdrop" @click="closeKeyboard"> <div v-show="show" :style="style" class="number-keyboard" @touchstart.stop @animationend="onAnimationEnd" @webkitAnimationEnd="onAnimationEnd" > <div v-if="title || showTitleClose" class="number-keyboard__title van-hairline--top"> <span v-text="title"/> <span v-if="showTitleClose" class="number-keyboard__close" @click="onClose" v-text="closeButtonText" /> </div> <div class="number-keyboard__body"> <key v-for="key in keys" :key="key.text" :text="key.text" :type="key.type" @press="onPressKey" /> </div> </div> </div> </transition> </template> <style lang="less" scoped rel="stylesheet"> .keyboard-backdrop { -webkit-transition: background-color 150ms ease-in-out; transition: background-color 150ms ease-in-out; position: fixed; top: 0; left: 0; z-index: 999; width: 100%; height: 100%; background-color: transparent; &.active { background-color: rgba(0, 0, 0, 0); } } @van-number-keyboard-key-height: 54px; .number-keyboard { left: 0; bottom: 0; width: 100%; position: fixed; user-select: none; background-color: @baseColor; animation-timing-function: ease-out; &__title { height: 30px; font-size: 13px; line-height: 30px; text-align: center; position: relative; color: #38f; border-bottom: 1px solid #e5e5e5; /*no*/ box-shadow: 0px -1px 3px rgba(0,0,0,0.1) /*no*/ } &__body { box-sizing: border-box; } &__close { right: 0; color: #38f; font-size: 14px; padding: 0 15px; position: absolute; &:active { background-color: #e8e8e8; } } .key { width: calc(100% / 3); font-size: 24px; font-style: normal; text-align: center; display: inline-block; vertical-align: middle; height: @van-number-keyboard-key-height; line-height: @van-number-keyboard-key-height; border-width: 1px 1px 0 0; /*no*/ border-bottom: 1px solid #e5e5e5; /*no*/ border-right: 1px solid #e5e5e5; /*no*/ &:nth-child(3){ border-right: none; } &:nth-child(6){ border-right: none; } &:nth-child(9){ border-right: none; } &:nth-child(10){ border-right: none; border-bottom: none; } &:nth-child(11){ border-right: none; border-bottom: none; } &:nth-child(12){ border-right: none; border-bottom: none; } } .delete { font-size: 0; background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAeCAMAAABg6AyVAAAAbFBMVEUAAAAfHiIdHB4eHR8dHR4eHB4dHB4dHR8gICIdHB4dHB4dHB4dHB8eHh8hISEeHR8fHB8fHR8fHR8fHx8eHiArKyszMzMeHB8eHB8fHR8eHiAeHh4dHB4vLjDY2Nn////b29zKysq9vb28vLzkfBRpAAAAHHRSTlMAK/PW+I/llBv77N1kSCPwWlFAOTMGBb28hHlu08g5sgAAAMlJREFUOMuV1MsWgiAQgGHQyOx+s+sgYO//jnnMGIdDDfwbN99CYEDQFiVEKkolPUG7gl9VTWC31NKuDbVz+Fc1tRJtPDmxS2BS3p5ZC+XXnnbAVoz2WEBCH7uZAalzGoa06whGiznT6sG2xgX4QO2Aej1+KN7XBKL2FvGaMtTWBhbQhtoaYzVQrHKwuGf8hhAPSF5g3xPSt45sCHcouNWx436FGA+RHyQcD35EcUj54U8ff4WYvVi1zLjelUh/OG6XjOeLWv5hfAOI+HLwwOAqhAAAAABJRU5ErkJggg==") no-repeat center center; background-size: auto 15px; } .gray { background-color: #f3f3f6; } .active { background-color: #e8e8e8; } } @keyframes van-slide-bottom-enter { from { transform: translate3d(0, 100%, 0); } } @keyframes van-slide-bottom-leave { to { transform: translate3d(0, 100%, 0); } } @keyframes van-fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes van-fade-out { from { opacity: 1; } to { opacity: 0; } } @keyframes van-rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .van-fade { &-enter-active { animation: .3s van-fade-in; } &-leave-active { animation: .3s van-fade-out; } } .van-slide-bottom { &-enter-active { animation: van-slide-bottom-enter .3s both ease; } &-leave-active { animation: van-slide-bottom-leave .3s both ease; } } // iPhoneX适配 @media (device-width: 375px) and (device-height: 812px) and (-webkit-min-device-pixel-ratio: 3) { .platform-ios { .number-keyboard { &__body { margin-bottom: 34px; } } } } // iPhoneX Max适配 @media (device-width: 414px) and (device-height: 896px) { .platform-ios { .number-keyboard { &__body { margin-bottom: 34px; } } } } </style> <script> import Key from './key' export default { name: 'NumberKeyboard', components: {Key}, props: { show: Boolean, // eslint-disable-line title: String, // eslint-disable-line closeButtonText: String, // eslint-disable-line theme: { type: String, default: 'default', }, extraKey: { type: String, default: '', }, zIndex: { type: Number, default: 100, }, transition: { type: Boolean, default: true, }, showDeleteKey: { type: Boolean, default: true, }, hideOnClickOutside: { type: Boolean, default: true, }, cusClass: { type: String, default: '', }, }, data () { return { keyBoardPlugin: false, } }, computed: { keys () { const keys = [] for (let i = 1; i <= 9; i++) { keys.push({text: i}) } keys.push( {text: this.extraKey, type: 'gray'}, {text: 0}, {text: 'delete', type: 'delete gray'} ) return keys }, style () { return { zIndex: this.zIndex, } }, showTitleClose () { return this.closeButtonText && this.theme === 'default' }, }, watch: { show () { if (!this.transition) { this.$emit(this.show ? 'show' : 'hide') } }, }, mounted () { this.handler(true) this.$el.setAttribute('vum-show-keyborad', '') }, destroyed () { this.handler(false) if (this.keyBoardPlugin) { document.body.removeChild(this.$el) } }, activated () { this.handler(true) }, deactivated () { this.handler(false) }, methods: { closeKeyboard () { let vm = this this.show = false let wrapper = document.querySelector('[vum-show-keyborad]') if (wrapper && vm.keyBoardPlugin) { document.body.removeChild(wrapper) } }, showNumberKeyboard (options) { this.keyBoardPlugin = true this.title = options.title this.closeButtonText = options.closeButtonText this.extraKey = options.extraKey this.keyDown = options.keyDown this.keyDelete = options.keyDelete this.show = true }, handler (action) { if (action !== this.handlerStatus && this.hideOnClickOutside) { this.handlerStatus = action document.body[(action ? 'add' : 'remove') + 'EventListener']('touchstart', this.onBlur) } }, onBlur () { this.$emit('blur') }, onClose () { this.$emit('close') this.show = false this.onBlur() }, onAnimationEnd () { this.$emit(this.show ? 'show' : 'hide') }, onPressKey (text) { let vm = this if (text === '') { return } if (text === 'delete') { this.$emit('delete') if (vm.keyDelete) { vm.keyDelete() } } else if (text === this.closeButtonText) { this.onClose() } else { this.$emit('input', text) if (vm.keyDown) { vm.keyDown(text) } } }, }, } </script>