Vue2级联选择(Cascader)

40 篇文章 3 订阅
38 篇文章 5 订阅

Vue3级联选择(Cascader)

Vue2选择器(Select)为基础实现的级联选择组件

可自定义设置以下属性:

  • 可选项数据源(options),类型:Array<any>,默认 []

  • (v-model)级联选中项(selectedValue),类型:Array<number|string>,默认[]

  • 下拉字典项的文本字段名(label),类型:string,默认 'label'

  • 下拉字典项的值字段名(value),类型:string,默认 'value'

  • 下拉字典项的后代字段名(children),类型:string,默认 'children'

  • 当此项为true时,点选每级菜单选项值(v-model)都会发生变化;否则只有选择三级选项后选项值才会变化(changeOnSelect),类型:boolean,默认 false

  • 下拉层级(zIndex),类型:number,默认 1

  • 级联下拉框相互间隙宽度,类型:number,单位px,默认 8px

  • 三级下拉各自宽度(width),类型:number|number[],默认 160

  • 下拉框高度(height),类型:number,单位px,默认 36px

  • 三级各自是否禁用(disabled),类型:boolean|boolean[],默认 false

  • 三级下拉各自占位文本(placeholder),类型:string|string[],默认 '请选择'

  • 下拉面板最多能展示的下拉项数,超过后滚动显示(num),类型:number,默认 6

效果如下图:

①创建级联下拉选择器Cascader.vue:

<template>
  <div class="m-cascader-wrap" :style="`height: ${height}px;`">
    <VueAmazingSelector
      :style="`margin-right: ${gap}px; z-index: ${zIndex};`"
      :options="firstOptions"
      v-model="selectedValue[0]"
      :label="label"
      :value="value"
      :disabled="disabled"
      :width="Array.isArray(width) ? width[0] : width"
      :height="height"
      :num="num"
      :placeholder="Array.isArray(placeholder) ? placeholder[0] : placeholder"
      @change="onFirstChange" />
    <VueAmazingSelector
      :style="`margin-right: ${gap}px; z-index: ${zIndex};`"
      :options="secondOptions"
      v-model="selectedValue[1]"
      :label="label"
      :value="value"
      :disabled="disabled"
      :width="Array.isArray(width) ? width[1] : width"
      :height="36"
      :num="num"
      :placeholder="Array.isArray(placeholder) ? placeholder[1] : placeholder"
      @change="onSecondChange" />
    <VueAmazingSelector
      :style="`z-index: ${zIndex};`"
      :options="thirdOptions"
      v-model="selectedValue[2]"
      :label="label"
      :value="value"
      :disabled="disabled"
      :width="Array.isArray(width) ? width[2] : width"
      :height="height"
      :num="num"
      :placeholder="Array.isArray(placeholder) ? placeholder[2]:placeholder"
      @change="onThirdChange" />
  </div>
</template>
<script>
// yarn add VueAmazingSelector
import { VueAmazingSelector } from 'vue-amazing-selector'
export default {
  name: 'Cascader',
  components: {
    VueAmazingSelector
  },
  model: {
    prop: 'selectedValue',
    event: 'model'
  },
  props: {
    options: { // 可选项数据源
      type: Array,
      default: () => []
    },
    selectedValue: { // (v-model)级联选中项
      type: Array,
      default: () => []
    },
    label: { // 下拉字典项的文本字段名
      type: String,
      default: 'label'
    },
    value: { // 下拉字典项的值字段名
      type: String,
      default: 'value'
    },
    children: { // 下拉字典项的后代字段名
      type: String,
      default: 'children'
    },
    changeOnSelect: { // 当此项为true时,点选每级菜单选项值(v-model)都会发生变化;否则只有选择三级选项后选项值才会变化
      type: Boolean,
      default: false
    },
    zIndex: { // 下拉层级
      type: Number,
      default: 1
    },
    gap: { // 级联下拉框相互间隙宽度,单位px,默认8px
      type: Number,
      default: 8
    },
    width: { // 三级下拉各自宽度
      type: [Number, Array],
      default: 160
    },
    height: { // 下拉框高度
      type: Number,
      default: 36
    },
    disabled: { // 统一是否全部禁用
      type: Boolean,
      default: false
    },
    placeholder: { // 三级下拉各自占位文本
      type: [String, Array],
      default: '请选择'
    },
    num: { // 下拉面板最多能展示的下拉项数,超过后滚动显示
      type: Number,
      default: 6
    }
  },
  data () {
    return {
      values: this.selectedValue,
      labels: [],
      firstOptions: this.options,
      secondOptions: [],
      thirdOptions: []
    }
  },
  watch: {
    selectedValue (to) {
      this.values = to
      if (to.length) {
        this.initCascader(to)
        this.initLabels(to)
      }
    }
  },
  mounted () {
    if (this.selectedValue.length) {
      this.initCascader(this.selectedValue)
      this.initLabels(this.selectedValue)
    }
  },
  methods: {
    findChildren (options, index) {
      const len = options.length
      for (let i = 0; i < len; i++) {
        if (options[i][this.value] === this.selectedValue[index]) {
          return options[i][this.children] || []
        }
      }
      return []
    },
    initCascader (selectedValue) {
      this.secondOptions = this.findChildren(this.firstOptions, 0)
      this.thirdOptions = []
      if (selectedValue.length > 1) {
        this.thirdOptions = this.findChildren(this.secondOptions, 1)
      }
    },
    findLabel (options, index) {
      const len = options.length
      for (let i = 0; i < len; i++) {
        if (options[i][this.value] === this.selectedValue[index]) {
          return options[i][this.label]
        }
      }
      return this.selectedValue[index]
    },
    initLabels (selectedValue) {
      this.labels[0] = this.findLabel(this.firstOptions, 0)
      if (selectedValue.length > 1) {
        this.labels[1] = this.findLabel(this.secondOptions, 1)
      }
      if (selectedValue.length > 2) {
        this.labels[2] = this.findLabel(this.thirdOptions, 2)
      }
    },
    onFirstChange (value, label, index) { // 一级下拉回调
      this.values = [value]
      this.labels = [label]
      if (this.changeOnSelect) {
        this.$emit('model', this.values)
        this.$emit('change', this.values, this.labels)
      }
      // 获取二级下拉选项
      this.secondOptions = this.firstOptions[index][this.children] || []
      this.thirdOptions = []
    },
    onSecondChange (value, label, index) { // 二级下拉回调
      this.values = [this.values[0], value]
      this.labels = [this.labels[0], label]
      if (this.changeOnSelect) {
        this.$emit('model', this.values)
        this.$emit('change', this.values, this.labels)
      }
      // 获取三级下拉选项
      this.thirdOptions = this.secondOptions[index][this.children] || []
    },
    onThirdChange (value, label) { // 三级下拉回调
      this.values[2] = value
      this.labels[2] = label
      this.$emit('model', this.values)
      this.$emit('change', this.values, this.labels)
    }
  }
}
</script>
<style lang="less" scoped>
.m-cascader-wrap {
  display: inline-block;
}
</style>

