246 lines
6.1 KiB
Vue
246 lines
6.1 KiB
Vue
<template>
|
||
<view class="u-form-item">
|
||
<view
|
||
class="u-form-item__body"
|
||
@tap="clickHandler"
|
||
:style="[addStyle(customStyle), {
|
||
flexDirection: (labelPosition || parentData.labelPosition) === 'left' ? 'row' : 'column'
|
||
}]"
|
||
>
|
||
<!-- 微信小程序中,将一个参数设置空字符串,结果会变成字符串"true" -->
|
||
<slot name="label">
|
||
<!-- {{required}} -->
|
||
<view
|
||
class="u-form-item__body__left"
|
||
v-if="required || leftIcon || label"
|
||
:style="{
|
||
width: addUnit(labelWidth || parentData.labelWidth),
|
||
marginBottom: parentData.labelPosition === 'left' ? 0 : '5px',
|
||
}"
|
||
>
|
||
<!-- 为了块对齐 -->
|
||
<view class="u-form-item__body__left__content">
|
||
<!-- nvue不支持伪元素before -->
|
||
<text
|
||
v-if="required"
|
||
class="u-form-item__body__left__content__required"
|
||
>*</text>
|
||
<view
|
||
class="u-form-item__body__left__content__icon"
|
||
v-if="leftIcon"
|
||
>
|
||
<u-icon
|
||
:name="leftIcon"
|
||
:custom-style="leftIconStyle"
|
||
></u-icon>
|
||
</view>
|
||
<text
|
||
class="u-form-item__body__left__content__label"
|
||
:style="[parentData.labelStyle, {
|
||
justifyContent: parentData.labelAlign === 'left' ? 'flex-start' : parentData.labelAlign === 'center' ? 'center' : 'flex-end'
|
||
}]"
|
||
>{{ label }}</text>
|
||
</view>
|
||
</view>
|
||
</slot>
|
||
<view class="u-form-item__body__right">
|
||
<view class="u-form-item__body__right__content">
|
||
<view class="u-form-item__body__right__content__slot">
|
||
<slot />
|
||
</view>
|
||
<view
|
||
class="item__body__right__content__icon"
|
||
v-if="$slots.right"
|
||
>
|
||
<slot name="right" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<slot name="error">
|
||
<text
|
||
v-if="!!message && parentData.errorType === 'message'"
|
||
class="u-form-item__body__right__message"
|
||
:style="{
|
||
marginLeft: addUnit(parentData.labelPosition === 'top' ? 0 : (labelWidth || parentData.labelWidth))
|
||
}"
|
||
>{{ message }}</text>
|
||
</slot>
|
||
<u-line
|
||
v-if="borderBottom"
|
||
:color="message && parentData.errorType === 'border-bottom' ? color.error : propsLine.color"
|
||
:customStyle="`margin-top: ${message && parentData.errorType === 'message' ? '5px' : 0}`"
|
||
></u-line>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import props from './props';
|
||
import mpMixin from '../../libs/mixin/mpMixin';
|
||
import mixin from '../../libs/mixin/mixin';
|
||
import defProps from '../../libs/config/props.js';
|
||
import color from '../../libs/config/color';
|
||
import { addStyle, addUnit, getProperty, setProperty, error } from '../../libs/function/index';
|
||
/**
|
||
* Form 表单
|
||
* @description 此组件一般用于表单场景,可以配置Input输入框,Select弹出框,进行表单验证等。
|
||
* @tutorial https://ijry.github.io/uview-plus/components/form.html
|
||
* @property {String} label input的label提示语
|
||
* @property {String} prop 绑定的值
|
||
* @property {String} rule 绑定的规则
|
||
* @property {String | Boolean} borderBottom 是否显示表单域的下划线边框
|
||
* @property {String | Number} labelWidth label的宽度,单位px
|
||
* @property {String} rightIcon 右侧图标
|
||
* @property {String} leftIcon 左侧图标
|
||
* @property {String | Object} leftIconStyle 左侧图标的样式
|
||
* @property {Boolean} required 是否显示左边的必填星号,只作显示用,具体校验必填的逻辑,请在rules中配置 (默认 false )
|
||
*
|
||
* @example <u-form-item label="姓名" prop="userInfo.name" borderBottom ref="item1"></u-form-item>
|
||
*/
|
||
export default {
|
||
name: 'u-form-item',
|
||
mixins: [mpMixin, mixin, props],
|
||
data() {
|
||
return {
|
||
// 错误提示语
|
||
message: '',
|
||
parentData: {
|
||
// 提示文本的位置
|
||
labelPosition: 'left',
|
||
// 提示文本对齐方式
|
||
labelAlign: 'left',
|
||
// 提示文本的样式
|
||
labelStyle: {},
|
||
// 提示文本的宽度
|
||
labelWidth: 45,
|
||
// 错误提示方式
|
||
errorType: 'message'
|
||
}
|
||
}
|
||
},
|
||
// 组件创建完成时,将当前实例保存到u-form中
|
||
computed: {
|
||
propsLine() {
|
||
return defProps.line
|
||
}
|
||
},
|
||
mounted() {
|
||
this.init()
|
||
},
|
||
emits: ["click"],
|
||
methods: {
|
||
addStyle,
|
||
addUnit,
|
||
color,
|
||
init() {
|
||
// 父组件的实例
|
||
this.updateParentData()
|
||
if (!this.parent) {
|
||
error('u-form-item需要结合u-form组件使用')
|
||
}
|
||
},
|
||
// 获取父组件的参数
|
||
updateParentData() {
|
||
// 此方法写在mixin中
|
||
this.getParentData('u-form');
|
||
},
|
||
// 移除u-form-item的校验结果
|
||
clearValidate() {
|
||
this.message = null
|
||
},
|
||
// 清空当前的组件的校验结果,并重置为初始值
|
||
resetField() {
|
||
// 找到原始值
|
||
const value = getProperty(this.parent.originalModel, this.prop)
|
||
// 将u-form的model的prop属性链还原原始值
|
||
setProperty(this.parent.model, this.prop, value)
|
||
// 移除校验结果
|
||
this.message = null
|
||
},
|
||
// 点击组件
|
||
clickHandler() {
|
||
this.$emit('click')
|
||
}
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
@import "../../libs/css/components.scss";
|
||
|
||
.u-form-item {
|
||
@include flex(column);
|
||
font-size: 14px;
|
||
color: $u-main-color;
|
||
|
||
&__body {
|
||
@include flex;
|
||
padding: 10px 0;
|
||
|
||
&__left {
|
||
@include flex;
|
||
align-items: center;
|
||
|
||
&__content {
|
||
position: relative;
|
||
@include flex;
|
||
align-items: center;
|
||
padding-right: 10rpx;
|
||
flex: 1;
|
||
|
||
&__icon {
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
&__required {
|
||
position: absolute;
|
||
left: -9px;
|
||
color: $u-error;
|
||
line-height: 20px;
|
||
font-size: 20px;
|
||
top: 3px;
|
||
}
|
||
|
||
&__label {
|
||
@include flex;
|
||
align-items: center;
|
||
flex: 1;
|
||
color: $u-main-color;
|
||
font-size: 15px;
|
||
}
|
||
}
|
||
}
|
||
|
||
&__right {
|
||
flex: 1;
|
||
|
||
&__content {
|
||
@include flex;
|
||
align-items: center;
|
||
flex: 1;
|
||
|
||
&__slot {
|
||
flex: 1;
|
||
/* #ifndef MP */
|
||
@include flex;
|
||
align-items: center;
|
||
/* #endif */
|
||
}
|
||
|
||
&__icon {
|
||
margin-left: 10rpx;
|
||
color: $u-light-color;
|
||
font-size: 30rpx;
|
||
}
|
||
}
|
||
|
||
&__message {
|
||
font-size: 12px;
|
||
line-height: 12px;
|
||
color: $u-error;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|