Commit 21a28559 authored by wlxuqu's avatar wlxuqu

基本完成form表单组件

parent c33b937d
......@@ -2,14 +2,14 @@
"easycom": {
"^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
},
// "condition": { //模式配置,仅开发期间生效
// "current": 0, //当前激活的模式(list 的索引项)
// "list": [{
// "name": "test", //模式名称
// "path": "pages/componentsC/grid/index", //启动页面,必选
// "query": "id=1&name=2" //启动参数,在页面的-+onLoad函数里面得到
// }]
// },
"condition": { //模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项)
"list": [{
"name": "test", //模式名称
"path": "pages/componentsA/form/index", //启动页面,必选
"query": "id=1&name=2" //启动参数,在页面的onLoad函数里面得到
}]
},
"pages": [
// 演示-组件
{
......@@ -450,6 +450,13 @@
{
"root": "pages/componentsA",
"pages": [
// form-表单
{
"path": "form/index",
"style": {
"navigationBarTitleText": "form-表单"
}
},
// slider-滑动选择器
{
"path": "slider/index",
......
......@@ -21,7 +21,7 @@
:required="required"
:icon="icon2"
>
<u-button v-if="showBtn" slot="button" size="mini" type="success">发送验证码</u-button>
<u-button v-if="showBtn" slot="right" size="mini" type="success">发送验证码</u-button>
</u-field>
</u-cell-group>
</view>
......
<template>
<view class="">
<u-form :model="model" :rules="rules">
<u-form-item :label="label" prop="name">
<u-input v-model="model.name" />
</u-form-item>
</u-form>
</view>
</template>
<script>
export default {
data() {
return {
model: {
name: ''
},
rules: {
name: [
{ required: true, message: '请输入活动名称', trigger: 'change' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'change' }
]
},
label: 'name'
};
},
computed: {
current() {
return this.show ? 0 : 1;
}
},
methods: {
showChange(index) {
this.show = !index;
},
titleChange(index) {
this.showTitle = !index;
this.show = true;
},
contentChange(index) {
this.contentSlot = !index;
this.content = !index;
this.show = true;
},
asyncChange(index) {
this.show = true;
this.asyncClose = !index;
},
confirm() {
setTimeout(() => {
this.show = false;
}, 2000)
}
}
};
</script>
<style scoped lang="scss">
</style>
<template>
<view class="u-form-item">
<view>{{label}}</view>
<view class="">
<slot />
<view :class="isRequired?'ai-form-item-label-required':''" class="ai-form-item-message" v-if="validateState==='error'">{{validateMessage}}</view>
</view>
</view>
</template>
<script>
export default {
import Emitter from '../../libs/util/emitter.js';
import schema from '../../libs/util/async-validator';
export default {
name: 'u-form-item',
mixins: [Emitter],
inject: ['uForm'],
props: {
// input的label提示语
label: {
type: String,
default: ''
},
// 绑定的值
prop: {
type: String,
default: ''
}
},
data() {
return {
initialValue: '', // 存储的默认值
isRequired: false, // 是否必填
validateState: '', // 是否校验成功
validateMessage: '' // 校验失败的提示语
};
},
computed: {
fieldValue() {
return this.uForm.model[this.prop];
}
},
methods: {
// 判断是否需要required校验
setRules() {
let that = this;
// 从父组件u-form拿到当前u-form-item需要验证 的规则
let rules = this.getRules();
if (rules.length) {
this.isRequired = rules.some(rule => {
// 如果有必填项,就返回,没有的话,就是undefined
return rule.required;
});
}
// blur事件
this.$on('on-form-blur', that.onFieldBlur);
// change事件
this.$on('on-form-change', that.onFieldChange);
},
// 从u-form的rules属性中,取出当前u-form-item的校验规则
getRules() {
// 父组件的所有规则
let rules = this.uForm.rules;
rules = rules ? rules[this.prop] : [];
// 保证返回的是一个数组形式
return [].concat(rules || []);
},
// blur事件时进行表单校验
onFieldBlur() {
this.validation('blur');
},
// change事件进行表单校验
onFieldChange() {
this.validation('change');
},
// 过滤出符合要求的rule规则
getFilteredRule(trigger) {
let rules = this.getRules();
// 历遍判断规则是否有对应的事件,比如blur,change触发等的事件
return rules.filter(res => !res.trigger || trigger.indexOf(trigger) !== -1);
},
// 校验数据
validation(trigger, callback = () => {}) {
// blur和change是否有当前方式的校验规则
let rules = this.getFilteredRule(trigger);
// 判断是否有验证规则
if (!rules || rules.length === 0) return;
// 设置当前的装填,标识为校验中
this.validateState = 'validating';
// 调用async-validator的方法
let validator = new schema({ [this.prop]: rules });
validator.validate({ [this.prop]: this.fieldValue }, { firstFields: true }, (errors, fields) => {
// 记录状态和报错信息
this.validateState = !errors ? 'success' : 'error';
this.validateMessage = errors ? errors[0].message : '';
// 调用回调方法
callback(this.validateMessage);
});
},
// 清空当前的u-form-item
resetField() {
this.uForm.model[this.prop] = this.initialValue;
}
},
// 组件创建完成时,将当前实例保存到u-form中
mounted() {
// 如果没有传入prop,就不进行校验
if (!this.prop) return;
// 发出事件,让父组件将本实例加入到管理数组中
this.dispatch('u-form', 'on-form-item-add', this);
// 设置初始值
this.initialValue = this.fieldValue;
// 添加表单校验
this.setRules();
},
// 组件销毁前,将实例从 Form 的缓存中移除
beforeDestroy() {
this.dispatch('u-form', 'on-form-item-remove', this);
}
};
</script>
<style>
</style>
<style></style>
......@@ -10,14 +10,14 @@ export default {
model: {
type: Object,
default() {
return {}
return {};
}
},
// 验证规则
rules: {
type: Object,
default() {
return {}
return {};
}
}
},
......@@ -28,28 +28,58 @@ export default {
},
data() {
return {
// 存储当前form下的所有u-form的示例
fields: []
};
},
created() {
// 存储当前form下的所有u-form-item的实例
// 不能定义在data中,否则微信小程序会造成循环引用而报错
this.fields = [];
// 存当前实例
let that =this;
let that = this;
// 监听on-form-item-add事件,将子组件添加到fields中
this.$on('on-form-item-add',item=>{
this.$on('on-form-item-add', item => {
if (item) {
that.fields.push(item);
}
});
// 删除当前有的实例
this.$on('on-form-item-remove',item=>{
this.$on('on-form-item-remove', item => {
// 如果当前没有prop的话表示当前不要进行删除(因为没有注入)
if (item.prop) {
that.fields.splice(that.fields.indexOf(item), 1);
}
});
},
methods: {
// 清空所有u-form-item组件的内容,本质上是调用了u-form-item组件中的resetField()方法
resetFields() {
this.fields.map(field => {
field.resetField();
})
},
methods: {}
// 校验全部数据
validate(callback) {
return new Promise(resolve => {
// 对所有的u-form-item进行校验
let valid = true; // 默认通过
let count = 0; // 用于标记是否检查完毕
this.fields.map(field => {
// 调用每一个u-form-item实例的validation的校验方法
field.validation('', error => {
// 如果任意一个u-form-item校验不通过,就意味着整个表单不通过
if(error) valid = false;
// 当历遍了所有的u-form-item时,调用promise的then方法
if(++count === this.fields.length) {
resolve(valid); // 进入promise的then方法
// 调用回调方法
if(typeof callback == 'function') callback(valid);
}
})
})
})
}
}
};
</script>
......
<template>
<view class="u-icon" :class="[labelPos == 'bottom' ? 'u-flex-col u-row-center' : 'u-flex u-col-center']">
<text class="u-icon__icon" :class="customClass" :style="[iconStyle]" @tap.stop="click" :hover-class="hoverClass" @touchstart.stop="touchstart"></text>
<text class="u-icon__icon" :class="customClass" :style="[iconStyle]" @tap.stop.prevent="click" :hover-class="hoverClass" @touchstart.stop.prevent="touchstart"></text>
<text v-if="label" class="u-icon__label" :style="{
color: labelColor,
fontSize: labelSize + 'rpx',
......
<template>
<input type="text" @input="handleInput" @blur="handleBlur" :value="defaultValue" />
</template>
<script>
import Emitter from '../../libs/util/emitter.js';
export default {
name: 'u-input',
mixins: [Emitter],
props: {
value: {
type: String,
default: '1234'
}
},
data() {
return {
defaultValue: this.value
};
},
watch: {
value(val) {
this.defaultValue = val;
}
},
methods: {
/**
* change 事件
* @param event
*/
handleInput(event) {
// 当前model 赋值
this.defaultValue = event.detail.value;
// vue 原生的方法 return 出去
this.$emit('input', event.detail.value);
// 过一个生命周期再发送事件给u-form-item,否则this.$emit('input')更新了父组件的值,但是微信小程序上
// 尚未更新到u-form-item,导致获取的值为空,从而校验混论
this.$nextTick(() => {
// 将当前的值发送到 u-form-item 进行校验
this.dispatch('u-form-item', 'on-form-change', event.detail.value);
})
},
/**
* blur 事件
* @param event
*/
handleBlur(event) {
// vue 原生的方法 return 出去
this.$emit('blur', event.detail.value);
this.$nextTick(() => {
// 将当前的值发送到 u-form-item 进行校验
this.dispatch('u-form-item', 'on-form-blur', event.detail.value);
})
}
}
};
</script>
......@@ -203,8 +203,8 @@
.u-input {
position: absolute;
top: 0;
left: 0;
width: 100%;
left: -100%;
width: 200%;
height: 100%;
text-align: left;
z-index: 9;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment