【商城项目16】级联选择器,新增属性分组,编辑回显

本文介绍了一个商城项目中级联选择器的优化,解决了返回空子集问题,并详细展示了如何在属性分组编辑中应用级联选择器,实现分类搜索和上传最近父节点的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【商城项目16】级联选择器,新增属性分组,编辑回显

解决返回空 子集合的问题:在children属性加注解

    @JsonInclude(JsonInclude.Include.NON_EMPTY)

image-20200603145148653

修改前:

image-20200603145403819

修改后:

image-20200603145409527

这样级联时候就不会出现空选择了:

image-20200603145514426

1.级联选择器

在分类时,用category-cascader自定义的组件,记得import进来

  <category-cascader :catelogPath.sync="catelogPath"></category-cascader>

category-cascader.vue:

<template>
<!-- 
使用说明:
1)、引入category-cascader.vue
2)、语法:<category-cascader :catelogPath.sync="catelogPath"></category-cascader>
    解释:
      catelogPath:指定的值是cascader初始化需要显示的值,应该和父组件的catelogPath绑定;
          由于有sync修饰符,所以cascader路径变化以后自动会修改父的catelogPath,这是结合子组件this.$emit("update:catelogPath",v);做的
      -->
  <div>
    <el-cascader
      filterable
      clearable 
      placeholder="试试搜索:手机"
      v-model="paths"
      :options="categorys"
      :props="setting"
    ></el-cascader>
  </div>
</template>

<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';

export default {
  //import引入的组件需要注入到对象中才能使用
  components: {},
  //接受父组件传来的值
  props: {
    catelogPath: {
      type: Array,
      default(){
        return [];
      }
    }
  },
  data() {
    //这里存放数据
    return {
      setting: {
        value: "catId",
        label: "name",
        children: "children"
      },
      categorys: [],
      paths: this.catelogPath
    };
  },
  watch:{
    catelogPath(v){
      this.paths = this.catelogPath;
    },
    paths(v){
      this.$emit("update:catelogPath",v);
      //还可以使用pubsub-js进行传值
      this.PubSub.publish("catPath",v);
    }
  },
  //方法集合
  methods: {
    getCategorys() {
      this.$http({
        url: this.$http.adornUrl("/mailproducts/category/list/tree"),
        method: "get"
      }).then(({ data }) => {
        this.categorys = data.categorytree;
      });
    }
  },
  //生命周期 - 创建完成(可以访问当前this实例)
  created() {
    this.getCategorys();
  }
};
</script>
<style scoped>
</style>

通过级联选择器,在上传时之上传最近的父节点,

attrgroup-add-or-update.vue:

<template>
  <el-dialog
    :title="!dataForm.id ? '新增' : '修改'"
    :close-on-click-modal="false"
    :visible.sync="visible"
    @closed="dialogClose"
  >
    <el-form
      :model="dataForm"
      :rules="dataRule"
      ref="dataForm"
      @keyup.enter.native="dataFormSubmit()"
      label-width="120px"
    >
      <el-form-item label="组名" prop="attrGroupName">
        <el-input v-model="dataForm.attrGroupName" placeholder="组名"></el-input>
      </el-form-item>
      <el-form-item label="排序" prop="sort">
        <el-input v-model="dataForm.sort" placeholder="排序"></el-input>
      </el-form-item>
      <el-form-item label="描述" prop="descript">
        <el-input v-model="dataForm.descript" placeholder="描述"></el-input>
      </el-form-item>
      <el-form-item label="组图标" prop="icon">
        <el-input v-model="dataForm.icon" placeholder="组图标"></el-input>
      </el-form-item>
      <el-form-item label="所属分类" prop="catelogId">
        <!-- <el-input v-model="dataForm.catelogId" placeholder="所属分类id"></el-input> @change="handleChange" -->
        <!-- <el-cascader filterable placeholder="试试搜索:手机" v-model="catelogPath" :options="categorys"  :props="props"></el-cascader> -->
        <!-- :catelogPath="catelogPath"自定义绑定的属性,可以给子组件传值 -->
        <category-cascader :catelogPath.sync="catelogPath"></category-cascader>
      </el-form-item>
    </el-form>
    <span slot="footer" class="dialog-footer">
      <el-button @click="visible = false">取消</el-button>
      <el-button type="primary" @click="dataFormSubmit()">确定</el-button>
    </span>
  </el-dialog>
</template>

