vue2中的简单表单和表格封装

本文介绍了如何在Vue项目中通过封装实现表单和表格的复用,包括NavForm.vue中的搜索框和CommonTable.vue中的表格组件,以及如何处理父子组件间的通信和自定义列宽管理。
摘要由CSDN通过智能技术生成

因为我有一个这样的表单,然后我很多页面都是一样的,所以我会将他封装为一套代码进行复用。

封装的代码如下:

<!-- NavForm.vue 头部搜索框的封装-->
<template>
  <el-form :inline="true" :model="searchInfo" class="demo-form-inline" @keyup.enter.native="onSubmit">
    <el-form-item
        v-for="item in searColumns"
        :key="item.model + item.label"
        :label-width="item.labelWidth"
    >
      <el-input v-if="item.type === 'input'" v-model="searchInfo[item.model]" :placeholder="item.placeholder"
                clearable></el-input>
      <el-select v-if="item.type === 'select'" v-model="searchInfo[item.model]" :placeholder="item.placeholder"
                 clearable>
        <el-option v-for="val in item.options" :key="val.value" :label="val.label" :value="val.value"></el-option>
      </el-select>

      <el-button v-if="item.type==='onSubmit'" icon="el-icon-search" type="primary" @click="onSubmit">查询
      </el-button>

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

    <el-form-item
        style="float: right"
        v-for="item in searColumns"
        :key="item.model"
        :label-width="item.labelWidth"
    >
      <el-button v-if="item.type === 'add'" icon="el-icon-plus" type="primary" @click="addSubmit">{{ item.label }}
      </el-button>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  props: {
    searColumns: {
      type: Array,
      required: true,
      default: () => []
    }
  },
  data() {
    return {
      searchInfo: {}
    };
  },
  methods: {
    onSubmit() {
      this.$emit('submit', this.searchInfo);
    },
    onReset() {
      this.searchInfo = {};
      this.$emit('reset');
    },
    addSubmit() {
      this.$emit('addSubmit',);
    },
  }
};
</script>

表单的使用:

<!--其中的searColumns搜索框的配置,submit为提交,reset为重置-->
      <NavForm
    :searColumns="searColumns"
    @submit="onSubmit"
    @reset="NoSubmit"
></NavForm>

<!--如何引入-->
import NavForm from "@/admin/components/NavForm.vue";

<!--searColumns搜索框的配置实例 其中需要输入框type为input select为下拉框-->
searColumns: [
{placeholder:'同步项ID', model: 'datasync_id',type: 'input'},
{placeholder: '状态', model: 'status',type: 'select', options: this.typeOptions}
],

<!--onSubmit需要获取子组件的数据 val用来赋值给父组件-->
onSubmit(val) {
this.page = 1;
if (this.searchInfo.datasync_id === "") {
this.searchInfo.datasync_id = null;
}
this.searchInfo = val;
this.GetSyncRecordList();
},

<!--上面的searColumns如果没有正确的拿到数据那么需要在mounted中赋值,示例:-->
mounted() {
this.searColumns = [
{placeholder:'同步项ID', model: 'datasync_id',type: 'input'},
{placeholder: '状态', model: 'status',type: 'select', options: this.typeOptions},
{type: 'onSubmit', label: '查询',},
{type: 'onReset', label: '重置',},
]
}

封装完了表单,那么我就开始封装表格了

表格的代码封装如下:

