Skip to content
On this page

级联选择 Cascader

通用的级联选择器

基础用法

默认 click 触发子菜单
hover 触发子菜单
选项值
[]
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">默认 click 触发子菜单</span>
      <b-cascader v-model="selected" :options="options" @change="handleChange"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">hover 触发子菜单</span>
      <b-cascader
        v-model="selected"
        :options="options"
        :props="{ expandTrigger: 'hover' }"
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">选项值</span>
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">默认 click 触发子菜单</span>
      <b-cascader v-model="selected" :options="options" @change="handleChange"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">hover 触发子菜单</span>
      <b-cascader
        v-model="selected"
        :options="options"
        :props="{ expandTrigger: 'hover' }"
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">选项值</span>
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>

禁用状态

设置disabled来控制禁用

禁用项
全部禁用
选项值
[]
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">禁用项</span>
      <b-cascader v-model="selected" :options="options" @change="handleChange"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">全部禁用</span>
      <b-cascader
        v-model="selected"
        :options="options"
        disabled
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">选项值</span>
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    disabled: true,
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">禁用项</span>
      <b-cascader v-model="selected" :options="options" @change="handleChange"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">全部禁用</span>
      <b-cascader
        v-model="selected"
        :options="options"
        disabled
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">选项值</span>
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    disabled: true,
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>

可以清空

可以清空选择

[]
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader
        v-model="selected"
        :options="options"
        clearable
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader
        v-model="selected"
        :options="options"
        clearable
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>

显示最后一级

输入框可设置只显示最后一级标签

[]
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader
        v-model="selected"
        :options="options"
        clearable
        :show-all-levels="false"
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader
        v-model="selected"
        :options="options"
        clearable
        :show-all-levels="false"
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>

多选模式

可以设置props.multiple来开启多选

默认 显示所有tag
折叠显示tag
选项值
[]
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">默认 显示所有tag</span>
      <b-cascader
        v-model="selected"
        :options="options"
        :props="{ multiple: true }"
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">折叠显示tag</span>
      <b-cascader
        v-model="selected"
        :options="options"
        :props="{ multiple: true }"
        collapse-tags
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: calc(100% - 500px); margin-right: 20px">
      <span class="demonstration">选项值</span>
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">默认 显示所有tag</span>
      <b-cascader
        v-model="selected"
        :options="options"
        :props="{ multiple: true }"
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">折叠显示tag</span>
      <b-cascader
        v-model="selected"
        :options="options"
        :props="{ multiple: true }"
        collapse-tags
        @change="handleChange"
      ></b-cascader>
    </div>
    <div class="block" style="width: calc(100% - 500px); margin-right: 20px">
      <span class="demonstration">选项值</span>
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>

选择任意一级选项

在单选模式下,你只能选择叶子节点;而在多选模式下,勾选父节点真正选中的都是叶子节点。启用该功能后,可让父子节点取消关联,选择任意一级选项

可通过 props.checkStrictly = true 来设置父子节点取消选中关联,从而达到选择任意一级选项的目的。

