学习了一年多的 vue 感觉vue还真是个强大的组件化框架.作为一个前端开发工作者,在开当中预到不少问题。也看到不少开发者写的vue代码,每个人写的代码都有些不同。很多人对组件化理解得不是很深,写的代码很多重复的代码却没抽出来,做成一个独立的组件。我先说说我遇到的情况:
很多人做表单的时候,一个页面一个组件,下面写很多原生input。比如:
像这样一个页面很多人都会直接一个路原生表单走到黑,
<form>
<label class="row-label">
<span>标题</span>
<span class="text-outdoor">
<input type="text" class="input-text />
<i class="clear-word" ></i>
<em>错误信息</em>
</span>
</label>
<label class="row-label">
<span>标题</span>
<span class="text-outdoor">
<input type="text" class="input-text />
<i class="clear-word" ></i>
<em>错误信息</em>
</span>
</label><label class="row-label">
<span>标题</span>
<span class="text-outdoor">
<input type="text" class="input-text />
<i class="clear-word" ></i>
<em>错误信息</em>
</span>
</label>
<form>
</template>
然后表单就一直加在这个页面,这样一个页面不觉得有很多重用的地方法嘛,为什么不把一个表单儿独立成一个组件呢,这样可大地减少代码理,下面是我自己把一个input 封装成一个组件的代码,我觉得一个input一个组件会给我们带来很大的方便。比如验证写验证的候可以独立验证。像表单验证这种自定义很强的插件本来是要自己写是最好的。组件化表单我方便我们写这样的插件。当然这仅能代表我的写法,没什么特别的意思大家觉得好就点赞,觉得不好当我没说。也可以给一些意见我,当作交流。
好了下面直接复制出我自己独立成组件的代码:
<label class="row-label">
<span class="row-title" v-if="toggleTitle==1" :style="{width:tw}">{{title}}</span>
<span class="text-outdoor">
<input :type="inputType" :id="id" :value="value" :disabled='isDisabled' class="input-text" :placeholder="tips" ref="input" @input="updateValue($event.target.value)" />
<i class="clear-word" @click="clear()" v-if="value&&(type!='password')&&(!isDisabled)" ></i>
<i :class="{'icon-view-pwd':(inputType=='password'),'icon-hide-pwd':(inputType!='password')}" v-if="value&&(type=='password')&&(!isDisabled)" @click="inputType!='password'?inputType='password':inputType='text' "></i>
<em class="err-msg" v-if="err!==true">{{err}}</em>
</span>
</label>
</template>
<script>
export default {
props: {
value: {
type: String, //需要绑定的值
default: ''
},
title: {
type: String
default: '标题' //表单的标题名称
},
tips: {
type: String,//表单的placeholder
default: '请输入内容'
},
type: {
type: String, //表单的类型,比如text number
default: 'text'
},
tw: {
type: String,//标题所占的宽度
default: '.1rem'
},
toggleTitle: { //就否要显示标题
type: String,
default: '0'
},
isDisabled:{ //是否禁用
default:false
},
schema:{ //验证字段的对象
default:false
},
rule:{ //验证的规则
default:false
},
},
computed: {
},
data() {
return {
inputType: this.$props.type,
newvalue:this.$props.value,
err:'',
id:'input-'+parseInt(Math.random()*1000)+'-'+parseInt(Math.random()*1000) //来个随机id好调用focus
}
},
methods: {
updateValue: function(value) {
if(this.schema){
this.err=this.schema.single(this.rule,value); //验证表单信息
}
this.$emit('update:value', value);
},
valtVal:function(){ //提交时验证
this.err=this.schema.single(this.rule,this.value);
return this.err;
},
focus:function(){
document.getElementById(this.id).focus();
},
showErr:function(err){ //显示错误的信息,这个是做异步验证的,下面会说
this.err=err;
},
clear: function() { //清理表单
this.$refs.input.value = "";
this.$emit('update:value', ""); <br/>}
}
};
</script>
验证码器代码:
export default function Validator(data,self,ref) {
this.data = data;//保存新建的规则,
this.result=""
this.self=self; 将页面的this传过来并保存
this.ref=ref; //将表单的ref索引传过来
}
Validator.prototype = {
constructor: Validator,
single: function(valname, val) { //验证单个字段 查看表单组件的valtVal()方法
let str = true;
if (this.data[valname]['tirm']) {
val = this.trim(val);
}
for (let i = 0; i < this.data[valname]['rule'].length; i++) {
let msg = this.data[valname]['msg'][i];
let rule = this.data[valname]['rule'][i];
if (typeof rule == 'string') {
if (this[rule](val)) {
str = true;
} else {
str = msg;
break;
}
} else {
if (this[rule[0]](rule, val)) {
str = true;
} else {
str = msg;
break;
}
}
}
return str;
},
all: function(data) {
return this.data[valname];
},
require: function(str) { //必须字段
if (str) {
return true;
} else {
return false;
}
},
tel: function(str) { //国内固话验证
var result = str.match(/^(\(\d{3,4}\)|\d{3,4}-)?\d{7,8}$/);
if (result == null) return false;
return true;
},
tel400: function(str) {
if (str.match(/^400\-[\d|\-]{7}[\d]{1}$/)) { //第一次匹配 400-(七个数字和-)(数字结尾)
if (str.match(/[\-]/g) == "-,-") { //第二次匹配两个 -
return true;
} else {
return false;
}
} else {
return false;
}
},
trim: function(str) { //去除前后空格
return str.replace(/(^\s*)|(\s*$)/g, '');
},
between: function(arr, val) { //区间大小
if (val.length >= arr[1] && val.length <= arr[2]) {
return true;
} else {
return false;
}
},
max:function(arr,val){
if (val.length > arr[1]) {
return false;
} else {
return true;
}
},
max:function(arr,val){
if (val.length <arr[1]) {
return false;
} else {
return true;
}
},
phone: function(str) {
var result = str.match(/^1[34578]\d{9}$/);
if (result == null) return false;
return true;
},
email: function(str) { //email
var result = str.match(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/);
if (result == null) return false;
return true;
},
getResult: function() {
return this.result;
},
strlen: function(str) { //
return str.replace(/[^\x00-\xff]/g, "**").length;
},
alltel:function (str) {
return this.tel(str)||this.tel400(str)||this.phone(str);
},
getdata:function () {
return this.self.shop
},
allvalt:function(){
let child = this.self.$refs[this.ref?this.ref:'form'].$children;
let oneerr=true;//获取第一个错误的组件 然后获取焦点
for(let i =0 ; i<child.length;i++){
if(child[i].rule){
if(child[i].valtVal()!==true&&oneerr===true){ 判断第一个没有通过验证的是哪个组件
child[i].focus();//调用组件的focus,查看input的focus方法
oneerr=false;
}
}
}
if(oneerr===true){
return true;
}else{
return false;
}
}
};
页面调用代码:
导入你的验证器代码在你的入口文件:import Schema from './validator/index.js';
Window.Schema=Schema||{};注册全局
<template>
<indoor>
<form-edit ref='form'>
<input-text toggleTitle=1 title="店铺名称:" tips="请输入店铺名称" :value.sync="shop.store_name" :schema="schema" rule="store_name" tw="1rem"></input-text>
//调用的时我们必须把数据绑定到上面
<input-text toggleTitle=1 title="联系人(可不填):" tips="请输入联系人姓名" :value.sync="shop.store_contact" tw="1rem"></input-text>
<input-text toggleTitle=1 title="电话号码:" tips="请输入联系电话" :value.sync="shop.store_phone" :schema="schema" rule="store_phone" tw="1rem"></input-text>
<input-text toggleTitle=1 title="店面地址:" ref='addr' tips="请输入地址至少要到区" :value.sync="shop.store_address" :schema="schema" rule="store_address" tw="1rem"></input-text>
<div class="sub-bar" style="padding-left: 1.3rem">
<button class="btns btn-sub" @click="send()">{{subword}}</button>
</div>
</form-edit>
</indoor>
</template>
<script>
//下面就是我写的验证器用法
let schema ={
store_name:{
tirm:false,
rule:['require',['between',3,20]],//这是用到的规则
msg:['店名是必须','店名必须在10-15个字符'] // 对应上面输入出的错误信息
},
store_phone:{
rule:['require','alltel'],
msg:['电话是必填的',"请输入正确的电话号码,固话,手机,400电话"]
},
store_address:{
rule:['require'],
msg:['地址不能为空']
}
};
export default {
components: { addbtn },
data() {
return {
btn: [{
type: 'link',
url: '/admin/shop/add',
name: '添加店铺',
class: 'btn-add-model'
}
],
shop:{
store_name:"",
store_phone:'',
store_ewm:'',
store_contact:'',
store_address:'',
latlng:''
},
forbid:true,
subword:"提交",
schema:new Schema(schema,this), //将验证码
tips:''
}
},
watch: {
'$route': function(to, from) {
if (this.$route.query.page) {
this.$refs.page.change({});
}
}
},
methods: {
async send(){
if(!this.schema.allvalt()){
return false;
}
}
};
</script>
不懂的可以看我的源代码 https://github.com/itvwork/itvwork
按提示安装依赖 然后运行项目
访问9090端口点击登录,然后点店铺管理,点击右上角的店铺添加 就可以看到源码了
验证器放在 app/validator 目录下
子组件事input放在 app/commpents/input/input-text.vue中
调用子组件和验证器的案例在:app/view/store/add.vue中
本文写到这里,有什么建议和疑问可以发我邮箱xieke76v@qq.com
这只是我自己总结出来的方法,当然大家有更好的方法也可以说,大家多交流,谢谢