select的value值为对象时,获取label和value

使用select时,有时后台查表浪费时间,会需要把select选中数据的id,name都传给后台。option的value绑定对象时,必需要给select绑定一个value-key,官方文档也有标注

代码如下

<el-select v-model="ruleForm.branch" filterable placeholder="请选择" value-key="id">

                        <el-option

                            v-for="item in ruleForm.branchArr"

                            :key="item.id"

                            :label="item.name"

                            :value="item">

                        </el-option> 

</el-select>
复制代码

转载于:https://juejin.im/post/5c861230f265da2d8963661b

<think>我们正在使用Element Plus的el-tree-select组件。用户希望获取选中节点的labelvalue。根据引用[1],我们知道在el-tree-select中,通过设置`:props`属性来指定节点中labelvalue对应的字段。例如,设置`{ label: 'name',value:'id' }`,那么节点的label就是name字段,value就是id字段。同,引用[1]也提到,如果不正确设置node-key以及props,可能会导致回显问题。另外,引用[2]提到在el-tree中获取选中节点的方法,包括全选半选节点。但是,el-tree-select组件是否支持类似的方法呢?实际上,el-tree-select组件是el-selectel-tree的组合,它提供了一个v-model绑定选中的(通常是value字段的)。但是,如果我们同需要选中的节点的label(例如显示的名称)value(例如id),我们可能需要通过其他方式获取。思路:1.我们通常通过v-model绑定的是选中的value(即节点的value字段,如id)。如果我们还需要label,那么我们需要根据选中的value去数据源中找到对应的节点,从而获取label。2.或者,我们可以监听选中的事件,在事件回调中获取选中的节点对象,从而直接获取labelvalue。具体方法:方法一:使用v-model绑定选中的value,然后通过计算属性或方法,根据value从数据中查找对应的节点,获取label。方法二:使用@change事件(或el-tree-select的其他事件,如check-change,但注意el-tree-select可能使用不同的事件)来获取选中的节点对象。但是,我们需要查看ElementPlus的文档(由于我们不能直接访问,根据经验): el-tree-select组件提供了`change`事件,当选中发生变化触发。该事件有两个参数:当前选中的value选中节点的数据(Node)的数组(如果是多选)或对象(如果是单选)。注意,多选情况下,它返回的是选中的节点对象数组吗?还是只是value数组?我们需要确认。实际上,根据Element Plus的文档(回忆),el-tree-select的change事件回调的第一个参数是当前选中的value数组(多选)或value(单选),第二个参数是当前操作导致选中状态变化的节点数组(包括选中取消选中的节点)。但是,如果我们想获取所有当前选中的节点对象,可能不能直接通过这个事件得到。因此,我们可以考虑使用另一种方式:利用组件的ref,通过调用组件的方法来获取选中的节点。在el-tree中,我们可以使用getCheckedNodes方法来获取选中的节点(包括全选半选?注意,el-tree-select内部封装了el-tree,但暴露的API可能不同)。然而,el-tree-select组件并没有直接提供获取选中节点对象的方法。所以,我们可能需要使用数据映射的方式:根据v-model绑定的value数组,在原始数据中查找对应的节点。但是,如果我们的数据结构是树形结构,查找可能需要递归,而且如果节点很多,可能会有性能问题。另一种思路:在初始化数据,我们构建一个映射表(id到节点的映射),这样我们可以通过value快速找到节点。步骤:1.构建一个映射对象,将每个节点的id(即value)映射到该节点的完整数据(包括label等)。注意,树形结构需要递归遍历。2.当选中发生变化,通过映射表将value数组映射到节点数组,然后就可以获取每个节点的labelvalue。然而,el-tree-select组件在单选多选情况下,获取选中节点的方式略有不同。具体实现:假设我们的数据结构如下: ```javascriptdata:[{id:1,name: '一级1',children:[{id:4,name: '二级1-1',children:[{id:9,name: '三级1-1-1'}]}] },{id:2,name:'一级2',children: [{id:5,name:'二级2-1'},{id:6,name:'二级2-2'}] }] ```在组件中: ```html<el-tree-selectv-model="selectedValue":data="data":props="{label:'name', value: 'id'}"node-key="id"multiple@change="handleChange"/> ```其中,`selectedValue`是选中的id数组(多选)或单个id(单选)。方法一:使用事件我们可以监听`change`事件,但是事件参数中并不直接包含节点对象(根据Element Plus文档,el-tree-select的change事件第一个参数是当前选中的value,第二个参数是触发事件的节点数组,但这个数组只包括本次变化涉及的节点,而不是所有选中的节点)。所以,我们可能需要自己维护选中的节点列表,或者使用映射表。方法二:使用ref我们可以给el-tree-select设置ref,然后通过ref调用内部el-tree的方法。根据ElementPlus的源码,el-tree-select内部有一个treeRef,它是el-tree的实例。所以我们可以这样: ```javascriptthis.$refs.treeSelect.treeRef.getCheckedNodes()```但是,这个treeRef是否公开?在文档中并没有明确说明,但我们可以尝试。实际上,在ElementPlus的官方文档中,el-tree-select并没有直接提供获取选中节点的方法,但我们可以通过内部tree的ref来调用。步骤:1.给el-tree-select设置ref,比如`myTreeSelect`2.然后通过`this.$refs.myTreeSelect.treeRef`获取内部的el-tree组件实例3.调用el-tree的`getCheckedNodes`方法(注意:这个方法返回的是当前选中的节点数组,包括全选半选?实际上,根据el-tree的文档,`getCheckedNodes`返回的是全选中的节点,不包括半选中的节点。而如果我们想要包括半选中的节点,可以使用`getCheckedNodes``getHalfCheckedNodes`合并,如引用[2]所示。但是,在el-tree-select中,我们通常只需要全选中的节点,因为半选中的节点不会直接作为选中的。)注意:在el-tree-select中,选中的节点是用户明确勾选的(即全选),半选中的节点(父节点)并不会作为选中的。所以,我们可能只需要全选中的节点。因此,我们可以这样获取选中的节点(包括labelvalue):```javascript//在需要获取选中节点的地方consttree=this.$refs.myTreeSelect.treeRef; if(tree) {constcheckedNodes= tree.getCheckedNodes();//返回选中的节点对象数组//每个节点对象中,有我们在props中指定的labelvalue字段(即这里的nameid)//例如,第一个节点的label:checkedNodes[0].name, value: checkedNodes[0].id} ```但是,这种方法在单选模式下是否有效?在单选模式下,我们通常使用`getCurrentNode`?但是el-tree-select在单选模式下,内部el-tree可能没有选中节点(因为它是通过选择来触发的)。实际上,在单选模式下,我们可能无法通过getCheckedNodes获取(因为单选模式没有复选框)。所以我们需要区分单选多选。在单选模式下,el-tree-select的v-model绑定的是单个id,我们可以通过映射表找到对应的节点。因此,为了通用,我们可以:1.构建一个映射表(将每个节点的id映射到节点对象),这样无论单选多选,我们都可以通过选中的value找到节点。2.构建映射表的方法:递归遍历整个数据树。示例代码:```javascript//构建映射constnodeMap ={}; functionbuildMap(nodes){nodes.forEach(node =>{nodeMap[node.id] =node;//注意:这里假设id唯一if (node.children&& node.children.length) {buildMap(node.children);}});} buildMap(this.data);```然后,当我们需要获取选中的节点:多选:```javascriptconstselectedNodes= this.selectedValue.map(id=> nodeMap[id]); ```单选: ```javascriptconst selectedNode =nodeMap[this.selectedValue]; ```但是,这种方法有一个问题:如果节点数据很大,构建映射表可能会消耗内存,而且需要维护(当数据变化,需要重新构建)。另外,如果节点id不唯一,则会有问题。考虑到el-tree-select内部已经维护了节点树,使用ref调用内部方法可能更直接。针对单选多选,我们分别处理:1.多选:使用`getCheckedNodes`方法。2.单选:el-tree-select内部有一个`currentNode`吗?或者我们可以通过v-model的在映射表中查找。但是,我们也可以统一使用ref来获取:在el-tree-select中,无论单选多选,我们都可以通过以下方式:```javascript//多选if(this.multiple) {constnodes =this.$refs.myTreeSelect.treeRef.getCheckedNodes();} else{//单选:我们可以通过getCurrentNode?但是el-tree中,单选情况下,当前选中的节点可以通过getCurrentNode获取,但是需要先设置current-node-key或者通过点击选中。而el-tree-select在选中,内部el-tree会设置当前节点吗?//实际上,在单选模式下,我们可以通过v-model的(即id)在树中查找节点,或者使用映射表。//或者,我们可以通过ref获取内部el-tree,然后调用getNode方法(根据id)来获取节点对象constnode =this.$refs.myTreeSelect.treeRef.getNode(this.selectedValue);// getNode方法返回节点对象} ```因此,结合ref内部el-tree的方法,我们可以这样实现:示例代码:```javascriptmethods: {getSelectedNodes() {if(this.multiple) {//多选returnthis.$refs.myTreeSelect.treeRef.getCheckedNodes();}else {//单选const node= this.$refs.myTreeSelect.treeRef.getNode(this.selectedValue);return node? [node]: [];}}} ```然后,我们就可以从返回的节点数组中获取每个节点的labelvalue。但是,注意:在单选模式下,我们可能还没有选中任何节点,所以需要判断。另外,在el-tree-select中,我们设置`node-key="id"`,所以getNode方法需要传入的就是节点的id。总结:1.在模板中设置ref(例如ref="myTreeSelect")node-key(例如node-key="id")。2.在需要获取选中节点的地方,调用上述`getSelectedNodes`方法(注意:这个方法中使用了treeRef,所以确保组件已经渲染完成)。但是,使用内部方法treeRef可能不是官方公开的API,存在版本变更的风险。因此,我们需要权衡。另一种官方推荐的方式:使用change事件,在事件中我们可以获取到变化的节点,然后自己维护选中的节点列表(多选情况下)。但是这样比较麻烦。考虑到易用性通用性,我们可以建议用户使用映射表的方式(通过id查找节点),这样不依赖内部实现。所以,我们提供两种方案供用户选择。方案一(推荐使用映射表):步骤:1.构建一个id到节点的映射表(递归遍历数据)。2.在获取选中节点,通过v-model绑定的selectedValue(如果是数组,则遍历;如果是单个,则直接取)来从映射表中取出节点对象。示例代码: ```javascript//在data中定义nodeMapdata(){return {data: [],//树形数据selectedValue:null,//单选,或者多选为数组nodeMap: {}//映射表} },created() {this.buildNodeMap(this.data);}, methods: {buildNodeMap(nodes) {nodes.forEach(node=> {this.nodeMap[node.id] =node;//注意:这里会覆盖相同id的节点,所以确保id唯一if (node.children&& node.children.length) {this.buildNodeMap(node.children);}});},getSelectedNodes() {if(this.multiple) {//多选,selectedValue是数组return this.selectedValue.map(id=> this.nodeMap[id]).filter(node=> node); //过滤掉可能找不到的节点}else {//单选return this.selectedValue? [this.nodeMap[this.selectedValue]]: [];}}} ```方案二:使用ref调用内部方法(不保证稳定性,但可能更直接)示例代码: ```javascriptmethods:{getSelectedNodes(){consttree =this.$refs.myTreeSelect?.treeRef;if (!tree)return [];if(this.multiple) {returntree.getCheckedNodes();} else{const node= tree.getNode(this.selectedValue);returnnode ?[node] :[];}} }```用户可以根据自己的需求选择。如果数据结构稳定且id唯一,推荐方案一。如果不想维护映射表,且可以接受使用内部方法,则使用方案二。最后,获取labelvalue:通过上述方法得到节点数组后,每个节点对象中就有我们在props中指定的labelvalue对应的字段(例如,label字段为'name',那么节点.name就是labelvalue字段为'id',那么节点.id就是value)。示例:```javascriptconstselectedNodes= this.getSelectedNodes();selectedNodes.forEach(node=> {constlabel =node.name; //根据实际设置的label字段constvalue =node.id;//根据实际设置的value字段});```注意:如果用户设置的props中labelvalue的字段不是'name''id',则需要根据实际设置来取。因此,我们可以动态获取:假设props设置是`{ label: 'labelField', value: 'valueField' }`,那么我们可以这样:```javascriptconstlabelField= this.treeProps.label; //假设treeProps是props中设置的const valueField =this.treeProps.value;selectedNodes.forEach(node=> {constlabel =node[labelField];constvalue =node[valueField]; });```但是,在组件内部,我们可能已经将props保存到data或computed中。所以,根据用户的具体实现,灵活获取。回答用户问题:用户的问题是:如何在el-tree-select组件中获取选中节点的labelvalue?我们可以这样回答:要获取el-tree-select组件中选中节点的labelvalue,有两种推荐方法:方法一:通过构建节点映射表,根据v-model绑定的(即选中的value)查找节点对象,然后获取labelvalue。方法二:通过ref调用组件内部el-tree的方法获取选中的节点对象(注意:这种方法依赖于内部实现,可能不稳定)。下面详细说明两种方法:方法一:使用映射表步骤:1.在组件创建,递归遍历树形数据,构建一个以节点id(即value)为键,节点对象的映射对象。2.当需要获取选中节点,根据v-model绑定的(如果是多选,则为数组;单选则为单个)从映射表中取出节点对象。3.从节点对象中取出labelvalue(根据您在props中设置的字段)。示例代码: ```vue<template><el-tree-selectv-model="selectedValue":data="data":props="treeProps"node-key="id":multiple="multiple"/><button @click="getSelectedNodes">获取选中节点</button></template> <script>export default{data(){return {multiple: true, //根据实际情况data: [/*树形数据*/ ],selectedValue:this.multiple? []: null, //根据单选或多选初始化treeProps:{label: 'name',value:'id' },//根据实际字段设置nodeMap:{} //映射表};},created() {this.buildNodeMap(this.data);},methods: {buildNodeMap(nodes) {nodes.forEach(node=> {//注意:确保id唯一,否则会覆盖this.nodeMap[node[this.treeProps.value]]= node;if (node.children&& node.children.length) {this.buildNodeMap(node.children);}});},getSelectedNodes() {//获取选中的节点对象数组letnodes =[];if (this.multiple){//多选:selectedValue是数组nodes= this.selectedValue.map(value=> this.nodeMap[value]).filter(node =>node !==undefined);}else {//单选if (this.selectedValue){const node= this.nodeMap[this.selectedValue];if (node)nodes =[node];}}//现在nodes是选中的节点数组//遍历nodes,获取labelvalueconstresult= nodes.map(node=> ({label: node[this.treeProps.label],value:node[this.treeProps.value]}));console.log(result);returnresult;}}};</script> ```方法二:使用ref调用内部方法步骤:1.给el-tree-select设置ref,例如`myTreeSelect`。2.通过`this.$refs.myTreeSelect.treeRef`获取内部el-tree组件的实例。3.如果是多选,调用`getCheckedNodes`方法获取选中的节点数组;如果是单选,调用`getNode`方法(传入选中的value获取节点对象。4.然后从节点对象中取出labelvalue。示例代码: ```vue<template><el-tree-selectref="myTreeSelect"v-model="selectedValue":data="data":props="treeProps"node-key="id":multiple="multiple"/><button @click="getSelectedNodesByRef">获取选中节点(通过ref)</button></template> <script>export default{data(){return{multiple:true,//根据实际情况data:[ /*树形数据*/ ],selectedValue:this.multiple ?[] :null,treeProps:{ label: 'name',value:'id' }};},methods: {getSelectedNodesByRef() {consttreeSelect= this.$refs.myTreeSelect;if (!treeSelect)return [];consttree =treeSelect.treeRef;if(!tree) return[];let nodes= [];if(this.multiple) {nodes= tree.getCheckedNodes();}else {constnode =tree.getNode(this.selectedValue);if (node)nodes =[node];}const result= nodes.map(node=> ({label: node[this.treeProps.label],value:node[this.treeProps.value]}));console.log(result);return result;}} };</script> ```注意:方法二依赖于el-tree-select内部暴露的treeRef,这虽然不是官方文档明确公开的API,但在Element Plus中目前是可用的。如果后续版本有变化,可能需要调整。用户可以根据自己的情况选择合适的方法。相关问题:1.在el-tree-select中,如何设置节点的禁用?2.el-tree-select的数据量很大,如何优化性能?3.如何动态更新el-tree-select的数据?</think>在 Element Plus 的 `el-tree-select` 组件中获取选中节点的 label value ,可以通过以下两种方法实现: ### 方法一:通过 `@change` 事件获取(推荐) 1. **监听 `@change` 事件**: ```vue <el-tree-select v-model="selectedValue" :data="treeData" :props="{ label: 'name', value: 'id' }" node-key="id" multiple @change="handleSelectionChange" /> ``` 2. **在事件处理函数中获取节点信息**: ```javascript methods: { handleSelectionChange(selectedIds) { // 根据选中 id 查找完整节点数据 const selectedNodes = this.findNodesByIds(selectedIds, this.treeData); // 提取 label value const result = selectedNodes.map(node => ({ label: node.name, // 对应 props.label 字段 value: node.id // 对应 props.value 字段 })); console.log("选中节点信息:", result); }, // 递归查找节点 findNodesByIds(ids, tree) { let nodes = []; tree.forEach(item => { if (ids.includes(item.id)) nodes.push(item); if (item.children) { nodes = nodes.concat(this.findNodesByIds(ids, item.children)); } }); return nodes; } } ``` ### 方法二:通过 `ref` 获取节点对象 1. **设置组件引用**: ```vue <el-tree-select ref="treeSelectRef" v-model="selectedValue" :data="treeData" :props="{ label: 'name', value: 'id' }" node-key="id" multiple /> ``` 2. **通过 `getCheckedNodes` 获取节点**: ```javascript methods: { getSelectedNodes() { const treeComponent = this.$refs.treeSelectRef.treeRef; const checkedNodes = treeComponent.getCheckedNodes(); const result = checkedNodes.map(node => ({ label: node.name, value: node.id })); console.log("选中节点信息:", result); return result; } } ``` ### 关键注意事项 1. **`props` 配置必须正确**: ```html :props="{ label: 'name', value: 'id' }" node-key="id" ``` 确保 `label` `value` 与数据字段匹配,且 `node-key` 与 `value` 字段一致[^1]。 2. **数据结构示例**: ```javascript treeData: [{ id: 1, name: 'Parent Node', children: [{ id: 2, name: 'Child Node' }] }] ``` 3. **多选模式**: - 使用 `multiple` 属性启用多选 - `v-model` 绑定为数组格式 ### 两种方法对比 | **方法** | **优点** | **缺点** | |----------------|-----------------------------|-----------------------| | `@change` 事件 | 实响应选择变化 | 需手动实现节点查找逻辑 | | `ref` 获取 | 直接获取完整节点对象 | 需主动调用方法触发 | > ⚠️ 注意:如果数据量较大,建议在初始化构建 `id->node` 的映射表优化查找性能: > ```javascript > created() { > this.nodeMap = this.createNodeMap(this.treeData); > }, > methods: { > createNodeMap(tree) { > const map = {}; > const traverse = (nodes) => { > nodes.forEach(node => { > map[node.id] = node; > if (node.children) traverse(node.children); > }); > }; > traverse(tree); > return map; > } > } > ``` [^1]: 必须正确配置 `props` `node-key`,否则会导致回显异常。 [^2]: 获取节点需注意全选/半选状态的处理逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值