单选选择任意一级选项
[]
多选选择任意一级选项
[]
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">单选选择任意一级选项</span>
      <b-cascader
        v-model="selected1"
        :options="options"
        :props="{ checkStrictly: true }"
        @change="handleChange"
      ></b-cascader>
      <div class="mt-5">{{ selected1 }}</div>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">多选选择任意一级选项</span>
      <b-cascader
        v-model="selected2"
        :options="options"
        :props="{ multiple: true, checkStrictly: true }"
        collapse-tags
        @change="handleChange"
      ></b-cascader>
      <div class="mt-5">{{ selected2 }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected1 = ref([])
const selected2 = ref([])

function handleChange(value) {
  console.log(value)
}
</script>
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">单选选择任意一级选项</span>
      <b-cascader
        v-model="selected1"
        :options="options"
        :props="{ checkStrictly: true }"
        @change="handleChange"
      ></b-cascader>
      <div class="mt-5">{{ selected1 }}</div>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">多选选择任意一级选项</span>
      <b-cascader
        v-model="selected2"
        :options="options"
        :props="{ multiple: true, checkStrictly: true }"
        collapse-tags
        @change="handleChange"
      ></b-cascader>
      <div class="mt-5">{{ selected2 }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected1 = ref([])
const selected2 = ref([])

function handleChange(value) {
  console.log(value)
}
</script>

动态加载

选中某一级时,动态加载之下的选项, 通过lazy开启动态加载,并通过lazyload来设置加载数据源的方法

lazyload方法有两个参数,第一个参数node为当前点击的节点,第二个resolve为数据加载完成的回调(必须调用)。为了更准确的显示节点的状态,还可以对节点数据添加是否为叶子节点的标志位 ( 默认字段为leaf,可通过props.leaf修改),否则会简单的以有无子节点来判断是否为叶子节点。

[]
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader v-model="selected" :props="props"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

let id = 0

const selected = ref([])
const props = {
  lazy: true,
  lazyLoad(node, resolve) {
    const { level } = node
    setTimeout(() => {
      const nodes = Array.from({ length: level + 1 }).map(() => ({
        value: ++id,
        label: `选项${id}`,
        leaf: level >= 2
      }))
      // 通过调用resolve将子节点数据返回,通知组件数据加载完成
      resolve(nodes)
    }, 1000)
  }
}
</script>
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader v-model="selected" :props="props"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

let id = 0

const selected = ref([])
const props = {
  lazy: true,
  lazyLoad(node, resolve) {
    const { level } = node
    setTimeout(() => {
      const nodes = Array.from({ length: level + 1 }).map(() => ({
        value: ++id,
        label: `选项${id}`,
        leaf: level >= 2
      }))
      // 通过调用resolve将子节点数据返回,通知组件数据加载完成
      resolve(nodes)
    }, 1000)
  }
}
</script>

可搜索

可以快捷地搜索选项并选择,将filterable赋值为true即可打开搜索功能,默认会匹配节点的label或所有父节点的label(由show-all-levels决定)中包含输入值的选项。

你也可以用filter-method自定义搜索逻辑,接受一个函数,第一个参数是节点node,第二个参数是搜索关键词keyword,通过返回布尔值表示是否匹配

单选可搜索
[]
多选可搜索
[]
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">单选可搜索</span>
      <b-cascader
        v-model="selected1"
        placeholder="试试搜索:鼓楼"
        :options="options"
        filterable
      ></b-cascader>
      <div class="mt-5">{{ selected1 }}</div>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">多选可搜索</span>
      <b-cascader
        v-model="selected2"
        placeholder="试试搜索:鼓楼"
        :options="options"
        :props="{ multiple: true }"
        collapse-tags
        filterable
        :filter-method="filterMethod"
      ></b-cascader>
      <div class="mt-5">{{ selected2 }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected1 = ref([])
const selected2 = ref([])

function filterMethod(node, keyword) {
  return node.label.includes(keyword) && node.parent && node.parent.label === '徐州'
}
</script>
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">单选可搜索</span>
      <b-cascader
        v-model="selected1"
        placeholder="试试搜索:鼓楼"
        :options="options"
        filterable
      ></b-cascader>
      <div class="mt-5">{{ selected1 }}</div>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <span class="demonstration">多选可搜索</span>
      <b-cascader
        v-model="selected2"
        placeholder="试试搜索:鼓楼"
        :options="options"
        :props="{ multiple: true }"
        collapse-tags
        filterable
        :filter-method="filterMethod"
      ></b-cascader>
      <div class="mt-5">{{ selected2 }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected1 = ref([])
const selected2 = ref([])

function filterMethod(node, keyword) {
  return node.label.includes(keyword) && node.parent && node.parent.label === '徐州'
}
</script>

自定义选项

可以自定义选项的内容 , scoped slot会传入两个字段 node 和 data,分别表示当前节点的 Node 对象和数据。

[]
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader :options="options">
        <template #default="{ node, data }">
          <span>{{ data.label }}</span>
          <span v-if="!node.isLeaf">({{ data.children.length }})</span>
        </template>
      </b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader :options="options">
        <template #default="{ node, data }">
          <span>{{ data.label }}</span>
          <span v-if="!node.isLeaf">({{ data.children.length }})</span>
        </template>
      </b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])

function handleChange(value) {
  console.log(value)
}
</script>

不同尺寸

<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader :options="options" size="large"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader :options="options"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader :options="options" size="small"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader :options="options" size="mini"></b-cascader>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
</script>
<template>
  <div flex>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader :options="options" size="large"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader :options="options"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader :options="options" size="small"></b-cascader>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <b-cascader :options="options" size="mini"></b-cascader>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
</script>

级联面板

可以不采用popper弹窗的面板显示。与级联选择器一样使用

[]
<template>
  <div flex>
    <div class="block" style="margin-right: 20px">
      <b-cascader-panel v-model="selected" :options="options"></b-cascader-panel>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])
