Skip to content

Cascader 级联选择器 1.0.9

手机扫码预览
13:03

组件名:rice-cascader

级联选择 用于多层级数据的选择。注:1.0.9版本开始支持

注意

1.1.0 版本起,修改判断逻辑:当配置项 options 最末层级的 children 为空数组或不存在时,点击选项将触发 finish 事件,表示所有选项已选择完毕。之前的版本仅校验 children 是否为 null,未对空数组做判断。

平台兼容性

uni-app x

AndroidiOSHarmonyOSHarmonyOS(Vapor)微信小程序h5
√(1.1.0+)

基础用法

  • 通过 options 参数设置数据源, options 的数据格式为 CascaderOption;
  • 通过 v-model 绑定选中项的值;
  • 通过 v-model:show 控制 Cascader 的显示与否(仅在usePopuptrue的情况下生效);
html
<rice-cascader v-model="value" v-model:show="show" title="选择地区" :options="options"
 @change="onChange"
 @finish="onFinish"
 @clickDisabled="onClickDisabled"/>
ts
import { CascaderOption, CascaderEvent, CascaderClickDisabledEvent } from "@/uni_modules/rice-ui"
const show = ref(false)
const value = ref('')
const valueText = ref("")
const options = ref<CascaderOption[]>([
  {
    text: '浙江省',
    value: 'zhejiang',
    children: [
      { text: '杭州市', value: 'hangzhou', children: [{ text: '上城区', value: 'shangcheng' }, { text: '西湖区', value: 'xihua' }] },
      { text: '宁波市', value: 'ningbo', children: [{ text: '北仑', value: 'beilun' }] }
    ] as CascaderOption[],
  },
  {
    text: '江苏省',
    value: 'jiangsu',
    children: [{ text: '南京市', value: 'nanjing', children: [{ text: '玄武区', value: 'xuanwu' }, { text: '雨花台区', value: 'yuhuatai' }] }, { text: '苏州', value: 'sunzhou' }] as CascaderOption[],
  }, {
    text: '广西壮族自治区',
    value: 'guangxi',
    children: [{ text: '柳州市', value: 'liuzhou' }, { text: '桂林市', value: 'guiling', disabled: true }] as CascaderOption[],
  }])

const onChange = (e : CascaderEvent) => {
  console.log('onChange', e)
}

const onFinish = (e : CascaderEvent) => {
  console.log('onFinish', e)
  uni.showToast({
    title: `选择完成了-${e.value}`,
    icon: 'none'
  })
  valueText.value = e.selectedOptions.map(v => v.text).join('/')
}

const onClickDisabled = (e : CascaderClickDisabledEvent) => {
  console.log('onClickDisabled', e)
  uni.showToast({
    title: `点击了禁用项-${e.option.value}`,
    icon: 'none'
  })
}

默认选中

通过 v-model 双向绑定选中的value

html
<rice-cascader v-model="value2" v-model:show="show2" :options="options" title="默认选中"></rice-cascader>
<script setup>
  const value2=ref('xihua')
</script>

自定义颜色和大小

  • 通过 active-color 属性设置选中状态下的文字颜色
  • 通过 color 属性设置未选中状态下的文字颜色
  • 通过 font-size 属性设置文字的大小
html
<rice-cascader v-model:show="show3" :options="options"
 active-color="#07c160"
 :color="themeState.isDark?'#fff':'#000'"
 font-size="17px"
 title="自定义颜色" />

异步加载

close-on-finish 设为 false,再监听 finish 事件自行加载远程数据,这种方式children需要设置为null 或不传

html
<rice-cascader v-model:show="show4" :options="options2" title="异步加载" :close-on-finish="false" 
@finish="onFinish4" />
ts
const show4 = ref(false)
	const options2 = ref<CascaderOption[]>([{
		text: '浙江省',
		value: 'zhejiang',
	},
	{
		text: '江苏省',
		value: 'jiangsu',
	},
	{
		text: '福建省',
		value: 'fujian',
	}, {
		text: '广西壮族自治区',
		value: 'guangxi',
	}])
	const onFinish4 = (e : CascaderEvent) => {
		if (e.tabIndex == 1) {
			uni.showToast({
				title: `选择完成了-${e.selectedOptions.map(v => v.text).join('/')}`,
				icon: 'none'
			})
			show4.value = false
			return
		}

		uni.showLoading({
			title: '加载中…',
			mask: true,
		})
		//模拟异步请求数据
		setTimeout(() => {
			const value = e.selectedOptions[0].value
			if (value == 'zhejiang') {
				options2.value[0].children = [
					{ text: '杭州市', value: 'hangzhou' },
				] as CascaderOption[]
			} else if (value == 'jiangsu') {
				options2.value[1].children = [
					{ text: '南京市', value: 'nanjing' }
				] as CascaderOption[]
			} else if (value == 'fujian') {
				//假设请求完成后数据为空
				options2.value[2].children = null
				show4.value = false
			}
			uni.hideLoading()
		}, 500)


	}

中国省市区数据

很多时候我们拿到的数据格式不一定是CascaderOption 类型,那么就要手动转为 CascaderOption 类型了,因为uniappx是有严格的类型校验的。

html
<rice-cascader v-model="value" v-model:show="show5" title="省市区数据"
  :options="areaList"
  :placeholder="`请选择${getText(tabIndex5)}`"
  @change="onChange5"/>
ts
import { CascaderOption ,CascaderEvent} from "@/uni_modules/rice-ui"
let transformAreaData : ((list : AreaData[]) => CascaderOption[]) | null = null