②在要使用的页面引入:

<template>
  <div class="selector">
    <Cascader
      v-model="selectedValue"
      label="label"
      value="value"
      children="children"
      changeOnSelect
      :options="options"
      :zIndex="9"
      :gap="8"
      :provinceWidth="120"
      :cityWidth="120"
      :areaWidth="120"
      :width="120"
      :height="36"
      :provinceDisabled="false"
      :cityDisabled="false"
      :disabled="false"
      :num="6"
      @change="onChange" />
  </div>
</template>
<script>
import Cascader from '@/components/Cascader'
export default {
  name: 'Selector',
  components: {
    Cascader
  },
  data () {
    return {
      options: [
        {
          value: '1',
          label: '北京',
          children: [
            {
              value: '11',
              label: '北京市',
              children: [
                {
                  value: '111',
                  label: '东城区'
                },
                {
                  value: '112',
                  label: '西城区'
                }
              ]
            }
          ]
        },
        {
          value: '2',
          label: '浙江',
          children: [
            {
              value: '21',
              label: '杭州市',
              children: [
                {
                  value: '211',
                  label: '西湖区'
                },
                {
                  value: '212',
                  label: '余杭区'
                }
              ]
            },
            {
              value: '22',
              label: '湖州市',
              children: [
                {
                  value: '221',
                  label: '吴兴区'
                },
                {
                  value: '222',
                  label: '安吉区'
                }
              ]
            }
          ]
        }
      ],
      selectedValue: []
    }
  },
  watch: {
    selectedValue (to) {
      console.log('selectedValue:', to)
    }
  },
  mounted () {
    setTimeout(() => {
      this.selectedValue = ['1', '11', '112']
    }, 1000)
  },
  methods: {
    onChange (value, label) {
      console.log('value:', value)
      console.log('label:', label)
    }
  }
}
</script>
<style lang="less" scoped>
</style>
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
Vue动态级联选择器是一种常见的前端交互组件,它可以根据用户的选择动态加载相关数据并实现级联效果。在Vue中,可以使用一些库或组件来实现这样的功能,比如element-ui、vue-cascader等。 下面是一个使用element-ui库实现Vue动态级联选择器的简单示例: 1. 首先,确保你已经安装了element-ui库。可以通过npm或yarn进行安装: ```bash npm install element-ui ``` 或 ```bash yarn add element-ui ``` 2. 在Vue的入口文件(一般是main.js)中引入element-ui和相关样式: ```javascript import Vue from 'vue'; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI); ``` 3. 在组件中使用el-cascader组件实现动态级联选择器: ```vue <template> <div> <el-cascader v-model="selectedOptions" :options="options" @change="handleCascadeChange" ></el-cascader> </div> </template> <script> export default { data() { return { options: [], // 存储级联选择器的选项数据 selectedOptions: [] // 存储用户选择的值 }; }, methods: { handleCascadeChange(value) { // 根据用户选择的值加载相关数据并更新选项 // 可以通过异步请求、本地数据或其他方式获取数据 // 更新options的值,以实现级联效果 } } }; </script> ``` 以上是一个简单的示例,你可以根据实际需求进行修改和扩展。在`handleCascadeChange`方法中,你可以根据用户选择的值来请求后端数据,更新`options`的值,以实现级联效果。 希望以上信息对您有所帮助!如有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值