¡Edición en línea de formularios Ant Design Vue!

Imagen de efecto

No hay imagen, directamente en la imagen:
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Escenarios de aplicación

Para la modificación de los datos de la tabla, lo más común es modificar el formulario en el cuadro modal. Es relativamente sencillo comenzar y la función de verificación es muy poderosa. Si edita en la fila de la tabla, es un poco más complicado comenzar. Modificar directamente en la columna será muy intuitivo y sencillo. Sin embargo, hay ciertos defectos. El formulario no se puede incrustar y la verificación no es amigable.

.Vista

<template>
  <div>
    <div class="page-location-wrapper">
      <bread-nav :nav-list="['数据模版', '数据模版DEMO']"/>
      <h1>数据模版DEMO</h1>
    </div>
    <div class="public-container">
      <div class="public-operation-bar">
        <div class="button-wrapper">
          <a-button icon="plus-circle" type="primary"
                    @click="addRow">新增
          </a-button>
          <a-button type="primary">批量发布</a-button>
        </div>
      </div>
      <a-divider/>
      <div class="table-wrapper">
        <!--每个列的宽度必须比列名总长度大才能使表格所有列对齐,留一个列不设置宽度-->
        <a-table
          :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange, onSelectAll: onSelectAllChange}"
          :columns="columns"
          :dataSource="tableData"
          bordered
          size="middle"
          :pagination="pagination"
          :loading="tableLoading"
          :scroll="{x: 2050}"
        >
          <template
            v-for="col in customRenderList"
            v-slot:[col]="text, record, index"
          >
            <div :key="col">
              <a-input
                :read-only="readonlyArr.includes(col)"
                placeholder="请输入"
                v-if="record.editable && inputScopedSlots.includes(col)"
                :value="text"
                @change="e => handleChange(e.target.value, record.key, col)"
              />
              <a-date-picker
                placeholder="请选择时间"
                v-else-if="record.editable && dateScopedSlots.includes(col)"
                :value="momentDateStr(text)"
                @change="onChangeDate($event, record.key, col)"
              />
              <a-select
                placeholder="请选择"
                style="display: block;"
                v-else-if="record.editable && selectScopedSlots.includes(col)"
                :value="text"
                @change="onChangeSelect($event, record.key, col)"
              >
                <a-select-option value="lucy">Lucy</a-select-option>
                <a-select-option value="jack">Jack</a-select-option>
              </a-select>
              <span v-else>{
    
    {
    
    text}}</span>
            </div>
          </template>

          <template #action="text, record, index">
            <div class="editable-row-operations">
              <div v-if="record.editable">
                <a @click="save(record.key)">保存</a>
                <a-divider type="vertical"/>
                <a @click="cancel(record.key)">取消</a>
              </div>
              <div v-else>
                <a @click="edit(record.key)">编辑</a>
              </div>
            </div>
          </template>
        </a-table>
      </div>
    </div>
  </div>
</template>

<script>
  import Mixin from './mixin'
  import Moment from 'moment'

  export default {
    
    
    name: "DataTemplateDemo",
    mixins: [Mixin],
    methods: {
    
    
      // 将时间字符串 转换 为 Moment
      momentDateStr(dateStr) {
    
    
        return Moment(dateStr)
      }
    }
  }
</script>

Mixin

import {
    
    clearReference} from '@/utils/utils'

const data = []

for (let i = 0; i < 10; i++) {
    
    
  data.push({
    
    
    key: i,
    a: '2019-12-17',
    b: 'lucy',
    c: '22',
    e: '22',
    d: '22',
    f: '22',
    g: '22',
    h: '22',
    i: '22',
    j: '22',
    editable: false
  })
}

