u-form-item.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <template>
  2. <view class="u-form-item">
  3. <view
  4. class="u-form-item__body"
  5. @tap="clickHandler"
  6. :style="[
  7. $u.addStyle(customStyle),
  8. {
  9. flexDirection:
  10. (labelPosition || parentData.labelPosition) === 'left'
  11. ? 'row'
  12. : 'column'
  13. }
  14. ]"
  15. >
  16. <!-- 微信小程序中,将一个参数设置空字符串,结果会变成字符串"true" -->
  17. <slot name="label">
  18. <!-- {{required}} -->
  19. <view
  20. class="u-form-item__body__left"
  21. v-if="required || leftIcon || label"
  22. :style="{
  23. width: $u.addUnit(labelWidth || parentData.labelWidth),
  24. marginBottom: parentData.labelPosition === 'left' ? 0 : '5px'
  25. }"
  26. >
  27. <!-- 为了块对齐 -->
  28. <view class="u-form-item__body__left__content">
  29. <!-- nvue不支持伪元素before -->
  30. <text
  31. v-if="required"
  32. class="u-form-item__body__left__content__required"
  33. >*</text
  34. >
  35. <view
  36. class="u-form-item__body__left__content__icon"
  37. v-if="leftIcon"
  38. >
  39. <u-icon :name="leftIcon" :custom-style="leftIconStyle"></u-icon>
  40. </view>
  41. <text
  42. class="u-form-item__body__left__content__label"
  43. :style="[
  44. parentData.labelStyle,
  45. {
  46. justifyContent:
  47. parentData.labelAlign === 'left'
  48. ? 'flex-start'
  49. : parentData.labelAlign === 'center'
  50. ? 'center'
  51. : 'flex-end'
  52. }
  53. ]"
  54. >{{ label }}</text
  55. >
  56. </view>
  57. </view>
  58. </slot>
  59. <view class="u-form-item__body__right">
  60. <view class="u-form-item__body__right__content">
  61. <view class="u-form-item__body__right__content__slot">
  62. <slot />
  63. </view>
  64. <view class="item__body__right__content__icon" v-if="$slots.right">
  65. <slot name="right" />
  66. </view>
  67. </view>
  68. </view>
  69. </view>
  70. <slot name="error">
  71. <text
  72. v-if="!!message && parentData.errorType === 'message'"
  73. class="u-form-item__body__right__message"
  74. :style="{
  75. marginLeft: $u.addUnit(
  76. parentData.labelPosition === 'top'
  77. ? 0
  78. : labelWidth || parentData.labelWidth
  79. )
  80. }"
  81. >{{ message }}</text
  82. >
  83. </slot>
  84. <u-line
  85. v-if="borderBottom"
  86. :color="
  87. message && parentData.errorType === 'border-bottom'
  88. ? $u.color.error
  89. : propsLine.color
  90. "
  91. :customStyle="`margin-top: ${
  92. message && parentData.errorType === 'message' ? '5px' : 0
  93. }`"
  94. ></u-line>
  95. </view>
  96. </template>
  97. <script>
  98. import props from './props.js'
  99. /**
  100. * Form 表单
  101. * @description 此组件一般用于表单场景,可以配置Input输入框,Select弹出框,进行表单验证等。
  102. * @tutorial https://www.uviewui.com/components/form.html
  103. * @property {String} label input的label提示语
  104. * @property {String} prop 绑定的值
  105. * @property {String | Boolean} borderBottom 是否显示表单域的下划线边框
  106. * @property {String | Number} labelWidth label的宽度,单位px
  107. * @property {String} rightIcon 右侧图标
  108. * @property {String} leftIcon 左侧图标
  109. * @property {String | Object} leftIconStyle 左侧图标的样式
  110. * @property {Boolean} required 是否显示左边的必填星号,只作显示用,具体校验必填的逻辑,请在rules中配置 (默认 false )
  111. *
  112. * @example <u-form-item label="姓名" prop="userInfo.name" borderBottom ref="item1"></u-form-item>
  113. */
  114. export default {
  115. name: 'u-form-item',
  116. mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
  117. data () {
  118. return {
  119. // 错误提示语
  120. message: '',
  121. parentData: {
  122. // 提示文本的位置
  123. labelPosition: 'left',
  124. // 提示文本对齐方式
  125. labelAlign: 'left',
  126. // 提示文本的样式
  127. labelStyle: {},
  128. // 提示文本的宽度
  129. labelWidth: 45,
  130. // 错误提示方式
  131. errorType: 'message'
  132. }
  133. }
  134. },
  135. // 组件创建完成时,将当前实例保存到u-form中
  136. computed: {
  137. propsLine () {
  138. return uni.$u.props.line
  139. }
  140. },
  141. mounted () {
  142. this.init()
  143. },
  144. methods: {
  145. init () {
  146. // 父组件的实例
  147. this.updateParentData()
  148. if (!this.parent) {
  149. uni.$u.error('u-form-item需要结合u-form组件使用')
  150. }
  151. },
  152. // 获取父组件的参数
  153. updateParentData () {
  154. // 此方法写在mixin中
  155. this.getParentData('u-form')
  156. },
  157. // 移除u-form-item的校验结果
  158. clearValidate () {
  159. this.message = null
  160. },
  161. // 清空当前的组件的校验结果,并重置为初始值
  162. resetField () {
  163. // 找到原始值
  164. const value = uni.$u.getProperty(this.parent.originalModel, this.prop)
  165. // 将u-form的model的prop属性链还原原始值
  166. uni.$u.setProperty(this.parent.model, this.prop, value)
  167. // 移除校验结果
  168. this.message = null
  169. },
  170. // 点击组件
  171. clickHandler () {
  172. this.$emit('click')
  173. }
  174. }
  175. }
  176. </script>
  177. <style lang="scss" scoped>
  178. @import '../../libs/css/components.scss';
  179. .u-form-item {
  180. @include flex(column);
  181. font-size: 32rpx;
  182. color: $u-main-color;
  183. &__body {
  184. @include flex;
  185. padding: 10px 0;
  186. &__left {
  187. @include flex;
  188. align-items: center;
  189. &__content {
  190. position: relative;
  191. @include flex;
  192. align-items: center;
  193. padding-right: 10rpx;
  194. flex: 1;
  195. &__icon {
  196. margin-right: 8rpx;
  197. }
  198. &__required {
  199. position: absolute;
  200. left: -9px;
  201. color: $u-error;
  202. line-height: 20px;
  203. font-size: 20px;
  204. top: 3px;
  205. }
  206. &__label {
  207. @include flex;
  208. align-items: center;
  209. flex: 1;
  210. color: $u-main-color;
  211. font-size: 15px;
  212. }
  213. }
  214. }
  215. &__right {
  216. flex: 1;
  217. &__content {
  218. @include flex;
  219. align-items: center;
  220. flex: 1;
  221. &__slot {
  222. flex: 1;
  223. /* #ifndef MP */
  224. @include flex;
  225. align-items: center;
  226. /* #endif */
  227. }
  228. &__icon {
  229. margin-left: 10rpx;
  230. color: $u-light-color;
  231. font-size: 30rpx;
  232. }
  233. }
  234. &__message {
  235. font-size: 12px;
  236. line-height: 12px;
  237. color: $u-error;
  238. }
  239. }
  240. }
  241. }
  242. </style>