├── .gitignore ├── LICENSE ├── README.md ├── dist └── VueInputCode.js ├── example ├── app.js ├── code.png ├── example.html └── index.js ├── package.json ├── src ├── InputCode.vue └── index.js ├── webpack.config.js ├── webpackExample.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IJ 26 | # 27 | *.iml 28 | .idea 29 | .gradle 30 | local.properties 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | 37 | # BUCK 38 | buck-out/ 39 | \.buckd/ 40 | android/app/libs 41 | android/keystores/debug.keystore 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 zhouyuexie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-input-code 2 | 3 | ## 基于Vue2.0+的移动端验证码输入组件. 4 | 5 | 6 | 7 | ## 功能预览 8 | 9 | + 输入时回调 10 | + 结果回调 11 | + 自定义错误处理 12 | + 自定义验证码个数 13 | + 样式可控 14 | 15 | [这里是可爱的Demo](https://quietboys.github.io/vue-input-code/) 16 | 17 | ## 支持 18 | 19 | 支持 Vue.js 2.0+. 20 | 21 | ## 安装和使用 22 | 23 | ```javascript 24 | npm install vue-input-code --save 25 | ``` 26 | 27 | - 作为全局组件使用 28 | 29 | ```javascript 30 | //在项目入口文件 31 | import Vue from 'vue'; 32 | import VueInputCode from 'vue-input-code'; 33 | Vue.component('VueInputCode', VueInputCode) 34 | ``` 35 | 36 | - 作为局部组件 37 | 38 | ```javascript 39 | //在某个组件中 40 | import VueInputCode from 'vue-input-code' 41 | export default { 42 | components: { 43 | VueInputCode 44 | } 45 | } 46 | ``` 47 | 48 | HTML中使用: 49 | 50 | ```html 51 | 52 | 53 | 54 | 55 | 56 | ``` 57 | 58 | ## API 59 | 60 | | 参数 | 类型 | 说明 | 可选值 | 默认值 | 61 | | ------------- |-------| -----| ----| -------| 62 | | code | 数组 | 用户输入的验证码数组 | — | — | 63 | | type | 字符串 | 用户输入类型 | number,text | number | 64 | | upper-case | Boolean | 类型为text的时候可调整输入的字符串为大写 | true,false | false | 65 | | get-input | 函数 | 用户每次输入后的回调函数,接受一个验证码字符串 | — | — | 66 | | success | 函数 | 用户输入完成后的回调函数,接受一个验证码字符串 | — | — | 67 | | error | 函数 | 用户输入不是预期的值的回调函数,接收一个错误的值 | — | — | 68 | | customValidate | 函数 | 自定义判断用户输入值是否正确,判断输入错误则需返回`false`,正确则返回`true`| — | — | 69 | | span-size | 字符串 | 输入后的字体显示大小 | — | 20px | 70 | | span-color | 字符串 | 输入后的字体显示颜色 | — | #f35252 | 71 | | input-size | 字符串 | 输入框的字体显示大小 | — | 20px | 72 | | input-color | 字符串 | 输入框的字体显示颜色 | — | #000 | 73 | | number | 数字 | 验证码个数 | — | 6 | 74 | | height | 字符串 | 整个框的显示高度 | — | 60px | 75 | 76 | ## CHANGELOG 77 | 78 | - version 1.3.1: fixed [issuse](https://github.com/zhouyuexie/vue-input-code/issues/4) about chinese input method bug. 79 | - version 1.5.0: add customValidate 80 | -------------------------------------------------------------------------------- /dist/VueInputCode.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.VueInputCode=e():t.VueInputCode=e()}(window,function(){return i={},o.m=n=[function(t,e,n){var i=n(3),o=n(4);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[t.i,o,""]]);var r={insert:"head",singleton:!1};i(o,r);t.exports=o.locals||{}},function(t,e,n){"use strict";t.exports=function(n){var d=[];return d.toString=function(){return this.map(function(t){var e=function(t,e){var n=t[1]||"",i=t[3];if(!i)return n;if(e&&"function"==typeof btoa){var o=function(t){var e=btoa(unescape(encodeURIComponent(JSON.stringify(t)))),n="sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(e);return"/*# ".concat(n," */")}(i),r=i.sources.map(function(t){return"/*# sourceURL=".concat(i.sourceRoot||"").concat(t," */")});return[n].concat(r).concat([o]).join("\n")}return[n].join("\n")}(t,n);return t[2]?"@media ".concat(t[2]," {").concat(e,"}"):e}).join("")},d.i=function(t,e,n){"string"==typeof t&&(t=[[null,t,""]]);var i={};if(n)for(var o=0;odiv{border:1px solid #323232;font-weight:900;background-color:white}.vue_input_code .input>div:nth-child(n){border-right:none}.vue_input_code .input>div:last-child{border-top-right-radius:5px;border-bottom-right-radius:5px;border-right:1px solid #323232}.vue_input_code .input>div input{font-size:20px;width:90%;color:#323232;text-align:center;outline:none;border:none;margin-right:5px;-webkit-tap-highlight-color:rgba(255,255,255,0)}.vue_input_code .input .input-code{position:absolute;top:0;left:0;margin-left:1%;border:none;background:none;display:flex;flex-direction:row;justify-content:center;align-items:center}.vue_input_code .input>span{border:1px solid #323232;font-weight:900;background-color:white;display:inline-block;text-align:center;font-size:20px}.vue_input_code .input>span:nth-child(n){border-right:none}.vue_input_code .input>span:first-child{border-top-left-radius:5px;border-bottom-left-radius:5px}.vue_input_code .input>span:last-child{border-top-right-radius:5px;border-bottom-right-radius:5px;border-right:1px solid #323232}.vue_input_code .input>span.first{border-top-left-radius:5px;border-bottom-left-radius:5px}.vue_input_code .input .input-code.first{border-top-left-radius:5px;border-bottom-left-radius:5px}.vue_input_code .input .input-code.last{border-top-right-radius:5px;border-bottom-right-radius:5px}\n",""]),e.default=o},function(t,e,n){"use strict";n.r(e);var i={props:{code:{type:Array,default:function(){return[]},required:!0},success:{type:Function,default:function(){}},error:{type:Function,default:function(){}},customValidate:{type:Function,default:void 0},getInput:{type:Function,default:function(){}},spanSize:{type:String,default:"20px"},spanColor:{type:String,default:"#f35252"},inputSize:{type:String,default:"20px"},inputColor:{type:String,default:"#000"},height:{type:String,default:"40px"},number:{type:Number,default:6},type:{type:String,default:"number",validator:function(t){return-1<["number","text"].indexOf(t)}},upperCase:{type:Boolean,default:!1}},data:function(){return{inputCodeNum:0,left:"0",inputCode:"",codeArray:[],blockWidth:(100/this.number).toFixed(4)+"%",blockSize:(100/this.number).toFixed(4),block:[],zIndex:10}},created:function(){for(var t=0;t 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 验证码输入组件 12 | 45 | 46 | 47 | 48 | 验证码输入 49 | 50 | 高度40px 51 | 54 | 高度60px 55 | 58 | 显示颜色 59 | 62 | 字体大小 63 | 66 | 4位验证码大写 67 | 70 | 11位手机号 71 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import VueInputCode from '../src/inputcode.vue'; 3 | // Vue.component('VueInputCode', VueInputCode); 4 | 5 | new Vue({ 6 | el:"#app", 7 | data:{ 8 | code:[], 9 | code1:[], 10 | code2:[], 11 | code3:[], 12 | code4:[], 13 | code5:[], 14 | codeString:"", 15 | input:"" 16 | }, 17 | created(){ 18 | 19 | }, 20 | methods:{ 21 | success(code){ 22 | this.codeString = code; 23 | }, 24 | getInput(code){ 25 | this.input = code; 26 | }, 27 | error(code){ 28 | console.log("错误输入:", code) 29 | } 30 | }, 31 | components:{ 32 | VueInputCode 33 | } 34 | }) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-input-code", 3 | "version": "1.5.0", 4 | "description": "基于vue2.0+的验证码输入组件", 5 | "main": "src/index.js", 6 | "directories": { 7 | "example": "example" 8 | }, 9 | "scripts": { 10 | "start": "NODE_ENV=development webpack", 11 | "build": "NODE_ENV=production webpack", 12 | "example": "NODE_ENV=development webpack --config webpackExample.config.js" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/zhouyuexie/vue-input-code.git" 17 | }, 18 | "browsers": [ 19 | "last 2 versions", 20 | "last 3 Safari versions" 21 | ], 22 | "keywords": [ 23 | "vue", 24 | "input", 25 | "code", 26 | "input-code" 27 | ], 28 | "author": "zhouyuexie", 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/zhouyuexie/vue-input-code/issues" 32 | }, 33 | "homepage": "https://github.com/zhouyuexie/vue-input-code#readme", 34 | "devDependencies": { 35 | "@babel/core": "^7.11.6", 36 | "@babel/plugin-transform-runtime": "^7.11.5", 37 | "@babel/preset-env": "^7.11.5", 38 | "@babel/register": "^7.11.5", 39 | "@babel/runtime": "^7.11.2", 40 | "babel-eslint": "^10.1.0", 41 | "babel-loader": "^8.1.0", 42 | "babel-runtime": "^6.26.0", 43 | "css-loader": "^4.3.0", 44 | "ejs-loader": "^0.5.0", 45 | "eslint": "7.9.0", 46 | "eslint-loader": "^4.0.2", 47 | "eslint-plugin-html": "^6.1.0", 48 | "file-loader": "^6.1.0", 49 | "html-webpack-plugin": "^4.5.0", 50 | "node-sass": "^4.14.1", 51 | "postcss-loader": "^4.0.2", 52 | "sass-loader": "^10.0.2", 53 | "style-loader": "^1.2.1", 54 | "uglifyjs-webpack-plugin": "^2.2.0", 55 | "underscore": "^1.11.0", 56 | "url-loader": "^4.1.0", 57 | "vue": "^2.6.12", 58 | "vue-hot-reload-api": "^2.3.4", 59 | "vue-html-loader": "^1.2.4", 60 | "vue-loader": "^15.9.3", 61 | "vue-style-loader": "^4.1.2", 62 | "vue-template-compiler": "^2.6.12", 63 | "webpack": "^4.44.2", 64 | "webpack-cli": "^3.3.12", 65 | "webpack-stream": "6.1.0" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/InputCode.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 19 | 20 | 21 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 42 | 221 | 222 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import VueInputCode from './InputCode.vue'; 2 | 3 | if (typeof window !== 'undefined' && window.Vue) { 4 | Vue.component('vue-input-code', VueInputCode); 5 | } 6 | 7 | export default VueInputCode; 8 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const {VueLoaderPlugin} = require("vue-loader"); 2 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); 3 | 4 | const isDev = process.env.NODE_ENV === 'development'; 5 | 6 | module.exports = { 7 | entry: './src/index.js', 8 | mode: process.env.NODE_ENV || 'development', 9 | output: { 10 | library: 'VueInputCode', 11 | libraryTarget: 'umd', 12 | path: __dirname + '/dist', 13 | filename: 'VueInputCode.js' 14 | }, 15 | resolve: { 16 | extensions: ['.js', '.vue', '.css'] 17 | }, 18 | externals: { 19 | vue: 'Vue' 20 | }, 21 | module: { 22 | rules: [{ 23 | // 这是处理es6文件 24 | test: /\.js$/, 25 | loader: 'babel-loader', 26 | exclude: /node_modules/, 27 | options: { 28 | presets: ['@babel/preset-env'], 29 | plugins: ['@babel/plugin-transform-runtime'] 30 | } 31 | }, { 32 | //这是处理scss文件 33 | test: /\.scss$/, 34 | use: ['style-loader', 'css-loader', 'sass-loader'] 35 | }, { 36 | test: /\.vue$/, 37 | include: /src/, 38 | loader: 'vue-loader', 39 | }, { 40 | // 这是处理css文件 41 | test: /\.css$/, 42 | use: ['style-loader', 'css-loader', 'sass-loader'] 43 | }, { 44 | test: /\.(png|jpg|gif)$/, 45 | loader: 'url-loader', 46 | options: { 47 | // Inline files smaller then 10kb as base64 dataURL 48 | limit: 10000, 49 | // Fallback to file-loader with this naming scheme 50 | name: '[name].[ext]?[hash]' 51 | } 52 | }] 53 | }, 54 | watch: isDev, 55 | optimization: { 56 | minimizer: [ 57 | new UglifyJsPlugin({ 58 | uglifyOptions: { 59 | output: { 60 | comments: false 61 | } 62 | } 63 | }) 64 | ] 65 | }, 66 | plugins: [new VueLoaderPlugin()] 67 | } -------------------------------------------------------------------------------- /webpackExample.config.js: -------------------------------------------------------------------------------- 1 | const {VueLoaderPlugin} = require("vue-loader"); 2 | 3 | module.exports = { 4 | entry: './example/index.js', 5 | mode: 'development', 6 | output: { 7 | library: 'VueInputCode', 8 | libraryTarget: 'umd', 9 | path: __dirname + '/example', 10 | filename: 'app.js' 11 | }, 12 | devtool: 'inline-source-map', 13 | resolve: { 14 | alias: { 15 | 'vue$': 'vue/dist/vue.esm.js' 16 | }, 17 | extensions: ['*', '.js', '.vue', '.json'], 18 | }, 19 | module: { 20 | rules: [{ 21 | // 这是处理es6文件 22 | test: /\.js$/, 23 | loader: 'babel-loader', 24 | exclude: /node_modules/, 25 | options: { 26 | presets: ['@babel/preset-env'], 27 | plugins: ['@babel/plugin-transform-runtime'] 28 | } 29 | }, { 30 | //这是处理scss文件 31 | test: /\.scss$/, 32 | use: ['style-loader', 'css-loader', 'sass-loader'] 33 | }, { 34 | test: /\.vue$/, 35 | include: /src/, 36 | loader: 'vue-loader', 37 | }, { 38 | // 这是处理css文件 39 | test: /\.css$/, 40 | use: ['style-loader', 'css-loader', 'sass-loader'] 41 | }, { 42 | test: /\.(png|jpg|gif)$/, 43 | loader: 'url-loader', 44 | options: { 45 | // Inline files smaller then 10kb as base64 dataURL 46 | limit: 10000, 47 | // Fallback to file-loader with this naming scheme 48 | name: '[name].[ext]?[hash]' 49 | } 50 | }] 51 | }, 52 | watch: false, 53 | plugins: [new VueLoaderPlugin()] 54 | } --------------------------------------------------------------------------------
高度40px
高度60px
显示颜色
字体大小
4位验证码大写
11位手机号