使用Vue+Element-UI简单的做了一个表格的增删改,效果图如下,新增和修改编辑共用一个弹框表单组件。

首先点击编辑按钮,把当前的行数据传递给子组件,开始我以为只要在父组件中传递相应的props,然后子组件里获取即可,但是没有表单并没有读取到数据。

// 父组件
<template>
...
 <edit-modal
   :row="row"
   :visible.sync="dialogFormVisible"
   @close="dialogFormVisible = false"
   @updateItem="onUpdateSubmit"
 />
...
</template>
<script>
    ...
    data() {
        return {
            row: {}
        }
    }
    ...
    methods: {
        // 编辑按钮
        updateItem(row) {
            this.row = {...row}
        }
        ...
    }
</script>

// 子组件
<template> ... </template>

<script>
...
props: {
    row: Object
},
data() {
    return {
        form: this.row
    }
}
...

</script>

分析:在表格页加载完成时,子组件也已经挂载到DOM上,此时this.form = {},所以当点击编辑的时候,并不会像我们想象的那般父组件改变了row的值,然后子组件开始渲染,在data中初始化数据。子组件中的data在beforeCreated和created之间就已经完成。

所以点击编辑按钮,在父组件中修改row的时候,子组件中this.form没有更新,解决方法可以使用v-if,在父组件中控制子组件是否重新渲染,当然每次重新挂载子组件不是一种好方法,也可以使用$nextTick,调用子组件的方法,改变this.form的值。如下:

// 父组件
updateItem(row = {}) {
    this.dialogFormVisible = true;
    this.$nextTick(() => {
        this.$refs.editModal.dataInit(row);
    })
},
// 子组件
dataInit(data) {
    if (data) {
        //初始化表单,清空验证等
        this.form = {...data};
        this.$refs.form.resetFields();
    }
},

完整代码如下:

父组件:

<template>
  <div class="about">
    <div class="lottery">
      <el-button type="primary" @click="updateItem">添加</el-button>
      <el-button type="danger" @click="open" :disabled="multipleSelection.length === 0">删除</el-button>
    </div>

    <el-table
      :data="tableData"
      border
      ref="multipleTable"
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection"></el-table-column>
      <el-table-column prop="id" label="序号"></el-table-column>
      <el-table-column prop="name" label="选项"></el-table-column>
      <el-table-column prop="creator" label="创建人"></el-table-column>
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button @click="updateItem(scope.row)" type="text" size="small">编辑</el-button>
          <el-popconfirm
            :title="['选项删除后无法恢复,确认删除[' + scope.row.name + ']吗'] + '?'"
            @confirm="deleteItem(scope.row)"
          >
            <el-button slot="reference" type="text" size="small">删除</el-button>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <edit-modal
      ref="editModal"
      :visible.sync="dialogFormVisible"
      @close="dialogFormVisible = false"
      @updateItem="onUpdateSubmit"
    />
  </div>
</template>

<script>
import editModal from './editModal.vue'
export default {
  components: { editModal },
  data() {
    return {
      tableData: [
        {
          id: 113,
          name: 'a',
          creator: 'dd',
        }
      ],
      multipleSelection: [],
      dialogFormVisible: false,
    }
  },
  methods: {
    open() {
      const content = this.multipleSelection.map(v => v.name)
      this.$confirm(`确认删除${content.join(',')}吗`, '批量删除', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // 删除 batchDelete
        this.$message({
          type: 'success',
          message: '删除成功!'
        });
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    updateItem(row = {}) {
      this.dialogFormVisible = true;
      this.$nextTick(() => {
        // 弹框打开时初始化表单
        this.$refs.editModal.dataInit(row);
      })
    },
    onUpdateSubmit(data) {
      if (data?.id) {
        this.tableData.map(v => v.id === data.id ? v.name = data.name : v.name);
      } else {
        this.tableData.push({
          id: Math.floor(Math.random() * 300),
          name: data.name,
          creator: 'dd',
        })
      }

      this.dialogFormVisible = false;
    },
    deleteItem(row) {
      this.tableData = this.tableData.filter(v => v.id != row.id);
      this.getList();
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    getList() {
      this.tableData = [...this.tableData, {
        id: Math.floor(Math.random() * 100),
        name: 'a',
        creator: 'dd',
      }]
    },
  },
  mounted() {
    this.getList();
  }
}
</script>

<style scoped>
.lottery {
  text-align: left;
}

.operate {
  margin: 15px 0;
}
</style>

子组件:

使用before-close控制弹框的关闭按钮和点击模态框时,调用对应的函数,处理一些数据。

<template>
  <el-dialog :title="title" :visible.sync="visible" :before-close="onClose">
    <el-form :model="form" :rules="rules" ref="form">
      <el-form-item label="选项" prop="name">
        <el-input v-model="form.name" autocomplete="off"></el-input>
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="onClose">取 消</el-button>
      <el-button type="primary" @click="submit">确 定</el-button>
    </div>
  </el-dialog>
</template>

<script>
export default {
  name: 'editModal',
  props: {
    visible: false
  },
  data() {
    return {
      form: {},
      rules: {
        name: [
          { required: true, message: '请输入选项' },
        ],
      },
    }
  },
  computed: {
    title: function () {
      return this.form.id ? '修改' : '添加'
    }
  },
  methods: {
    dataInit(data) {
      if (data) {
        this.form = {...data};
        this.$refs.form.resetFields();
      }
    },
    onClose() {
      this.$emit('close')
    },
    submit() {
      this.$refs.form.validate((valid) => {
          if (valid) {
            this.$emit('updateItem', this.form)
          } else {
            return false;
          }
        })
    }
  },
}
</script>

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