<script>
import CategoryCascader from '../common/category-cascader'
export default {
  data() {
    return {
      props:{
        value:"catId",
        label:"name",
        children:"children"
      },
      visible: false,
      categorys: [],
      catelogPath: [],
      dataForm: {
        attrGroupId: 0,
        attrGroupName: "",
        sort: "",
        descript: "",
        icon: "",
        catelogId: 0
      },
      dataRule: {
        attrGroupName: [
          { required: true, message: "组名不能为空", trigger: "blur" }
        ],
        sort: [{ required: true, message: "排序不能为空", trigger: "blur" }],
        descript: [
          { required: true, message: "描述不能为空", trigger: "blur" }
        ],
        icon: [{ required: true, message: "组图标不能为空", trigger: "blur" }],
        catelogId: [
          { required: true, message: "所属分类id不能为空", trigger: "blur" }
        ]
      }
    };
  },
  components:{CategoryCascader},
  
  methods: {
    dialogClose(){
      this.catelogPath = [];
    },
    getCategorys(){
      this.$http({
        url: this.$http.adornUrl("/product/category/list/tree"),
        method: "get"
      }).then(({ data }) => {
        this.categorys = data.data;
      });
    },
    init(id) {
      this.dataForm.attrGroupId = id || 0;
      this.visible = true;
      this.$nextTick(() => {
        this.$refs["dataForm"].resetFields();
        if (this.dataForm.attrGroupId) {
          this.$http({
            url: this.$http.adornUrl(
              `/product/attrgroup/info/${this.dataForm.attrGroupId}`
            ),
            method: "get",
            params: this.$http.adornParams()
          }).then(({ data }) => {
            if (data && data.code === 0) {
              this.dataForm.attrGroupName = data.attrGroup.attrGroupName;
              this.dataForm.sort = data.attrGroup.sort;
              this.dataForm.descript = data.attrGroup.descript;
              this.dataForm.icon = data.attrGroup.icon;
              this.dataForm.catelogId = data.attrGroup.catelogId;
              //查出catelogId的完整路径
              this.catelogPath =  data.attrGroup.catelogPath;
            }
          });
        }
      });
    },
    // 表单提交
    dataFormSubmit() {
      this.$refs["dataForm"].validate(valid => {
        if (valid) {
          this.$http({
            url: this.$http.adornUrl(
              `/product/attrgroup/${
                !this.dataForm.attrGroupId ? "save" : "update"
              }`
            ),
            method: "post",
            data: this.$http.adornData({
              attrGroupId: this.dataForm.attrGroupId || undefined,
              attrGroupName: this.dataForm.attrGroupName,
              sort: this.dataForm.sort,
              descript: this.dataForm.descript,
              icon: this.dataForm.icon,
              catelogId: this.catelogPath[this.catelogPath.length-1]
            })
          }).then(({ data }) => {
            if (data && data.code === 0) {
              this.$message({
                message: "操作成功",
                type: "success",
                duration: 1500,
                onClose: () => {
                  this.visible = false;
                  this.$emit("refreshDataList");
                }
              });
            } else {
              this.$message.error(data.msg);
            }
          });
        }
      });
    }
  },
  created(){
    this.getCategorys();
  }
};
</script>

image-20200603151534640

2.保存

后端不用改,直接用。

3.修改时如何回显级联

改后端:

给AttrGroupEntity添加属性:

@TableField(exist = false)
	private Long[] catelogPath;

修改AttrGroupController的info函数,注意注注入目录服务:

    @Autowired
    private CategoryService categoryService;
    /**
     * 信息
     */
    @RequestMapping("/info/{attrGroupId}")
    public R info(@PathVariable("attrGroupId") Long attrGroupId){
		AttrGroupEntity attrGroup = attrGroupService.getById(attrGroupId);
        Long catelogId = attrGroup.getCatelogId();
        Long[] path = categoryService.findCatelogPath(catelogId);

        attrGroup.setCatelogPath(path);
        return R.ok().put("attrGroup", attrGroup);
    }

目录category,新建接口findCatelogPath:

    Long[] findCatelogPath(Long catelogId);

接口实现类添加:

//225,25,2
private List<Long> findParentPath(Long catelogId,List<Long> paths){
    //1、收集当前节点id
    paths.add(catelogId);
    CategoryEntity byId = this.getById(catelogId);
    if(byId.getParentCid()!=0){
        findParentPath(byId.getParentCid(),paths);
    }
    return paths;

}