</script>
<template>
  <div flex>
    <div class="block" style="margin-right: 20px">
      <b-cascader-panel v-model="selected" :options="options"></b-cascader-panel>
    </div>
    <div class="block" style="width: 220px; margin-right: 20px">
      <div class="mt-5">{{ selected }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const options = [
  {
    value: 'nanjing',
    label: '南京',
    children: [
      {
        value: 'xuanwu',
        label: '玄武区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'jianye',
        label: '建邺区'
      }
    ]
  },
  {
    value: 'xuzhou',
    label: '徐州',
    children: [
      {
        value: 'tongshan',
        label: '铜山区'
      },
      {
        value: 'gulou',
        label: '鼓楼区'
      },
      {
        value: 'yunlong',
        label: '云龙区',
        children: [
          { value: 'dalonghu', label: '大龙湖街道' },
          { value: 'guozhuanglu', label: '郭庄路街道' },
          { value: 'lvdi', label: '绿地商务城' },
          { value: 'jinlonghu', label: '金龙湖街道' }
        ]
      },
      {
        value: 'jiawang',
        label: '贾汪区'
      },
      { value: 'peixian', label: '沛县' },
      { value: 'fengxian', label: '丰县' },
      { value: 'pizhou', label: '邳州市' },
      { value: 'xinyi', label: '新沂市' }
    ]
  }
]
const selected = ref([])
</script>

Cascader Props

参数说明类型可选值默认值
value / v-model选中项绑定值-
options可选项数据源,键名可通过 Props 属性配置array
props配置选项,具体见下表object
size尺寸stringmedium / small / mini
placeholder输入框占位文本string请选择
disabled是否禁用booleanfalse
clearable是否支持清空选项booleanfalse
show-all-levels输入框中是否显示选中值的完整路径booleantrue
collapse-tags多选模式下是否折叠Tagboolean-false
separator选项分隔符string斜杠' / '
filterable是否可搜索选项boolean
filter-method自定义搜索逻辑,第一个参数是节点node,第二个参数是搜索关键词keyword,通过返回布尔值表示是否命中function(node, keyword)--
debounce搜索关键词输入的去抖延迟,毫秒number300
before-filter筛选之前的钩子,参数为输入的值,若返回 false 或者返回 Promise 且被 reject,则停止筛选function(value)
popper-class自定义浮层类名string

Cascader Events

事件名称说明回调参数
change当选中节点变化时触发选中节点的值
expand-change当展开节点发生变化时触发各父级选项值组成的数组
blur当失去焦点时触发(event: Event)
focus当获得焦点时触发(event: Event)
visible-change下拉框出现/隐藏时触发出现则为 true,隐藏则为 false
remove-tag在多选模式下,移除Tag时触发移除的Tag对应的节点的值

Cascader Methods

方法名说明参数
getCheckedNodes获取选中的节点(leafOnly) 是否只是叶子节点,默认值为 false

Cascader Slots

名称说明
-自定义备选项的节点内容,参数为 { node, data },分别为当前节点的 Node 对象和数据
empty无匹配选项时的内容

CascaderPanel Attributes

参数说明类型可选值默认值
value / v-model选中项绑定值-
options可选项数据源,键名可通过 Props 属性配置array
props配置选项,具体见下表object

CascaderPanel Events

事件名称说明回调参数
change当选中节点变化时触发选中节点的值
expand-change当展开节点发生变化时触发各父级选项值组成的数组

CascaderPanel Methods

方法名说明参数
getCheckedNodes获取选中的节点数组(leafOnly) 是否只是叶子节点,默认值为 false
clearCheckedNodes清空选中的节点-

CascaderPanel Slots

名称说明
-自定义备选项的节点内容,参数为 { node, data },分别为当前节点的 Node 对象和数据

Props

参数说明类型可选值默认值
expandTrigger次级菜单的展开方式stringclick / hover'click'
multiple是否多选boolean-false
checkStrictly是否严格的遵守父子节点不互相关联boolean-false
emitPath在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值boolean-true
lazy是否动态加载子节点,需与 lazyLoad 方法结合使用boolean-false
lazyLoad加载动态数据的方法,仅在 lazy 为 true 时有效function(node, resolve),node为当前点击的节点,resolve为数据加载完成的回调(必须调用)--
value指定选项的值为选项对象的某个属性值string'value'
label指定选项标签为选项对象的某个属性值string'label'
children指定选项的子选项为选项对象的某个属性值string'children'
disabled指定选项的禁用为选项对象的某个属性值string'disabled'
leaf指定选项的叶子节点的标志位为选项对象的某个属性值string'leaf'