任务描述:
使用vue封装一个输入框组件,实现基本的正则验证,前后缀图标插入等功能
具体完成内容:
router/index.js中路由配置
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/pages/home'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/', //这里是路由也就是网址跳转的路径
name: 'home', //路由名称
component: Home //注册组件,注意这里要与具体组件中export default中设置的一致
}
]
})
page/home/index.vue:使用输入框组件构建的页面
<template> <div id="wrap"> <p class="text">普通输入框:</p> <input-box placeholder="请输入内容" id="normal"/> //注意普通类型的参数传递,直接就是常规的属性写法 <p class="text">字数限制输入框:</p> <input-box placeholder="输入限制为最多10个" maxlength="10"/> <p class="text">禁止输入框:</p> <input-box :disabled="true" placeholder="禁止输入" class="wrap-no-input" id="forbid"/> //布尔值的参数传递需要加冒号变成动态的,表示传入的不是字符串,是一个表达式 <p class="text">密码输入框:</p> <input-box type="password" placeholder="请输入密码" id="pwd"> <i class="iconfont icon-hidepwd right" slot="right" @click="change"></i> //事件绑定使用v-on的简写形式@事件名="函数名" </input-box> <p class="text">带前后缀图标输入框:</p> <input-box placeholder="请输入要搜索的内容" id="withIcons"> <i class="iconfont icon-search left" slot="left"></i> //有名插槽的写法 <i class="iconfont icon-close right" slot="right"></i> </input-box> <p class="text">正则验证输入框:</p> <input-box placeholder="6-8位字母或数字" id="regConfirm" pattern="/^([0-9a-zA-Z]){6,8}$/g" @addTip = "showTip"/> </div> </template> <script> import InputBox from '@/components/InputBox'; //引入组件 export default { name: 'Home', components:{ InputBox //注册组件 }, data () { return { } }, methods:{ showTip(res){ var tip = document.getElementById("tip"); if(tip) { if(res == "验证成功") { tip.style.color = "green"; }else{ tip.style.color = "red"; } tip.innerText = res; }else{ var wrap = document.getElementById('wrap'); var el = document.createElement('p'); el.id = "tip"; el.innerText = res; el.style.fontSize ="10px"; if(res == "验证成功") { el.style.color = "green"; }else{ el.style.color = "red"; } wrap.appendChild(el); } }, change(e){ var list = e.target.classList; if(list.contains('icon-hidepwd')){ list.remove('icon-hidepwd'); list.add('icon-showpwd'); document.getElementById("pwd").type="text" }else if (list.contains('icon-showpwd')){ list.remove('icon-showpwd'); list.add('icon-hidepwd'); document.getElementById("pwd").type="password" } } } } </script> <style> @import "../../assets/css/iconfont.css"; //引入样式,注意这里引入的是外部的,style标签上不要添加scoped .text{ font-size:15px; } .left,.right{ color:rgb(150, 149, 149); } </style>
components/InputBox.vue:输入框组件具体封装
<template> <div :class="className"> <slot name="left" class="left"></slot> <input :type="type" //动态参数的绑定,使用v-bind的简写形式冒号: :placeholder="placeholder" :disabled = "disabled" :maxlength="maxlength" :id = "id" :pattern = "pattern" class="input" v-model = "content" //v-model双向数据绑定 @blur = "blur" /> <slot name="right"></slot> </div> </template> <script> export default { name: 'InputBox', props:{ //参数接收。注意一般会校验类型,以及设置default默认值 type:{ type:String, default:'text' }, placeholder:{ type:String, default:'' }, leftshow:{ type:Boolean, default:false }, rightshow:{ type:Boolean, default:false }, disabled:{ type:Boolean, default:false }, maxlength:{ type:String, default:'100' }, className:{ type:String, default:'wrap' }, id:{ type:String, default:'' }, pattern:{ type:String, default:'' } }, data () { return { content:'', succShow:false, errShow:false } }, methods:{ blur(e){ if(this.id === 'regConfirm'){ var patt = eval(this.pattern); //子组件接收到的props参数,也是可以直接使用this.参数名来调用的 if(patt.test(e.target.value)){ //e.target.value获取输入框中的内容 var res = "验证成功" }else{ var res = "验证失败" } } this.$emit('addTip',res); //子组件中触发事件,参数分别为事件名和参数,父组件中监听的话,也是直接@事件名,与这里是一致的 } } } </script> <style> *{ padding:0; margin:0; } .wrap{ display: flex; align-items: center; width: 200px; height: 30px; padding: 0 12px; margin:10px auto; background-color: #fff; border:1px solid rgb(31, 31, 31); border-radius: 5px; } .input{ flex: 1; background: none; border: 0; margin: 0 10px; color: #999; line-height: 1.5; outline:none; /* 兼容火狐浏览器,去掉input本身红色边框的写法 */ -moz-appearance: none !important; outline: none !important; -moz-outline: none !important; box-shadow: none !important; -moz-box-shadow: none !important; } .wrap-no-input{ display: flex; align-items: center; width: 200px; height: 30px; padding: 0 12px; margin:10px auto; background-color: rgb(185, 184, 184); border:1px solid rgb(31, 31, 31); border-radius: 5px; color:#fff; } .wrap-no-input .input{ color:#fff; } .wrap-textarea{ display: flex; align-items: center; width: 200px; height: 100px; padding: 0 12px; margin:10px auto; background-color: #fff; border:1px solid rgb(31, 31, 31); border-radius: 5px; color:#fff; } </style>
assets/css中引入字体图标文件并且创建fonts文件夹放入字体图标相关文件,注意修改下面的路径,不然报错:
@font-face {font-family: "iconfont";
src: url('../fonts/iconfont.eot?t=1587914589125'); /* IE9 */
src: url('../fonts/iconfont.eot?t=1587914589125#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAASEAAsAAAAACPAAAAQ1AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDKgqFBIQ/ATYCJAMUCwwABCAFhG0HWxvWB8iemjwJgtkgAgAFMo0jIYKv/dB9d/chhC5RgAqAVKKiItOycCxcK1vVqVJsVH3ZiAz/nvZeMwiZ1HYw2h2UtUmWKbs0EzLrhC8J5Yl/0tctJxb0E3AN+If7Ga98gPns21yywqJtOsEBdV+H6B3Iifotw6sOcjdOE+g0LhA8zsgrA3oKfVIgnlIkBvQSSqUiM7RCXbCygHgLKm0a5t0DvPF+P/6DxdADkioD/ayr++lSkPST+uSDdC9ykznwuj892HVkLAAK8bjQeAsJggsQnXK8lnVAa+gTfQW9PvksLlJYT/ZaGJX/8jpRhCQTNdCF3Ri3Hyr8pCyEwi9PhOCXF0Lil4/IuWIqcWdP4e9AjHHSiT6/KUtyY2pipW9kZGfk5A9JEdz6JKK7rBhseRw+b1t8ykClEm8Ti6zPKYRKpWi0XJTYiPnx3ZutRBfVgpK5I4ow0bqT5LFH3Y9H5dyTJWm9Wl1erlMolpn8Mp8ej1epWsRX1bCYlZ40qi4UzY/a2q7jWmv2LlOp2owW9nB7DY3FC85TjlqL5q3nu63mrMrmRvZwtssg9yTC5NgjUL9+HG56Ug4ht+cU8G6Xp0nZdaAut9fHdHS3Peg+vRf+uypdow2XtNY7hNl5bzMlD/X0y4Fr1sAcvf3vCgpfHk4utwyS3Z3oBZcXDszaewQRNCK9kFlRu1SKxRbz+eyd8V7olWZskJv719r/f79sw/LhZcNBltkARDNojjUb5EQ5OQd74Z3xIBlhNJL2kVlg67Wh/MlOQUcmslOj2WnbEbUGcWVqNd4tq0PgIJc3WhHrSavQtwre4LGjg4hBc+S8wQhz7ErHwOrH0tFH7k7uJnOlZRsdQh2HWtunic0um8gpf+aQY4jjBttDtKeHMDbJw7OAxifFCu9GW/5IlsJm1Mxi2MLdYsjMzLKZt9SS94NmujI/+xR6yC9464G7s8FPpsLye4T7VP7Ghy5ov9o07nebFoAfd2+txPY7BcBEnjcLzPowWMCGonB0VVWkYospmSpnsTgJnYaGDyLKoFf9iEfA6YTWSARJYwyy1gSq4Bag0mUZaq096DQvc32XIQxEFH3AnH4Eod9BSHp9gqzffVTBvYTKqM9Q6w8EOl2H5Y5dpoIySGVwjMWlaEULSknoOsLUsAZ+ZglONtRgTJzjEcQ4I6M8aDBfmI5k4nU408ccWSMZwrIESjB0LZqBzsNrami0nqGrcAnLr2TZ+hiBgCh6Jb6ErgUGjjBwGBZOClWhBYoiQatDOJ1ZBpmfL4EjNaiBYSpKytRiOIYM1T0qGJ8QgMoU1oFKzqW/TCNSCBaLoMYRGLRaqAysx9UYQRqqvnhYFZwEi6+yhb9eDAFpRUCF/PHFtdeY9WeW1Q+pggcRqAW1oQ7ofsjWYjXh+98mjIr1iDYgsDpSilVRTqEO20BJKhsAAAAAAA==') format('woff2'),
url('../fonts/iconfont.woff?t=1587914589125') format('woff'),
url('../fonts/iconfont.ttf?t=1587914589125') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('../fonts/iconfont.svg?t=1587914589125#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-hidepwd:before {
content: "\e624";
}
.icon-showpwd:before {
content: "\e625";
}
.icon-search:before {
content: "\e627";
}
.icon-close:before {
content: "\e569";
}
最后运行的结果: