Vue 学习随笔系列四 -- form 表单封装

Vue 学习随笔系列四 – form 表单封装

文章目录

  • Vue 学习随笔系列四 -- form 表单封装
  • 一、form 表单封装方法(1)
    • 1、组件封装
    • 2、组件使用
  • 二、form 表单封装方法(2)
    • 1、form 表单组件封装
    • 2、表单组件引用
  • 三、form 表单封装方法(3)
      • 1、组件封装
      • 2、组件引用


一、form 表单封装方法(1)

1、组件封装

<template>
  <el-form
    ref="form"
    :model="form"
    :label-width="80"
    :label-colon="true"
    label-position="left"
  >
    <el-row >
      <el-col :span="8">
        <el-form-item label="姓名">
          <el-input v-model="form.name" clearable></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="8">
        <el-form-item label="年龄">
          <el-input v-model="form.age" clearable></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="8">
        <div class="button-box">
          <el-button class="search" type="primary" @click="handleQuery"
            >筛 选</el-button
          >
        </div>
      </el-col>
    </el-row>
  </el-form>
</template>

<script>
export default {
  data () {
    return {
      form: {
        name: '', // 查询条件1 
        age: '' //  查询条件2
      }
    }
  },
  methods: {
    handleQuery () {
      this.$emit('handleQuery', this.form)
    }
  },
  mounted () {
    // this.handleQuery()
  }
}
</script>

<style scoped>
.button-box {
  white-space: nowrap;
}
.search {
  background-color: #0049CA;
  color: #FFFFFF;
}
</style>

2、组件使用

<template>
	<div>
		<SearchPanel class="mb25" @handleQuery="handleQuery"></SearchPanel>
	</div>
</template>

<script>
	import SearchPanel from './SearchPanel.vue'

	export default {
	  components: {  SearchPanel,  },
	  data(){
	  	return{
  		  total: 0, // 总条数
	      pageNum: 1,
	      pageSize: 10,
	      pageSizes: [10, 20, 50, 100],
	      searchParams: {},
	  	}
	  },
	  methods: {
	  	hadleQuery(){
	  		this.searchParams = { ...params, pageNum: this.pageNum, pageSize: this.pageSize }
	  	}
	  }
  }
</script>

二、form 表单封装方法(2)

1、form 表单组件封装

此案例包含 input 输入框, select 选择框 等,根据实际需求使用

<template>
  <div class="form">
      <el-form
          ref="form"
          :model="formData"
          :inline="inline"
          :label-width="labelWidth"
          :label-position="labelPosition"
      >
          <el-form-item
              v-for="item in formConfig"
              :key="item.model"
              :label="item.label"
              :label-width="item.labelWidth"
          >
              <el-input
                  v-if="item.type === 'input'"
                  v-model="formData[item.model]"
                  :type="item.inputType ? item.inputType : 'text'"
                  clearable
              />

              <el-date-picker
                  v-if="item.type === 'daterange'"
                  v-model="formData[item.model]"
                  type="daterange"
                  value-format="yyyy-MM-dd"
                  start-placeholder="开始日期"
                  end-placeholder="结束日期"
                  :style="`
                      width: ${item.width ? item.width : 300}px
                  `"
                  @onChange="setDateRange(formData[item.model], item.model)"
              />

              <el-select
                  v-if="item.type === 'select'"
                  v-model="formData[item.model]"
                  clearable
                  placeholder="请选择"
                  :multiple="item.multiple"
                  :filterable="item.filterable"
                  :max-tag-count="item.max_tag_count"
                  style="width:100%;"
              >
                  <el-option
                      v-for="data in item.list"
                      :key="getSelectKeys(data, 'key')"
                      :value="getSelectKeys(data, 'key')"
                  >
                      {{ getSelectKeys(data, "value") }}
                  </el-option>
              </el-select>

              <slot name="item" />

              <el-button
                v-if="item.type === 'confirm'"
                type="primary"
                :loading="item.isSearching"
                @click="query"
              >
                查询
              </el-button>

              <el-button
                v-if="item.type === 'add'"
                type="primary"
                @click="addItem"
              >
                新增
              </el-button>

              <el-button
                v-if="item.type === 'mod'"
                type="primary"
                @click="modItem"
              >
                修改
              </el-button>

              <el-button
                v-if="item.type === 'delete'"
                type="primary"
                @click="deleteItem"
              >
                删除
              </el-button>

              <el-button
                v-if="item.type === 'upload'"
                type="primary"
                @click="upload"
              >
                上传
              </el-button>

              <el-button
                v-if="item.type === 'download'"
                type="primary"
                @click="download"
              >
                下载
              </el-button>

              <el-button
                v-if="item.type === 'reset'"
                type="primary"
                @click="reset"
              >
                重置
              </el-button>

              <slot name="button" />
          </el-form-item>

          <slot name="form" />
      </el-form>
  </div>
</template>

<script>
export default {
  name: 'CommonForm',
  props: {
      // 表单项是否行内显示
      inline: {
          type: Boolean,
          default: true,
      },
      // 表单项配置
      formConfig: {
          type: Array,
          default: () => []
      },
      // 表单项数据
      form: {
          type: Object,
          default: () => {}
      },
      // 表单标签宽度
      labelWidth: {
          type: String,
          default: '100',
      },
      // 表单标签位置,默认左侧
      labelPosition: {
          type: String,
          default: 'left',
      },
  },
  data() {
      return {
          formData: this.form,
          selectKeys: []
      };
  },
  mounted() {
      // 初始化设置formdata项的开始时间和结束时间
      this.formConfig
          .filter(item => item.type === 'daterange')
          .map(item => {
              this.setDateRange(this.formData[item.model], item.model);
          });
  },
  methods: {
      getSelectKeys(obj, type) {
          const key = Object.keys(obj);
          return type === 'key' ? obj[key[0]] : obj[key[1]];
      },
      // 选取日期后赋给 form 对应属性名
      setDateRange(date, model) {
        console.log("date", date)
          this.formData[`${model}_start`] = date[0];
          this.formData[`${model}_stop`] = date[1];
      },
      // 查询
      query() {
        this.$emit('query');
      },
      // 编辑
      modItem() {
        this.$emit('modItem')
      },
      addItem(){
        this.$emit('addItem')
      },
      // 删除
      deleteItem() {
        this.$emit('deleteItem');
      }, 
      upload() {
        this.$emit('upload')
      },
      download() {
        this.$emit('download')
      },
      // 重置表单
      reset() {
        this.$refs.form.resetFields();
      },
      // 获取表单参数
      getForm() {
        console.log("formData", this.formData)
        return this.formData
      }
  },
};
</script>

2、表单组件引用

<template>
  <div class="index">
    <QueryForm
      ref="queryForm"
      :form="form"
      :form-config="formConfig"
      @query="query"
      @refresh="refresh"
      @addItem="addItem"
      @modItem="modItem"
      @deleteItem="deleteItem"
      @upload="upload"
      @download="download"
    >
    </QueryForm>
  </div>
</template>

<script>
import QueryForm  from "./QueryForm.vue"

export default {
  name: 'HelloWorld',
  components: {
    QueryForm
  },
  props: {
    // msg: String
  },
  data(){
    return{
      isSearching: false, // 是否查询种
      form: {
        id: '',
        status: '',
        time: '',
        pageSize: 10,
        pageNum: 1,
      },
      formConfig: [
        {model:'id', label: "ID", type: 'input', placeholder: "请输入"},
        {
          model: 'status', 
          label: "状态", 
          type: 'select', 
          list:[
            {
              key: "1",
              value: "选项1"
            },
            {
              key: "2",
              value: "选项2"
            }
          ],
          placeholder: "请选择"
        },
        {model: 'time', label: "日期", type: 'daterange', placeholder: "请选择"},
        {
          model: "confirm", // 确认按钮
          text: "查询",
          type: 'confirm',
          label: '',
          isSearching: this.isSearching
        },
        {
          model: "add", // 确认按钮
          text: "新增",
          type: 'add',
          label: '',         
        },
        {
          model: "mod", // 确认按钮
          text: "修改",
          type: 'mod',
          label: '',         
        },
        {
          model: "delete", // 确认按钮
          text: "删除",
          type: 'delete',
          label: '',         
        },
        {
          model: "upload", // 确认按钮
          text: "上传",
          type: 'upload',
          label: '',         
        },
        {
          model: "download", // 确认按钮
          text: "下载",
          type: 'download',
          label: '',         
        },
      ],
    }
  },
  methods: {
    query(){
      const formParams = this.$refs.queryForm.getForm() || {}
      console.log("query", formParams)
    },
    // 查询
    refresh(){
      console.log("refresh")
    },
    // 新增
    addItem(){
      console.log("addItem")
      this.$refs.addForm.handleOpen({
        title: '新增'
      })
    },
    // 修改
    modItem() {
      console.log("modItem")
    },
    // 删除
    deleteItem() {
      console.log("deleteItem")
    },
    // 上传
    upload() {
      console.log("upload")
      this.$refs.uploadBox.handleOpen()
    },
    // 下载
    download() {
      console.log("download")
    },
  }
}
</script>

实现效果:
在这里插入图片描述

三、form 表单封装方法(3)

1、组件封装

<template>
  <el-form
    ref="form"
    :model="formData"
    size="small"
    label-width="100px"
    class="form-box"
  >
    <el-row>
      <el-col 
        v-for=" item in formConfig.itemList"
        :span="8">
        
        <el-form-item        
          :key = "item.model"
          :label="item.label"
        >
          <el-input
            v-if="item.type === 'input'"
            v-model="formData[item.model]"
            :type="item.inputType ? item.inputType : 'text'"
            :placeholder="item.placeholder"
            :disabled="item.disabled"
            clearable
          >
          </el-input>

          <el-select
            v-if="item.type === 'select'"
            v-model="formData[item.model]"
            :type="item.inputType ? item.inputType : 'text'"
            :placeholder="item.placeholder"
            :disabled="item.disabled"
            :multiple="item.multiple"
            :filterable="item.filterable"
            clearable
          >
            <el-option
              v-for="data in item.list"
              :key="getSelectKeys(data, 'key')"
              :label="getSelectKeys(data, 'label')"
              :value="getSelectKeys(data, 'key')"
            >
            {{ getSelectKeys(data, "value") }}
            </el-option>
          </el-select>

          <el-cascader
            v-if="item.type === 'cascader'"
            v-model="formData[item.model]"
            :options="item.formOptions"
            :multiple="item.multiple"
            :filterable="item.filterable"
            :placeholder="item.placeholder"
            @change="handleChange"
          ></el-cascader>

          <el-date-picker
            v-if="item.type === 'daterange'"
            v-model="formData[item.model]"
            :type="daterange"
            format="yyyy-MM-dd"
            @onChange="datechange"
          ></el-date-picker>

        </el-form-item>
      </el-col>  

      <el-col :span="24">
            type="warning"
            @click="emitEvent({eventName: 'addorModItem', params: 'mod'})"
          >
            <i class="el-icon-edit"></i>
            修改 
          </el-button>

          <el-button
            size="small"
            type="danger"
            @click="emitEvent({eventName: 'deleteItem', params: ''})"
          >
            <i class="el-icon-delete"></i>
            删除 
          </el-button>
        </el-form-item>

        <el-form-item>
          <el-button
            v-for="(item, index) in formConfig.operate"
            :key="index"
            size="small"
            :type="item.type"
            :icon="item.icon"
            @click="emitEvent({eventName: item.handleClick, params: ''})"
          >{{ item.name }}</el-button>
        </el-form-item>
      </el-col>

    </el-row>
  </el-form>
</template>

<script>
export default {
name: 'QueryForm',
// props: ['busItemList'],
props: {
  // 表单项是否行内显示
  inline: {
    type: Boolean,
    default: true
  },
  // 表单项配置
  formConfig: {
    type: Array,
    default: () => []
  },
  // 表单项数据
  form: {
    type: Object,
    default: () => { }
  },
},
computed: {
},
data () {
  return {
    formData: this.form,
  }
},
mounted() {
  // 
},
methods: {
  // 下拉框
  getSelectKeys(obj, type) {
    const key = Object.keys(obj);

    // console.log("obj==", obj)
    // console.log('type==', obj[key[1]])

    return type === 'key' ? obj[key[0]] : obj[key[1]];
  },
  // 重置
  reset () {
    this.$refs.form.resetFields()
    // this.formData = {}
    Object.keys(this.formData).forEach(key=>{this.formData[key]=''})
  },
  // 获取form数据
  getFormParams () {
    console.log("formData==", this.formData)
    return this.formData
  },
  // 触发查询
  emitEvent ({eventName, params}) {
    this.$emit(eventName, params)
  },
  handleChange(val){
    console.log("val==", val)
  }
  
}
}
</script>
<style lang='scss' scoped>
  .form-box {
    // margin-bottom: 10px;
    :deep .el-form-item__label {
      font-size: 14px;
    }
    :deep .el-input__inner {
      font-size: 14px;
    }
  }
  .el-button {
    font-size: 14px;
  }
  .export {
    background-color: #0049CA;
    color: #FFFFFF;
    float: right;
    margin-right: 5%;
  }
  .el-buttom :active {
    background-color: #0049CA;
    color: #FFFFFF;
  }
</style>

2、组件引用

<template>
  <div class="index">
    <QueryForm
      ref="queryForm"
      :form="form"
      :form-config="formConfig"
      @query="query"
    >
    </QueryForm>
  </div>
</template>

<script>
import QueryForm  from "../component/QueryForm.vue"

export default {
  name: 'HelloWorld',
  components: {
    QueryForm
  },
  props: {
    // msg: String
  },
  data(){
    return{
      isSearching: false, // 是否查询中
      form: {
        id: '',
        status: '',
        time: '',
        pageSize: 10,
        pageNum: 1,
      },
      formConfig:{
        itemList: [
          {model:'id', label: "ID", type: 'input', placeholder: "请选择请选择", formOptions: this.options},
        ],
        operate: [
          {type: "success", name: "查询", handleClick: "query"}
        ]
      },
    }
  },
  methods: {
    query(){
      // const formParams = this.$refs.queryForm.getForm() || {}
      console.log("query")
    },
    // 查询
    refresh(){
      console.log("refresh")
    },
  }
}
</script>


你可能感兴趣的:(vue.js,学习,javascript)