1.首先调接口获取到标签列表,
// 级联选择器如果选择的不是第三级菜单
async getParamsData() {
if (this.selectedCateKeys.length !== 3) {
// 级联选择器不会有参数,下面的面板也都为空
this.selectedCateKeys = []
this.manyTableData = []
this.onlyTableData = []
return
}
// 如果选中的是三级分类
console.log(this.selectedCateKeys)
// 根据所选分类的Id,和当前所处的面板,获取对应的参数
const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`, {
params: { sel: this.activeName },
})
if (res.meta.status !== 200) {
return this.$message.error('获取参数列表失败!')
}
//将获取到的参数做处理
res.data.forEach((item) => {
// 将res.data的参数做处理 -------------------------- attr_vals记住这个,对标签进行增删都要用它
// item.attr_vals = item.attr_vals ? item.attr_vals.split(' ') : []
item.attr_vals = item.attr_vals.length === 0 ? [] : item.attr_vals.split(' ') //split(' ')表示将字符串转为数组,因为 attr_vals里面已经有都好进行分隔,所以这里不需要写逗号
//有了这个,相当于给每个数据加上了文本显示与隐藏的属性,在插槽里面就可以直接调用到,就不会造成之间的相互影响了
item.inputVisible = false
//有了这个,相当于给每个数据加上了文本框值属性,在插槽里面就可以直接调用到,就不会造成之间的相互影响了
item.inputValue = ''
})
console.log(res.data)
if (this.activeName === 'many') {
this.manyTableData = res.data
} else {
this.onlyTableData = res.data
}
},
上面的一些配套内容:
data() {
return {
// 级联选择框双向绑定到的数组(他的长度可以让我们拿到三级分类的id)
selectedCateKeys: [],
// 被激活的页签的名称(因为点击哪个表格是不确定的,所以需要这个)
activeName: 'many',
// 动态参数的数据(表格一的数据)
manyTableData: [],
// 静态属性的数据(表格二的数据)
onlyTableData: [],
}
},
computed: {
// 当前选中的三级分类的Id--------------------这个cateId在将新添加的内容保存到数据库,调接口删除用户,点击添加框和修改框确定按钮都要用到
cateId() {
if (this.selectedCateKeys.length === 3) {
return this.selectedCateKeys[2]
}
return null
},
},
2.这是标签列表的html结构(elementui组件)
<!-- 展开行 -->
<el-table-column type="expand">
<!-- 插槽 -->
<template slot-scope="scope">
<!-- 循环渲染Tag标签 closable为标签加上❌号 @close="handleClose(i, scope.row)"关闭tag标签时触发的事件 -->
<el-tag v-for="(item, i) in scope.row.attr_vals" :key="i" closable @close="handleClose(i, scope.row)">{{ item }}</el-tag>
<!-- 输入的文本框 -->
<!-- @keyup.enter.native="handleInputConfirm(scope.row)" 点击回车键是触发-->
<!-- @blur="handleInputConfirm(scope.row)"在 Input 失去焦点时触发 -->
<el-input
class="input-new-tag"
v-if="scope.row.inputVisible"
v-model="scope.row.inputValue"
ref="saveTagInput"
size="small"
@keyup.enter.native="handleInputConfirm(scope.row)"
@blur="handleInputConfirm(scope.row)"
>
</el-input>
<!-- 添加按钮 -->
<el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag</el-button>
</template>
</el-table-column>
3.标签变成文本框
// 点击+ New Tag按钮
showInput(row) {
// 显示输入框
row.inputVisible = true
// 让文本框自动获得焦点
// $nextTick 方法的作用,就是当页面上文本框渲染出来之后,才会去调用.focus()函数让文本框获得焦点
this.$nextTick((_) => {
this.$refs.saveTagInput.focus()
})
},
4.文本框变成标签
// 文本框失去焦点,或摁下了 Enter 都会触发
async handleInputConfirm(row) {
// 如果文本框里面没有内容,就重置文本框并且关闭文本框变回Tag标签
if (row.inputValue.trim().length === 0) {
row.inputValue = ''
row.inputVisible = false
return
}
// 如果有内容,则将内容去除空格后添加进attr_vals数组里面-------------(attr_vals数组就是标签里面的内容)
row.attr_vals.push(row.inputValue.trim())
// 重置文本框
row.inputValue = ''
// 关闭文本框变回Tag标签
row.inputVisible = false
// 将新添加的内容保存到数据库(只有保存进数据库才可以真正的保存进attr_vals数组)
this.saveAttrVals(row)
},
5.将刚才变成的标签保存进数据库,这样标签即使刷新后也能存在了
// 将新添加的内容保存到数据库(保存完后不要刷新页面,不然会关闭展开行,导致体验不好)
async saveAttrVals(row) {
// 需要发起请求,保存这次操作
const { data: res } = await this.$http.put(`categories/${this.cateId}/attributes/${row.attr_id}`, {
attr_name: row.attr_name,
attr_sel: row.attr_sel,
attr_vals: row.attr_vals.join(' '), // 将数组转换为字符串(因为接口上说这个参数只要字符串)(因为我们拿过来时将这个参数转成了数组,现在我们是转回去)
})
if (res.meta.status !== 200) {
return this.$message.error('修改参数项失败!')
}
this.$message.success('修改参数项成功!')
},
6.点击标签的叉号删除标签(也要保存进数据库)
// 关闭tag标签时触发的事件
handleClose(i, row) {
row.attr_vals.splice(i, 1) //删除attr_vals数组里面的点击关闭的这个标签
// 刷新将新添加的内容保存到数据库这个函数
this.saveAttrVals(row)
},