封装一个日期组件,提交数据为字符串——dateStingPicker

  • A+
所属分类:Web前端
摘要

需求:在这里用到几个属性,在提交数据的时候需要提交给表单的数据我们通过lastValue传递;如果不需要格式转换可以直接使用this.momVal = value这样传递的数据类型还是moment对象。


dateStingPicker组件封装

需求:

  1. 页面中使用日期选择框,输入框中回显日期格式“XXXX年XX月XX日”
  2. 提交数据时将日期格式转换为字符串,如:“20210314”
  3. 查看时,回显数据日期格式同样为“XXXX年XX月XX日”

演示实例

封装一个日期组件,提交数据为字符串——dateStingPicker

序——使用软件及框架版本

  1. vue 2.6.11
  2. ant-design-vue 1.7.1
  3. moment.js(日期转换依赖)

设计思路

  1. 根据需求,可以知道需要回显格式需要为“XXXX年XX月XX日”,查看组件库a-date-picker,了解到format属性可以将在输入框中数据转换为特定格式。
  2. 在提交数据时,由于我们是封装组件,给其他页面中使用,所以需要将需要提交的值由子组件置到父组件上,所以在日期组件中选中日期出发的事件change/input,在选中日期的时候需要使用到$emit,将值置到上层副组件。
  3. 在回显数据时,查看页面数据的时候,表单上显示数据,此时从后台数据中拿到的是字符串“20210314”,同时需要将数据格式化为“XXXX年XX月XX日”,显示在输入框中。

具体代码过程

1. template模板区域

<template>   <div>     <!--  这里momVal是momentValue的缩写,因为value的真实值是moment对象  -->     <a-date-picker       :value="momVal"       :allowClear="allowClear"       :disabled="disabled"       :format="dateFormat"       :mode="mode"       :placeholder="placeholder"       @change="dateChanged"     >     </a-date-picker>   </div> </template> 

在这里用到几个属性,

  1. 由于是封装组件,所以使用value实现数据的双向绑定,在表单中使用allClear的时候在点击清除按钮时也可以清除表单显示和底层数据。
  2. mode是输入框显示模式,date、month、year可选,但是year模式时不太好用,具体可以参考下一篇,year年份组件封装。
  3. 当然组件上不止有@change事件,@blur@select都是可以使用的,可以根据项目需求来具体使用,不过在父组件上使用事件时,需要在子组件props 中声明,并在模板部分使用双向绑定:select="select"

2. js区域

<script> import moment from 'moment'  export default {   name: 'dateStringPicker',   props: {     value: {       type: [String, Number],       default: ''     },     // 返回的日期格式     dateFormat: {       type: String,       default: 'YYYY年MM月DD日'     },     // 类型,选择年份请传入"year",选择年月请传入"month"     mode: {       type: String,       default: 'date'     },     placeholder: {       type: String,       default: '请选择日期'     },     disabled: {       type: Boolean,       default: false     },     allowClear: {       type: Boolean,       default: true     },     // 判断输入的两种状态input/change     triggerChange: {       type: Boolean,       default: true     }   },   data () {     const dateStr = this.value     return {       // 由于vue是数据驱动页面加载的,所以在data中需要给value一个初始值       momVal: !dateStr ? null : moment(dateStr, this.dateFormat),       lastValue: ''     }   },   watch: {     // 此处的监听,用来实现设计思路3     value (val) {       if (!val) {         this.momVal = null       } else {         this.momVal = moment(val, 'YYYYMMDD')       }     }   },   methods: {     moment,     // 此处change事件,用来实现设计思路2,此处有注意事项,当时写的时候还是遇到一些问题的     dateChanged (mom) {       // 参考注意事项3       if (!mom) {         if (this.triggerChange) {           this.$emit('change', null)         } else {           this.$emit('input', null)         }       } else {         // 参考注意事项1         this.lastValue = moment(mom).format('YYYYMMDD')         // 参考注意事项2         if (this.triggerChange) {           this.$emit('change', this.lastValue         } else {           this.$emit('input', this.lastValue)         }       }     }   } } </script> 

注意事项:

  1. 在提交数据的时候需要提交给表单的数据我们通过lastValue传递;如果不需要格式转换可以直接使用this.momVal = value这样传递的数据类型还是moment对象。

  2. 生造一个triggerChange属性的原因是,在ant-design-vue组件中,使用a-form表单组件的时候,分了两种情况

    • 提交数据时不需要校验规则,使用v-model绑定数据
    • 提交数据时需要校验规则,使用v-decorator

    在使用v-model时,点击日期触发的事件时input,而在使用v-decorator时,点击日期触发的事件时change

  3. 为什么要在提交数据的change 事件中,添加一个!mom的条件判断,原因是:在表单上添加allClear属性之后,表单中会出现可以清除当前输入框数据的符号“❌”,在清除表单数据的时候,表单上回显示no valid或者NaN,原因可能是清除之后表单的初始值数据类型不对,这点我也不是太清楚。总之,解决方法就是添加一个!mom的条件判断,在清除表单数据的时候重新给表单value赋一个空值null,因为value的类型是对象,所以不能是""

测试demo实例

<template>   <div>     <div class="box">       <h1>this is dateStringPiker</h1>       <div class="btn">         <a-button type="primary" @click="click"> 提交数据</a-button>       </div>       <a-form :form="editForm" layout="inline">         <!--  使用v-model时,是以input事件从子组件抛出value值  -->         <a-form-item label="v-model形式的绑定的 日期">           <date-string-picker             v-model="editForm.date"             :trigger-change="false">           </date-string-picker>         </a-form-item>          <!-- 在需要校验的情况下,在表单中使用v-decorator的形式绑定,         同时自组件要以change的形式将value抛出到上层副组件 -->         <!--        <a-form-item label="v-decorator形式绑定的 日期">-->         <!--          <date-string-picker-->         <!--            v-decorator="['date',{initialValue:''}]"-->         <!--            :trigger-change="true">-->         <!--          </date-string-picker>-->         <!--        </a-form-item>-->       </a-form>     </div>   </div> </template>  <script> import dateStringPicker from '@/component/dateStringPicker'  export default {   name: 'demo',   components: {     dateStringPicker   },   data() {     return {       // 使用v-decorator要使用下面方法注册form表单       // editForm: this.$form.createForm(this)        // v-model的形式,form表单注册则比较简单       editForm: {         date: ''       }     }   },   methods: {     click() {       console.log('点击按钮')       // v-model绑定测试提交       // console.log(this.editForm)        // v-decorator绑定,测试数据提交       this.editForm.validateFields((err, value) => {         console.log(err)         console.log(value)       })     }   } } </script>  <style scoped lang="less"> .box {   margin: 30px 30px; }  .btn {   margin: 30px 30px; } </style>  

Find me

Gitee:https://gitee.com/heyhaiyon/ant-vue-admin.git

微信