情景阐述:前端有一个表单,在新增或者编辑时会visible,表单中有一组checkbox,用于记录集群运行节点,这组checkbox的数据源来自集群信息查询,可多选,在前端选中值以数组存储显示,在后端以string存储。在进行新增过程中,通过json对象传值到后端,用RequestBody接收对象,这过程中涉及类型转换。
1、前端选择运行节点的值存储在数组里,保存时需要转换成字符串:
在开发中,若需要将数组转换为字符串,可以利用数组对象的join()和toString()方法实现。
toString()方法会把数组转换为字符串,逗号分隔每一项。
join('分隔符')会将数组的所有元素用指定的分隔符链接成为一个字符串。
join()和toString()方法可将多维数组转为字符串,默认情况下使用逗号连接。不同的是,join()方法可以指定连接数组元素的符号。另外,当数组元素为undefined、null或空数组时,对应的元素会被转换为空字符串。
_this.mdl.runNode = _this.mdl.runNode.toString();
那么在数据库中该字段数据就以字符串存储,每个节点以逗号隔开。
前端显示前先将字符串转换成数组:
let runNodes = _this.item.runNode;
_this.mdl.runNode = runNodes.split(',');
2、点击两次编辑,会报错“runNodes.split is not a function”
得到的runNodes 可能不是一个字符串,可以用 runNodes.toString().split(',')来获取。
3、checkbox已经选中赋值,但是页面上不显示
可能的原因是数据的加载时机不同造成的。当您在组件挂载后,立即使用内联数据初始化选择值时,选择值可以正常显示。但是,当您使用异步接口请求数据时,初始化选择值的代码可能会在数据请求完成之前执行,导致选择值无法正确设置。要解决在组件渲染之前设置选择值的问题,确保选择框正确渲染出来并标记已选项。
下面是一些可能的解决方案:
1)使用 async/await 或 Promise 对数据进行异步加载,并在获取数据之后再初始化选择值:
async fetchData () {
const res = await ClusterApi.getClusterNode({"id": clusterId})
this.nodes = res.data.records.map(item => {
return {'label': item.name, 'value': item.name}
})
this.selectedNodes = ['node-1'] // 初始化选择值
}
2)在使用异步接口加载数据之前,将 selectedNodes 初始化为空数组,然后在数据请求完成后再更新选择值:
data () {
return {
nodes: [],
selectedNodes: []
}
},
methods: {
fetchData () {
const _this = this
ClusterApi.getClusterNode({"id": clusterId}).then(function (res) {
_this.nodes = res.data.records.map(item => {
return {'label': item.name, 'value': item.name}
})
_this.selectedNodes = [] // 将选择值初始化为空数组
})
},
selectNodes () {
// 处理选择节点的代码
}
},
mounted () {
this.fetchData()
},
watch: {
nodes: function () {
// 在节点数据变化时,更新选择值
this.selectedNodes = ['node-1']
}
}
3)使用 v-if 条件渲染来确保数据加载完成后再显示 v-checkbox-group 组件和其选项:
<template>
<div>
<div v-if="nodes.length">
<v-checkbox-group v-model="selectedNodes">
<v-checkbox v-for="node in nodes" :key="node.value" :label="node.label" :value="node.value"></v-checkbox>
</v-checkbox-group>
</div>
<div v-else>
数据正在加载中...
</div>
</div>
</template>
4)通过在获取节点信息后使用$nextTick方法来等待DOM渲染完成后再设置选择值。
async showNodes(clusterId) {
let _this = this;
_this.nodes = [];
//获取节点信息
const res = await ClusterApi.getClusterNode({"id": clusterId});
_this.nodes = res.data.records.map(item =>{
return {'label':item.name, 'value': item.name}
})
//等待DOM渲染完成后再设置选择值
this.$nextTick(() => {
_this.mdl.runNode = ['node-1','node-3'];
});
}
$nextTick方法用于在下次DOM更新后执行回调函数,确保DOM更新完成后再执行后续逻辑。在上面的代码中,获取节点信息的过程改为异步等待,并使用$nextTick方法等待DOM渲染完成后再设置选择值. 通过这样的方式,可以保证在节点信息获取并且DOM渲染完成后再设置选择值,从而可以确保checkbox组件会正确地显示选项值。
5)把 _this.mdl.runNode = ['node-1','node-3'] 移到 showNodes 方法之后的 then 回调中,在获取数据完成后再设置选择值。
created () {
this.showNodes(clusterId).then(() => {
this.mdl.runNode = ['node-1','node-3'];
});
},
async showNodes(clusterId) {
let _this = this;
_this.nodes = [];
const res = await ClusterApi.getClusterNode({"id": clusterId});
_this.nodes = res.data.records.map(item =>{
return {'label':item.name, 'value': item.name}
});
}
将 _this.mdl.runNode = ['node-1','node-3'] 放到 created 钩子函数中,就会在渲染组件和获取数据之前执行,因此 checked 属性在组件渲染时仍然是空数组,所以不能正常勾选选择框。为了解决这个问题,可以执行 showNodes 方法,然后再把 _this.mdl.runNode 设置为选中值。把 _this.mdl.runNode = ['node-1','node-3'] 移到 showNodes 方法之后的 then 回调中,在获取数据完成后再设置选择值。同时,把 showNodes 方法也变为异步函数并使用 async/await 来获取数据。最后,在 created 钩子函数中调用 showNodes 方法,并在方法执行完成后设置选择值。