<template>
  <div>
    <el-table
        ref="multipleTable"
        :data="tableData"
        :header-cell-style="{ background: '#F5F7FA' }"
        tooltip-effect="dark"
        border
        @header-dragend="handleHeaderDragend"
        @selection-change="handleSelectionChange"
        :row-class-name="rowClassName"
    >
      <el-table-column
          type="selection"
          width="55">
      </el-table-column>
      <el-table-column
          v-for="column in columns"
          :key="column.prop"
          :prop="column.prop"
          :label="column.label"
          :width="column.width"
          :show-overflow-tooltip="column.showOverflowTooltip"
          :align="column.align"
      >
        <!-- 使用作用域插槽来自定义列的内容 -->
        <template v-slot="scope">
          <slot :name="`column-${column.prop}`" :row="scope.row">
            <!-- 这里是默认内容,当没有提供名为 `column-${column.prop}` 的插槽时显示 -->
            {{ scope.row[column.prop] }}
          </slot>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  name: 'CommonTable',
  props: {
    tableData: {
      type: Array,//类型
      required: true,//必填
      default: () => []
    },
    columns: {
      type: Array,//类型
      required: true,//必填
      default: () => []
    }
  },
  data() {
    return {
      selectedRows: [] // 添加这一行
    }
  },
  methods: {
    // 选中的行
    handleSelectionChange(selection) {
      this.selectedRows = selection; // 更新被选中的行
      // console.log(selection,'selection');
    },
    // 改变选中行的颜色
    rowClassName({ row }) {
      if (this.selectedRows.includes(row)) {
        return 'row-selected';
      }
      return '';
    },
    // 拖拽表单自定义宽度的方法
    handleHeaderDragend(newWidth, oldWidth, column, event) {
      console.log(newWidth, oldWidth, column, event, 'newWidth, oldWidth, column, event')
      // console.log(this.$route.name, '$route.name')
      const columnKey = column.property;
      const columnWidths = JSON.parse(localStorage.getItem(`${this.$route.name}-columnWidths`)) || {};
      columnWidths[columnKey] = newWidth;
      localStorage.setItem(`${this.$route.name}-columnWidths`, JSON.stringify(columnWidths));
    },
    applyColumnWidths(columns) {
      // 应用列宽度的逻辑
      const columnWidths = JSON.parse(localStorage.getItem(`${this.$route.name}-columnWidths`)) || {};
      columns.forEach((column) => {
        if (columnWidths[column.prop]) {
          column.width = columnWidths[column.prop];
        }
      });
    }
  },
  watch: {
    columns: {
      immediate: true,
      handler(newColumns) {
        this.applyColumnWidths(newColumns);
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      // 应用列宽度的逻辑// 获取自定义宽度的方法
      const columnWidths = JSON.parse(localStorage.getItem(`${this.$route.name}-columnWidths`)) || {};
      this.columns.forEach((column) => {
        if (columnWidths[column.prop]) {
          column.width = columnWidths[column.prop];
        }
      });
    });
  },
  beforeDestroy() {
    // 保存自定义宽度的方法
    const columnWidths = {};
    this.$refs.multipleTable.columns.forEach((column) => {
      if (column.width) {
        columnWidths[column.property] = column.width;
      }
    });
    localStorage.setItem(`${this.$route.name}-columnWidths`, JSON.stringify(columnWidths));
  }
}
</script>

<style lang="scss">
//表格里面的边框颜色改为透明
.el-table__body-wrapper .el-table__row .el-table__cell {
  border-left-color: transparent !important;
  border-right-color:transparent !important ;
}
//选中行的颜色
.el-table .row-selected {
  background: #F5FAFA;
}
</style>

使用方法如下:

    <CommonTable
    :tableData="tableData"
    :columns="tableColumns"
    >
<!--个性化的插槽,比如给category_id添加一个tag -->
        <template v-slot:column-category_id="{ row }">
          <el-tag>{{ row.category_id }}</el-tag>
        </template>

<!--  个性化操作栏,比如我需要一个查看修改删除的操作栏-->
         <template v-slot:column-actions="{ row }">
           <el-button type="text" @click="viewItem(row)">查看</el-button>
           <el-button type="text" @click = "deleteItem(row)" > 删除 </el-button>
           <el-button type="text" @click = "editItem(row)" > 修改 </el-button>
         </template>
    </CommonTable>

<!--如何引入-->
import CommonTable from "@/admin/components/CommonTable.vue";

<!--tableData示例:-->
tableData: [],
<!--获取参数值之后:-->
this.tableData = res.data.data即可

<!--tableColumns示例:-->
tableColumns: [
{label: '同步项ID', prop: 'datasync_id', width: 'auto', showOverflowTooltip: true},
{label: '状态', prop: 'status', width: 'auto', showOverflowTooltip: true},
{label: '失败原因', prop: 'reason', width: 'auto', showOverflowTooltip: true},
// {label: '操作', prop: 'actions', width: 'auto'}
],

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值