提示:记录学习elementUI时遇到的一些问题及解决办法
现象: 第一次打开网页,先点击修改,再点击新增,发现输入框竟然有值
原因: 点击修改后,关闭对话框的时候,置空失效了
分析: 主人公resetFields有问题
线索1: Dialog 的内容是懒渲染的,即在第一次被打开之前,传入的默认 slot不会被渲染到 DOM 上
线索2: vue数据改变(先执行同步所有)再去更新DOM(异步代码)
无问题操作: 第一次打开网页,先点击新增按钮 -> dialog出现 -> el-form组件第一次挂载(关联的addForm对象的属性的值为空字符串) el-form组件内绑定了初始值,所以后续调用resetFields的时候,它可以用到空字符串初始值来重置
有问题: 第一次打开网页,先点击修改按钮 -> 虽然dialog变量为true了但是同步代码把addForm对象里赋值了(默认值) -> DON更新异步 -> dialog出现 -> el-form组件第一次挂载(使用addForm内置做回显然后第一次el-fonm内绑定了初始值(有值)) -> 以后做重置,它就用绑定的带值的做重置
按照1、2、3的顺序操作出现 bug ,图片展示:
按照1、2、3的顺序,在第二步、 第三步 操作时出现的图片,(设计时,是要点击第三步的地方是提出的框的数据清空,按照上面的步骤操作出现如下的情况)
按照1、3、2、3的顺序出现如下情况(这是正确的情况,我们要解决上面那种情况)
import axios from 'axios'
const baseURL = 'xxxxxx'
const myAxios = axios.create({
// 基地址
baseURL
})
// 导出 axios 自定义函数
export default myAxios
/**
* 获取-文章分类
* @returns {*}
*/
const getArtCateListAPI = () => {
return request({
url: '/my/cate/list'
})
}
/**
* 添加-文章的分类
* @param cate_name cate_name:文章分类名
* @param cate_alias cate_alias:文章分类别名
* @returns {*}
*/
const addArtCateAPI = ({cate_name, cate_alias}) => {
return request({
url: 'my/cate/add',
method: 'POST',
data: {
cate_name,
cate_alias
}
})
}
/**
* 更新-文章分类
* @param id 文章分类id
* @param cate_name 文章分类名
* @param cate_alias 文章分类别名
* @returns {*}
*/
const updateArtCateAPI = ({id, cate_name, cate_alias}) => {
return request({
url: '/my/cate/info',
method: 'put',
data: {
id,
cate_name,
cate_alias
}
})
}
// 导出接口
export {
addArtCateAPI,
getArtCateListAPI,
updateArtCateAPI
}
<template>
<div>
<!-- 预览文章 -->
<el-card class="box-card">
<div slot="header" class="clearfix header-box">
<span>文章分类</span>
<el-button size="mini" type="primary" @click="addCateBtnFn">添加分类</el-button>
</div>
<!-- 分类数据表格 -->
<!-- data 数据源 -->
<el-table :data="cateList" border stripe style="width: 100%">
<!-- type 是 table-column 内置属性,你告诉他用 index,意思就是第一个单元格用索引值 -->
<el-table-column label="序号" type="index" width="100"></el-table-column>
<el-table-column label="分类名称" prop="cate_name"></el-table-column>
<el-table-column label="分类别名" prop="cate_alias"></el-table-column>
<el-table-column label="操作">
<!-- scope对象:{ row:行对象 } -->
<template v-slot:default="scope">
<el-button size="mini" type="primary" @click="updateCateBtnFn(scope.row)">修改</el-button>
<el-button size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog :visible.sync="dialogVisible" title="提示" width="30%" @close="dialogCloseFn">
<!-- 添加的表单 -->
<el-form ref="addRef" :model="addForm" :rules="addRules" label-width="80px">
<el-form-item label="分类名称" prop="cate_name">
<el-input v-model="addForm.cate_name" maxlength="10" minlength="1"></el-input>
</el-form-item>
<el-form-item label="分类别名" prop="cate_alias">
<el-input v-model="addForm.cate_alias" maxlength="15" minlength="1"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="confirmFn">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import {addArtCateAPI, getArtCateListAPI, updateArtCateAPI} from '@/api'
export default {
name: 'ArtCate',
data() {
return {
// 文章的分类列表
cateList: [],
dialogVisible: false, // 增加文章分类对话框-->出现(true)/隐藏(false)
addForm: { // 添加表单的数据对象
cate_name: '',
cate_alias: ''
},
addRules: { // 添加表单的验证规则对象
cate_name: [
{required: true, message: '请输入分类名称', trigger: 'blur'},
{pattern: /^\S{1,10}$/, message: '分类名必须是1-10位的非空字符', trigger: 'blur'}
],
cate_alias: [
{required: true, message: '请输入分类别名', trigger: 'blur'},
{pattern: /^[a-zA-Z0-9]{1,15}$/, message: '分类别名必须是1-15位的字母数字', trigger: 'blur'}
]
},
isEdit: false, // true为编辑状态,false为新增状态
editId: '' // 记录文章类别的id
}
},
methods: {
// 获取文章分类
async initCateListFn() {
const {data: res} = await getArtCateListAPI()
// console.log(res);
this.cateList = res.data
},
// 添加分类按钮点击事件->为了让对话框出现
addCateBtnFn() {
this.isEdit = false
this.editId = ''
this.dialogVisible = true
},
// 对话框确定按钮->点击事件->让对话框消失/调用保存文章分类接口
confirmFn() {
this.$refs.addRef.validate(async valid => {
if (valid) {
// 通过校验
if (this.isEdit) { // 修改分类
// 把要编辑的文章分类id添加到对象上
const {data: res} = await updateArtCateAPI({id: this.editId, ...this.addForm})
// console.log(res)
if (res.code !== 0) return this.$message.error(res.message)
this.$message.success(res.message)
} else { // 添加分类
const {data: res} = await addArtCateAPI(this.addForm)
// console.log(res)
if (res.code !== 0) return this.$message.error(res.message)
this.$message.success(res.message)
}
this.initCateListFn()
// 关闭对话框
this.dialogVisible = false
} else {
// 未通过校验
return false
}
})
},
// 对话框-关闭时的回调
dialogCloseFn() {
this.$refs.addRef.resetFields()
},
// 修改分类按钮->点击事件(先做数据回显)
updateCateBtnFn(obj) {
this.isEdit = true
this.editId = obj.id
this.dialogVisible = true
// 让el-dialog第一次挂载el-form时,先用addForm空字符串初始值绑定到内部,后续用作resetFields重置
// 所以让真实DOM先创建并在内部绑定好复制好初始值
// 接着我们真实DOM更新后绑定好了,咱们再给数据回显
// 注意:我们给v-model对象赋值只是影响当前显示的值,不会影响到resetFields复制的初始值
// 数据回显(回填)
this.addForm.cate_name = obj.cate_name
this.addForm.cate_alias = obj.cate_alias
}
},
created() {
// 获取文章分类
this.initCateListFn()
}
}
</script>
<style lang="less" scoped>
.header-box {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
将 article.vue 代码中的 updateCateBtnFn 函数修改一下就行
updateCateBtnFn(obj) {
this.isEdit = true
this.editId = obj.id
this.dialogVisible = true
// $nextTick()回调推迟到下一个 DOM 更新周期之后执行
this.$nextTick(() => {
this.addForm.cate_name = obj.cate_name
this.addForm.cate_alias = obj.cate_alias
})
}