transformAreaData = (list : AreaData[]) => {
  const result = list.map(item => {
    const children = item['children'] as AreaData[] | null
    return {
      value: item.code,
      text: item.name,
      extend: { code: item.code },
      children: (children != null && children.length > 0) ? transformAreaData!(children) : null
    } as CascaderOption
  })
  return result
}

// 假设area为后端返回的数据
areaList.value = [transformAreaData!(area!)] as CascaderOption[]

// 设置placeholder
const tabIndex5=ref(0)
const onChange5 = (e : CascaderEvent) => {
  tabIndex5.value = e.tabIndex + 1
}

const getText = (index : number) => {
  if (index == 0) return '省份'
  if (index == 1) return '城市'
  return '区县'
}

全部选择完成后不关闭

通过 close-on-finish 属性可以设置 选择完成后不关闭 popup,一般用于数据校验,可以通过optionsBottom 插槽自行控制关闭的时机,校验成功后再通过v-model:show绑定的值手动关闭。

html
<rice-cascader v-model:show="show6" :options="areaList" title="选择完成后不关闭" :close-on-finish="false"
  :close-on-click-overlay="false" close-icon="clear-fill" ref="cascaderRef">
  <template #optionsBottom="{tabIndex}">
    <view class="options-bottom">
      <rice-button type="primary" shape="round" :text="`选择完成-${getText(tabIndex)}`" @click="sure"></rice-button>
    </view>
  </template>
</rice-cascader>

<script setup>
const show6 = ref(false)
const valueText6 = ref("")
const cascaderRef = ref<RiceCascaderComponentPublicInstance | null>(null)
const sure = () => {
  const value = cascaderRef.value!.getSelectedOptions() as CascaderOption[]
  valueText6.value = value.map(v => v.text).join('/')
  show6.value = false
}
</script>

自定义选项上方内容

通过 optionsTop 插槽可以自定义选项上方内容

html
<rice-cascader v-model:show="show7" title="自定义选项上方内容" :options="areaList">
  <template #optionsTop="{tabIndex}">
    <text class="options-tip">请选择{{getText(tabIndex)}}</text>
  </template>
</rice-cascader>

不使用popup

use-popup 设置为 false 即可不依赖 popup,如果想要全页面展示,可以通过custom-style 设置 高度或者 flex:1

html
<rice-cascader v-model="value2" title="" :use-popup="false" :closeable="false" :options="options"/>

API

Props

属性名类型说明默认值
v-model:show/showboolean是否显示,usePopuptrue时生效false
v-model/model-valueString|Number绑定的数据-
optionsCascaderOption[]可选项的数据[]
titleString顶部栏标题-
title-alignString标题对齐方式,可选值:center、leftcenter
placeholderString未选中时的提示文字请选择
colorString选项文字颜色-
active-colorString选中状态下的文字颜色-
font-sizeString|Number选项文字大小16px
closeableBoolean是否显示关闭按钮true
close-iconString关闭按钮的图标cross
borderBoolean选项是否显示下边框false
use-popupBoolean是否使用popuptrue
close-on-finishBoolean全部选项选择完成后是否关闭popup,是否全部选择完成判断的条件是childrennulltrue
close-on-click-closeBoolean点击关闭按钮是否关闭popuptrue
close-on-click-overlayBoolean点击遮罩层是否关闭popuptrue
safe-area-inset-bottomBoolean是否开启底部安全区适配usePopuptrue 时默认开启
z-indexNumberzIndex 层级999
custom-styleObject自定义style-

CascaderOption 数据结构

键名说明类型
text选项文字(必填)String
value选项对应的值(必填,且不能重复)String|Number
disabled是否禁用Boolean
children子选择列表,为null或不传时表示没有下一级CascaderOption[]
extend自定义扩展字段,可以在 changefinish 事件回调中获取any

Events

事件名说明回调参数
change选中项变化时触发(value:CascaderEvent)
finish全部选项选择完成后触发,判断依据是childrennull 或不传(value:CascaderEvent)
clickDisabled点击禁用的选项时触发(value:CascaderClickDisabledEvent)
clickClose点击关闭图标时触发-
open打开时触发-
close关闭时触发-
opened打开动画结束时触发-
closed关闭动画结束时触发-

方法

通过 ref 可以获取到 Cascader 实例并且调用实例的方法

方法名说明返回值
getSelectedOptions获取当前选中项的集合CascaderOption[]

调用方法示例

ts
const cascaderRef = ref<RiceCascaderComponentPublicInstance | null>(null)
//需确保cascaderRef.value不为null的情况下才能使用 "!."
const value = cascaderRef.value!.getSelectedOptions() as CascaderOption[]

Slots 插槽

名称说明参数
optionsTop选项上方区域tabIndex : number
optionsBottom选项下方区域tabIndex : number

类型定义

组件导出如下类型

ts
//options的参数类型
type CascaderOption = {
	text : string,
	value : string | number,
	disabled ?: boolean,
	children ?: CascaderOption[], //子项,为null或不传时表示没有下一级
	extend ?: any | null,
}

//选中项变化/选择完成时的参数类型
type CascaderEvent = {
	value : string | number, //选项对应的值
	selectedOptions : CascaderOption[], //选中的选项集合
	tabIndex : number, // 当前tab的索引值
}

//点击禁用的选项时的参数类型 
type CascaderClickDisabledEvent = {
	option : CascaderOption, //当前点击的项
	tabIndex : number, //tab索引值
}

type CascaderTitleAlign = 'left' | 'center'

组件类型

ts
// 组件类型
const cascaderRef = ref<RiceCascaderComponentPublicInstance | null>(null)