const Mixin = {
    
    
  data() {
    
    
    return {
    
    
      // 表格列 - 为了方便使 dataIndex === scopedSlots.customRender
      columns: [
        {
    
    title: '左边固定', width: 200, align: 'center', dataIndex: 'a', fixed: 'left', scopedSlots: {
    
    customRender: 'a'}},
        {
    
    title: '测试列3', width: 200, dataIndex: 'b', scopedSlots: {
    
    customRender: 'b'}},
        {
    
    title: '测试列4', width: 200, dataIndex: 'c', scopedSlots: {
    
    customRender: 'c'}},
        {
    
    
          title: '测试列5', width: 200, children: [
            {
    
    title: '分组1', width: 200, dataIndex: 'e', scopedSlots: {
    
    customRender: 'e'}},
            {
    
    title: '分组2', width: 200, dataIndex: 'j', scopedSlots: {
    
    customRender: 'j'}},
          ]
        },
        {
    
    title: '测试列6', width: 200, dataIndex: 'f', scopedSlots: {
    
    customRender: 'f'}},
        {
    
    title: '测试列7', width: 200, dataIndex: 'g', scopedSlots: {
    
    customRender: 'g'}},
        {
    
    title: '测试列8', width: 200, dataIndex: 'h', scopedSlots: {
    
    customRender: 'h'}},
        {
    
    title: '测试列8', dataIndex: 'i', scopedSlots: {
    
    customRender: 'i'}},
        {
    
    title: '右边固定2', width: 200, align: 'center', scopedSlots: {
    
    customRender: 'action'}, fixed: 'right'},
      ],
      // 表格数据
      tableData: [],
      // 表格缓存的数据 - 用来点击取消时回显数据
      cacheData: [],
      // 每一列的插槽名 - 表格行内编辑用
      customRenderList: ['a', 'b', 'c', 'e', 'f', 'g', 'h', 'i', 'j'],
      // 用来匹配插槽中显示input框
      inputScopedSlots: ['c', 'e', 'f', 'g', 'h', 'i', 'j'],
      // 用来匹配插槽中显示date框
      dateScopedSlots: ['a'],
      // 用来匹配插槽中显示select框
      selectScopedSlots: ['b'],
      // 对于某些自动赋值的input框设为 只读
      readonlyArr: ['c'],
      // 表格分页
      pagination: {
    
    
        current: 1,
        size: 'large',
        pageSize: 10, // 默认每页显示数量
        total: 0, // 总条数
        showQuickJumper: true,
        showTotal: (total, range) => `总共 ${
      
      total} 条记录,当前第 ${
      
      range[0]}条至第${
      
      range[1]}条`,
        onChange: (page) => this.pageChange(page)
      },
      // 表格loading
      tableLoading: false,
      // 表格选中key
      selectedRowKeys: []
    }
  },
  created() {
    
    
    // 此处模拟ajax,赋值(需清除引用)
    this.tableData = clearReference(data)
    this.cacheData = clearReference(data)
  },
  methods: {
    
    
    // 分页事件
    pageChange(page) {
    
    
      this.pagination.current = page
    },
    // 表格选中事件
    onSelectChange(selectedRowKeys) {
    
    
      console.log(selectedRowKeys);
      this.selectedRowKeys = selectedRowKeys;
    },
    // 表格点击全选事件
    onSelectAllChange(selected, selectedRows) {
    
    
      // 判断 全选并且第一行数据为新增 则不选中新增那一行
      if (selected && selectedRows[0].key === 'newRow') {
    
    
        this.selectedRowKeys.splice(0, 1)
      }
    },
    // 添加一行
    addRow() {
    
    
      if (this.tableData.some(item => item.newRow === true)) return this.$message.info('请先编辑完毕后在再添加!');

      // 新增时取消表格选中的key
      this.selectedRowKeys = []

      this.tableData.unshift({
    
    
        key: 'newRow',  // newRow 表示该行是新增的,提交成功后 key替换为数据库ID
        newRow: true,   //用来限制只能新增一行
        a: this.$dateformat(new Date(), 'isoDate'),
        b: undefined,
        c: '',
        e: '',
        d: '',
        f: '',
        g: '',
        h: '',
        i: '',
        j: '',
        editable: true
      })
      this.cacheData.unshift({
    
    
        key: 'newRow',
        newRow: true,
        a: this.$dateformat(new Date(), 'isoDate'),
        b: undefined,
        c: '',
        e: '',
        d: '',
        f: '',
        g: '',
        h: '',
        i: '',
        j: '',
        editable: false
      })
    },
    // 编辑一行
    edit(rowKey) {
    
    
      const newData = [...this.tableData];
      const target = newData.filter(item => rowKey === item.key)[0];
      // 根据rowKey判断该行数据是否存在
      if (target) {
    
    
        target.editable = true;   // 修改target可以直接影响到newData
        this.tableData = newData;
      }
    },
    // 点击保存
    save(rowKey) {
    
    
      const newData = [...this.tableData];
      const target = newData.filter(item => rowKey === item.key)[0];
      if (target) {
    
    
        delete target.editable;
        this.tableData = newData;
        this.cacheData = newData.map(item => ({
    
    ...item}));
      }
    },
    // 点击取消
    cancel(rowKey) {
    
    
      const newData = [...this.tableData];
      const target = newData.filter(item => rowKey === item.key)[0];
      if (target) {
    
    
        // 将缓存数据中匹配到的数据对象覆盖合并当前被修改的行
        Object.assign(target, this.cacheData.filter(item => rowKey === item.key)[0]);
        delete target.editable;
        this.tableData = newData;
      }
    },
    // input 输入change
    handleChange(value, rowKey, colName) {
    
    
      const newData = [...this.tableData];
      const target = newData.filter(item => rowKey === item.key)[0];
      if (target) {
    
    
        target[colName] = value;
        this.tableData = newData;
      }
    },
    // 日期框 change
    onChangeDate($event, rowKey, colName) {
    
    
      const newData = [...this.tableData];
      const target = newData.filter(item => rowKey === item.key)[0];
      if (target) {
    
    
        target[colName] = this.$dateformat($event, 'isoDate');
        this.tableData = newData;
      }
    },
    // select 框 change
    onChangeSelect($event, rowKey, colName) {
    
    
      const newData = [...this.tableData];
      const target = newData.filter(item => rowKey === item.key)[0];
      if (target) {
    
    
        target[colName] = $event;

        // 根据select框的值自动带出某个input的值 - 因为第三列列名为c
        $event === 'lucy' ? target.c = '根据lucy带出的值' : target.c = '根据jack带出的值'

        this.tableData = newData;
      }
    }
  }
}

export default Mixin

Principio de realización

Basado en una demostración oficial de antV más algunas implementaciones nuevas propias, la implementación específica tiene comentarios muy detallados en el código. A regañadientes, no hay más tiempo para optimizar este grueso y tosco post de blog, en la actualidad solo podemos pegar el código de demostración de una manera simple y tosca.

suplemento

Porque el texto del clearReferencemétodo es en realidadJSON.parse(JSON.stringify(obj))

Supongo que te gusta

Origin blog.csdn.net/dizuncainiao/article/details/103599434
Recomendado
Clasificación