@Override
    public Long[] findCatelogPath(Long catelogId) {
        List<Long> paths = new ArrayList<>();
        List<Long> parentPath = findParentPath(catelogId, paths);
        Collections.reverse(parentPath);
        return parentPath.toArray(new Long[parentPath.size()]);
    }

效果:

image-20200603154947945

image-20200603155005721

使级联可搜索:

<category-cascader :catelogPath.sync="catelogPath"></category-cascader>
<think>好的,我现在需要帮助用户解决在Vue中使用el-cascader组件时,按勾选顺序传递值的问题。首先,我需要回顾用户提供的引用内容,看看有没有相关的实现方法。 根据引用[2],用户提到el-cascader默认是根据层级结构来显示选项,而按勾选顺序传值需要自定义处理。用户希望摆脱层级约束,按照选择的顺序传递值。引用[3]中提到了通过change事件和ref获取选中的节点信息,特别是label值,这可能对获取选中顺序有帮助。引用[4]讨论了多选时父节点和子节点的勾选问题,虽然主要问题不同,但涉及到了勾选状态的监听和处理。 首先,我需要明确用户的需求:他们希望无论层级如何,都能按照用户勾选的顺序来传递值,而不是按照层级结构。例如,用户可能先选择子节点,再选择父节点,这时候传值的顺序应该保持先子后父。 接下来,我需要考虑如何实现这一点。el-cascader默认的行为是按照层级结构来组织选中的值,所以可能需要监听用户的勾选事件,记录每次选择的节点,并维护一个按顺序的数组。当用户勾选或取消勾选时,更新这个数组,并将最终的顺序作为v-model的值传递出去。 参考引用[3]中的方法,可以通过@change事件来获取当前选中的节点。使用ref获取组件实例,然后调用getCheckedNodes方法,这个方法返回当前选中的节点数组。但是默认情况下,这个数组可能还是按照层级结构排序的,所以需要自己维护一个顺序。 可能的步骤包括: 1. 使用v-model绑定一个数组来存储按顺序选中的值。 2. 监听change事件,每次勾选或取消时,获取所有已选中的节点。 3. 维护一个数组,记录用户点击的顺序。例如,当用户勾选一个节点时,将其添加到数组中;取消勾选时,从数组中移除。 4. 由于el-cascader本身可能不支持这种顺序,可能需要禁用其自动更新v-model,而是手动管理。 但这里有一个问题,el-cascader的v-model通常会根据组件的内部状态自动更新,所以如果手动管理,可能需要使用.sync修饰符或者监听事件来覆盖默认行为。不过,根据Element UI的文档,el-cascader的v-model是双向绑定的,所以直接修改绑定的数组可能会影响组件的显示状态。 另一个方法是利用checkedNodes数组,每次change事件触发时,获取最新的checkedNodes,然后按照用户操作的顺序来排序。但是如何追踪用户的点击顺序呢?可能需要利用鼠标事件,比如@check事件,每次勾选时记录节点,并添加到顺序数组中。 Element UI的el-cascader组件有一个@check事件,当用户勾选节点时触发。这个事件的参数是当前被勾选的节点。可以在每次触发@check事件时,将节点添加到自定义的数组中,并在@close事件(当选择器关闭时)或者@change事件时更新v-model的值。但需要注意取消勾选的情况,这时候需要从数组中移除节点。 具体步骤可能如下: 1. 在el-cascader上绑定@check和@uncheck事件(如果有的话),或者监听change事件,并结合getCheckedNodes来获取所有已选中的节点。 2. 维护一个数组selectedNodes,按用户勾选的顺序存储节点。 3. 当用户勾选一个新节点时,将其添加到selectedNodes数组。 4. 当用户取消勾选时,从selectedNodes数组中移除对应的节点。 5. 将selectedNodes数组中的节点的值提取出来,形成按顺序的值数组,并更新到v-model中。 不过,Element UI的el-cascader可能没有直接提供@uncheck事件,因此可能需要通过比较前后变化来处理取消勾选的情况。或者,在每次change事件触发时,获取所有当前选中的节点,并与之前保存的selectedNodes数组进行比较,找出新增或移除的节点,从而更新顺序。 这种方法可能比较复杂,但可以实现需求。例如: - 使用一个变量prevSelectedNodes保存上一次选中的节点数组。 - 在change事件触发时,获取当前的checkedNodes数组。 - 比较当前和之前的数组,找出新增的节点(勾选)和移除的节点(取消勾选)。 - 根据这些变化更新selectedNodes数组的顺序。 - 最后,将selectedNodes中的节点值映射为所需的格式,并更新到v-model。 另外,引用[3]中提到,通过ref获取checkedNodes,可以使用fileRef.value.getCheckedNodes(),这些节点对象可能包含pathLabels或path等信息,可以用来构建层级路径的值。例如,每个节点的path数组可能包含从根到当前节点的value,这样可以将每个节点的path作为该选项的值,从而保持层级结构,但按顺序排列。 不过用户需要的是按勾选顺序传值,而不是层级顺序。因此,可能需要将每个选中的节点的全路径值存储在一个数组中,并按照勾选顺序排列。例如,用户先选中子节点A,再选中父节点B,那么v-model的值应该是[[子路径], [父路径]],顺序保持不变。 但是,el-cascader的多选模式下,v-model的值默认是一个二维数组,每个元素是选中节点的路径数组。例如:[[一级1, 二级1, 三级1], [一级2, 二级2]]。这些值本身已经包含了层级信息,但它们的顺序可能按照层级排序,而不是用户勾选的顺序。 因此,关键在于如何让v-model中的数组顺序反映用户的勾选顺序,而不是组件内部的层级顺序。为了实现这一点,可能需要完全手动管理v-model的值,而不是依赖组件的自动更新。 可能的实现方法: 1. 设置el-cascader的v-model为一个空数组,并设置:emitPath为false(如果允许),但不确定是否适用。或者,禁用自动更新,手动控制。 或者: 1. 使用@change事件,当触发时,获取所有选中的节点(getCheckedNodes),然后按照用户勾选的顺序排列,并更新到v-model。 但如何确定这些节点的勾选顺序呢?因为getCheckedNodes返回的数组可能不是按照用户点击的顺序,而是按照组件内部的数据顺序排列的。 这时候可能需要自己记录用户的每一次勾选和取消操作。例如: - 当用户勾选一个节点时,将该节点的路径添加到selectedValues数组的末尾。 - 当用户取消勾选时,从selectedValues数组中移除对应的路径。 - 然后将selectedValues数组赋值给v-model。 但是如何捕获勾选和取消勾选的单个事件呢?Element UI的el-cascader是否有对应的事件? 查阅Element UI的文档,el-cascader的多选模式下,有change事件,当选中值变化时触发,参数是当前选中的值数组。还有一个expand-change事件,但可能不相关。此外,可能还有check事件,当用户勾选节点时触发,参数是被勾选的节点。但需要确认。 假设存在check事件,那么可以这样做: - 监听@check事件,当用户勾选一个节点时,将该节点的路径值添加到selectedValues数组中。 - 监听@uncheck事件(如果存在),当用户取消勾选时,从selectedValues数组中移除该节点的路径值。 - 将selectedValues数组作为v-model的值。 但问题在于,el-cascader可能没有提供@uncheck事件,或者无法直接获取到取消勾选的节点。这时候可能需要结合change事件来处理。 例如,每次change事件触发时,比较新旧选中的值,找出新增的值和移除的值,然后更新selectedValues数组的顺序。例如: - 维护一个selectedValues数组,保存当前按顺序排列的值。 - 当change事件触发时,获取新的值数组newValues。 - 比较newValues和selectedValues,找出新增的值,将它们按顺序添加到selectedValues的末尾;找出移除的值,将它们从selectedValues中删除。 - 这样,selectedValues数组会保持用户的操作顺序。 但这种方法可能存在问题,比如当用户同时勾选或取消多个节点时,无法准确判断顺序。但在大多数情况下,用户可能逐一点击,每次change事件触发时,只涉及一个节点的变化,这时可以准确记录顺序。 例如,初始时selectedValues是空的。用户勾选节点A,触发change事件,newValues是[A的路径],此时selectedValues更新为[A的路径]。接着用户勾选节点B,newValues是[A的路径, B的路径](假设组件默认按层级顺序排列),但此时如何判断用户点击的顺序?如果组件返回的newValues顺序是按数据层级排列的,而不是用户点击顺序,那么这种方法无法正确记录顺序。 这说明,仅仅依赖change事件可能不够,因为无法确定用户点击的顺序。这时候可能需要更底层的事件,比如每个节点的勾选事件。 查阅Element UI的文档,发现el-cascader在多选模式下,确实有一个check事件,当用户勾选一个节点时触发。这个事件的参数是被勾选的节点数据。因此,可以监听@check事件,每当触发时,将节点的路径值添加到selectedValues数组的末尾。同时,处理取消勾选的情况,可能需要监听节点移除的事件,但Element UI是否有对应的事件呢? 在Element UI中,可能没有直接的uncheck事件,但可以通过比较change事件前后的selectedValues数组来找出被移除的节点。例如,每次change事件触发时,保存当前的selectedValues数组,并与新的值数组进行比较,找出被移除的节点,然后从selectedValues中删除它们。 具体步骤如下: 1. 在data中定义selectedValues数组,用来存储按顺序排列的选中值。 2. 监听el-cascader的@check事件,当触发时,将勾选的节点路径添加到selectedValues数组。 3. 监听el-cascader的@change事件,当触发时,获取当前组件的选中值currentValues(可能通过v-model绑定或者ref获取)。 4. 比较currentValues和selectedValues,找出哪些值在currentValues中不存在于selectedValues,这些可能是由于组件内部逻辑自动添加的(比如父节点勾选导致子节点全部勾选),此时需要处理这些新增的值。但这种情况可能比较复杂,因为用户希望手动管理顺序。 5. 同时,需要处理取消勾选的情况,即找出哪些值在selectedValues中存在但不在currentValues中,这些需要从selectedValues中移除。 这种方法可能会比较复杂,因为需要处理组件内部自动勾选的情况,例如勾选父节点时自动勾选所有子节点。但用户的需求是严格按照用户点击的顺序传值,可能不需要考虑这种自动勾选的情况,或者希望禁用这种自动勾选行为。因此,可能需要设置checkStrictly为true,使得可以单独选择父节点和子节点。 根据引用[4],当checkStrictly为true时,可以选到父节点,但此时父节点勾选不会自动勾选子节点。这可能符合用户的需求,因为这样每次勾选都是用户明确的操作,不会有自动添加的节点。因此,可以结合checkStrictly和手动管理选中顺序。 综上,实现步骤可能如下: 1. 设置el-cascader的props.checkStrictly为true,允许独立选择任意层级的节点。 2. 监听@check事件,当用户勾选节点时,将节点的路径值添加到selectedValues数组末尾。 3. 监听@remove-tag事件(当多选模式下移除标签时触发),当用户移除一个标签时,从selectedValues数组中删除对应的值。 4. 将selectedValues数组作为v-model的值,确保顺序与勾选顺序一致。 但需要验证这些事件是否有效,并且如何获取节点的路径值。 例如,在@check事件中,事件参数是节点对象,节点对象可能有path属性,或者可以通过getNode的方法获取路径。根据引用[3],使用getCheckedNodes()[0].label可以获取标签,而节点对象可能包含path的信息,或者可以通过node.data获取节点的数据。 假设节点对象包含path属性,那么可以构造路径值。例如,每个节点的path属性是一个数组,包含从根到当前节点的value。因此,在@check事件处理函数中,可以将node.pathValues(假设)或者手动构造路径数组,添加到selectedValues中。 或者,在@check事件中,通过node.getPath()方法获取路径数组。需要查阅Element UI的文档确认节点对象的方法。 例如,Element UI的cascader节点对象可能有getPath()方法,返回从根节点到当前节点的节点数组。然后,可以从这些节点中提取value,构成路径数组。 假设在@check事件处理函数中,可以获取到节点的路径数组,那么可以将其添加到selectedValues数组中。同时,在@remove-tag事件中,当用户移除某个标签时,从selectedValues中删除对应的路径数组。 此外,需要将el-cascader的v-model绑定到selectedValues数组,但由于我们手动管理顺序,可能需要关闭组件的自动更新,或者每次更新时同步组件的选中状态。这可能会有冲突,因为如果手动修改selectedValues,组件会根据这个数组来显示选中的标签。因此,需要确保两者同步。 可能的代码实现: 在Vue组件中: <template> <el-cascader v-model="selectedValues" :options="options" :props="props" @check="handleCheck" @remove-tag="handleRemoveTag" multiple ></el-cascader> </template> <script> export default { data() { return { selectedValues: [], props: { checkStrictly: true, multiple: true, emitPath: true, // 确保值包含路径 // 其他props配置 }, options: [...] // 级联数据 }; }, methods: { handleCheck(node) { // 获取节点的路径值数组,例如node.valuePath const path = node.getPath().map(n => n.value); // 避免重复添加 if (!this.selectedValues.some(p => JSON.stringify(p) === JSON.stringify(path))) { this.selectedValues.push(path); } }, handleRemoveTag(tag) { // tag是移除的路径值数组 const index = this.selectedValues.findIndex(p => JSON.stringify(p) === JSON.stringify(tag)); if (index !== -1) { this.selectedValues.splice(index, 1); } } } }; </script> 这里假设node.getPath()返回节点路径的数组,每个节点有value属性。然后,将路径的value数组添加到selectedValues中。当用户移除标签时,通过@remove-tag事件获取被移除的tag值(即路径数组),从selectedValues中删除。 但需要注意,@remove-tag事件的参数是否是路径数组。根据Element UI文档,当多选模式下移除标签时,@remove-tag事件的参数是被移除的tag的值,即对应的路径数组,因此可以正确处理。 此外,需要确保emitPath设置为true,这样v-model的值才会是路径数组。同时,设置checkStrictly为true,允许独立选择节点,避免父节点勾选导致子节点自动勾选,从而干扰用户的勾选顺序。 这样,selectedValues数组将按照用户勾选的顺序来存储路径值,并且在移除时也会按顺序移除,从而实现了按勾选顺序传值的需求。 还需要测试这种实现方式是否有效,特别是在用户交互时,selectedValues数组是否能正确更新,并且el-cascader显示的标签顺序是否与selectedValues一致。因为el-cascader默认可能按照层级顺序排列标签,但通过手动控制v-model的值,可能可以覆盖默认顺序。 此外,如果用户需要回显时保持勾选顺序,那么selectedValues数组的正确维护就很重要。在组件初始化时,如果需要回显已选中的值,需要确保selectedValues数组的顺序与之前保存的顺序一致。 总结,关键步骤包括: 1. 设置checkStrictly为true,允许独立勾选节点。 2. 使用@check事件捕获勾选动作,按顺序添加路径值。 3. 使用@remove-tag事件捕获取消勾选动作,按顺序移除路径值。 4. 绑定v-model到手动维护的selectedValues数组,确保顺序正确。 这样,用户就可以按照勾选的顺序传递值了。同时,需要注意在回显时,selectedValues数组的格式必须与el-cascader预期的格式一致,即每个元素是路径数组,如[[一级, 二级], [一级, 三级]]。</think>在Vue中实现$el-cascader$级联选择器按勾选顺序传值,可通过以下步骤实现: ### 一、核心实现原理 通过监听组件的**勾选事件**和**移除标签事件**,手动维护选中值的顺序数组。需设置$checkStrictly: true$解除层级约束,配合$getCheckedNodes$方法获取完整节点信息[^2][^3]。 ### 二、具体实现代码 ```vue <template> <el-cascader v-model="selectedPaths" :options="options" :props="cascaderProps" @check="handleNodeCheck" @remove-tag="handleTagRemove" multiple ref="cascaderRef" ></el-cascader> </template> <script> export default { data() { return { selectedPaths: [], // 按勾选顺序存储路径值 cascaderProps: { checkStrictly: true, // 允许独立勾选节点[^4] emitPath: true, // 返回完整路径 multiple: true, label: 'label', value: 'value', children: 'children' }, options: [/* 级联数据 */] } }, methods: { // 勾选节点时触发 handleNodeCheck(checkedNode) { const path = checkedNode.getPath().map(n => n.value) const exists = this.selectedPaths.some(p => JSON.stringify(p) === JSON.stringify(path) ) if (!exists) { this.selectedPaths = [...this.selectedPaths, path] } }, // 移除标签时触发 handleTagRemove(removedPath) { this.selectedPaths = this.selectedPaths.filter(p => JSON.stringify(p) !== JSON.stringify(removedPath) ) } } } </script> ``` ### 三、关键配置说明 1. **checkStrictly模式**:解除父子节点关联,实现自由勾选 2. **emitPath配置**:返回完整路径值而非末级值[^1] 3. **事件监听机制**: - @check:精确捕获每次勾选动作 - @remove-tag:精确捕获每次移除动作 4. **路径值对比**:使用JSON序列化解决数组比对问题 ### 四、补充说明 通过$this.$refs.cascaderRef.getCheckedNodes()$可获取包含层级关系的节点集合,用于需要同时保留顺序和层级信息的场景[^3]。若需要展示自定义顺序的标签,可通过CSS样式覆盖默认排序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值