vcode-input.vue 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <template>
  2. <view class="vcode-input-body">
  3. <text
  4. class="vcode-input-item"
  5. :class="{
  6. 'vcode-input-line': isBorderLine,
  7. 'vcode-input-border': !isBorderLine,
  8. 'on': textLength === index && focus
  9. }"
  10. v-for="(v, index) in sum"
  11. :key="index"
  12. @tap.stop="setFocus"
  13. :style="{
  14. borderColor:
  15. text.length === index && focus
  16. ? borderActiveColor
  17. : text.length > index
  18. ? borderValueColor
  19. : borderColor,
  20. color: text.length > index ? borderValueColor : borderColor
  21. }"
  22. >
  23. {{ text[index] ? text[index] : '' }}
  24. </text>
  25. <view class="hidden-input">
  26. <input
  27. id="vcodeInput"
  28. ref="vcodeInput"
  29. type="number"
  30. :show-confirm-bar="false"
  31. auto-blur
  32. :focus="focus"
  33. :maxlength="sum"
  34. v-model="value"
  35. @blur="setBlur"
  36. :password="isPassword"
  37. placeholder="验证码"
  38. />
  39. </view>
  40. </view>
  41. </template>
  42. <script>
  43. export default {
  44. name: 'VcodeInput',
  45. props: {
  46. sum: {
  47. type: Number,
  48. default: 6
  49. },
  50. isBorderLine: {
  51. type: Boolean,
  52. default: false
  53. },
  54. borderColor: {
  55. type: String,
  56. default: '#e8e8e8'
  57. },
  58. borderValueColor: {
  59. type: String,
  60. default: '#424456'
  61. },
  62. borderActiveColor: {
  63. type: String,
  64. default: '#FF6B00'
  65. },
  66. isAutoComplete: {
  67. type: Boolean,
  68. default: true
  69. },
  70. isPassword: {
  71. type: Boolean,
  72. default: false
  73. }
  74. },
  75. data() {
  76. return {
  77. focus: false,
  78. text: [],
  79. value: ''
  80. }
  81. },
  82. watch: {
  83. value(value, oldVal) {
  84. this.$emit('vcodeChange', value)
  85. if (this.isAutoComplete) {
  86. if (value.length >= this.sum) {
  87. this.focus = false
  88. this.$emit('vcodeInput', value)
  89. }
  90. } else {
  91. this.$emit('vcodeInput', value)
  92. }
  93. if (this.isPassword) {
  94. let val = ''
  95. for (let i = 0; i < value.length; i++) {
  96. val += '●'
  97. }
  98. this.text = val
  99. } else {
  100. this.text = value.split('')
  101. }
  102. }
  103. },
  104. computed:{
  105. textLength(){
  106. return this.text.length
  107. }
  108. },
  109. mounted() {
  110. this.$nextTick(() => {
  111. this.initInput()
  112. })
  113. },
  114. methods: {
  115. initInput() {
  116. this.focus = true
  117. // #ifdef H5
  118. this.$refs.vcodeInput.$refs.input.setAttribute('type', 'number')
  119. this.$refs.vcodeInput.$refs.input.setAttribute('pattern', '[0-9]*')
  120. // #endif
  121. },
  122. setBlur() {
  123. this.$nextTick(() => {
  124. this.focus = false
  125. })
  126. },
  127. setFocus() {
  128. this.focus = !this.focus
  129. },
  130. clearValue() {
  131. this.value = ''
  132. }
  133. }
  134. }
  135. </script>
  136. <style lang="scss" scoped>
  137. @keyframes cursorflash {
  138. 0%{
  139. opacity: .2;
  140. }
  141. 50%{
  142. opacity: .8;
  143. }
  144. 100%{
  145. opacity:.2;
  146. }
  147. }
  148. .vcode-input-body {
  149. margin-left: -36rpx;
  150. margin-right: -36rpx;
  151. position: relative;
  152. overflow: hidden;
  153. /* #ifndef APP-NVUE */
  154. display: flex;
  155. /* #endif */
  156. flex-direction: row;
  157. justify-content: center;
  158. align-items: center;
  159. }
  160. .vcode-input-item {
  161. width: 76rpx;
  162. height: 76rpx;
  163. margin-left: 12rpx;
  164. margin-right: 12rpx;
  165. line-height: 76rpx;
  166. text-align: center;
  167. font-weight: 500;
  168. color: #c4761f !important;
  169. border-radius: 4rpx;
  170. }
  171. .vcode-input-item.on::after {
  172. content: '|';
  173. animation: cursorflash 2s infinite ease-in-out;
  174. }
  175. .vcode-input-border {
  176. border-style: solid;
  177. border-width: 2rpx;
  178. border-color: $uni-border-color;
  179. border-radius: 4rpx;
  180. }
  181. .vcode-input-line {
  182. border-bottom-style: solid;
  183. border-bottom-width: 2rpx;
  184. border-color: $uni-border-color;
  185. }
  186. .hidden-input {
  187. width: 0px;
  188. height: 0px;
  189. position: absolute;
  190. left: -1px;
  191. top: -1px;
  192. overflow: hidden;
  193. }
  194. </style>