赞
踩
目前Vue Element的 el-cascader 级联选择器,多选或者选择任意一级,需要点击左侧的checkbox才能选中。
目标:点击label选中,已选中状态再次点击label取消选中
有两种方式实现
- <!-- 改造前 -->
-
- <template>
- <div>
- <el-cascader
- v-model="cascaderValue"
- :options="options"
- :props="{ multiple: true,checkStrictly:true }"
- clearable>
- </el-cascader>
- {{cascaderValue}}
- </div>
- </template>
改造点
多选
- <!-- 改造后 -->
-
- <template>
- <div>
- <el-cascader
- v-model="cascaderValue"
- :options="options"
- :props="{ multiple: true,checkStrictly:true }"
- clearable>
- <!-- 重点:第一步,增加slot-scope -->
- <template slot-scope="{ node, data }">
- <span style="display:block" @click="onClick(node)">{{ data.label }}</span>
- </template>
- </el-cascader>
- {{cascaderValue}}
- </div>
- </template>
-
- <script>
-
- export default {
- name: 'Test',
- data () {
- return {
- cascaderValue: [],
- options: [
- {
- value: 1,
- label: '东南',
- disabled: true,
- children: [
- {
- value: 2,
- label: '上海',
- disabled: true,
- children: [
- { value: 3, label: '普陀' },
- { value: 4, label: '黄埔' },
- { value: 5, label: '徐汇' }
- ]
- }
- ]
- },
- {
- value: 6,
- label: '西北',
- disabled: true,
- children: [
- { value: 7, label: '陕西' },
- { value: 8, label: '新疆' }
- ]
- },
- {
- value: 9,
- label: '东北'
- }
- ]
- }
- },
- methods: {
- // 单选的情况
- // onClick (node) {
- // if (!node.isDisabled) {
- // this.cascaderValue = node.path
- // }
- // },
- // 多选的情况
- onClick (node) {
- if (node.isDisabled) {
- return
- }
-
- // 定义一个数组,用于处理数据
- const data = []
-
- // 将之前选择的数据保存
- if (this.cascaderValue.length) {
- this.cascaderValue.forEach(n => {
- data.push(n)
- console.log('之前的值', data)
- })
- }
-
- // 处理:
- // 未选状态:将当前点击的node.path(是一个数组[1,2,3]),添加到data中
- // 已选状态:已选中的从data数组中查找node.path删除
- if (!node.checked) {
- data.push(node.path)
- console.log('未选->选中', data)
- } else {
- if (data.length) {
- // 将[ [ 1, 2, 3 ], [ 1, 2, 4 ], [ 1, 2, 5 ] ]数据转为["1,2,3", "1,2,4", "1,2,5"],因为数组不能比较
- const map = data.map(n => n.join(','))
- // 找出node.path删除
- const idx = map.findIndex(q => q === node.path.join(','))
- if (idx > -1) {
- data.splice(idx, 1)
- }
- console.log('已选->取消选中', data)
- }
- }
-
- // 最后双向绑定v-model的数据
- this.cascaderValue = data
- }
- }
- }
- </script>
多选存在问题:当使用el-cascader属性 clearable 的时候,会出现删除错误的问题,因为级联选择器绑定的数据是按照指定的格式添加。
因此需要在 “数据赋值到v-model” 以前对数据进行处理
将options树形数据转为数组数据
将满足条件的数据过滤出来
<template> <div> <!-- 多选 --> <el-cascader v-model="cascaderValue" :options="options" :props="{ multiple: true,checkStrictly:true }" clearable> <!-- 重点:增加slot-scope --> <template slot-scope="{ node, data }"> <span style="display:block" @click="onClick(node)">{{ data.label }}</span> </template> </el-cascader> {{cascaderValue}} </div> </template> <script> export default { name: 'Test', data () { return { cascaderValue: [], options: [ { value: 1, label: '东南', disabled: true, children: [ { value: 2, label: '上海', disabled: true, children: [ { value: 3, label: '普陀' }, { value: 4, label: '黄埔' }, { value: 5, label: '徐汇' } ] } ] }, { value: 6, label: '西北', disabled: true, children: [ { value: 7, label: '陕西' }, { value: 8, label: '新疆' } ] }, { value: 9, label: '东北' } ] } }, computed: { // 1.第一步,将树形数据转数组数据 // ["1,2,3", "1,2,4", "1,2,5", "6,7", "6,8", "9"] gradeLabelToList () { return this.treeToList(this.options) } }, methods: { // 单选的情况 // onClick (node) { // if (!node.isDisabled) { // this.cascaderValue = node.path // } // }, // 多选的情况 onClick (node) { if (node.isDisabled) { return } // 定义一个数组,用于处理数据 const data = [] // 将之前选择的数据保存 if (this.cascaderValue.length) { this.cascaderValue.forEach(n => { data.push(n) console.log('之前的值', data) }) } // 处理: // 未选状态:将当前点击的node.path(是一个数组[1,2,3]),添加到data中 // 已选状态:已选中的从data数组中查找node.path删除 if (!node.checked) { data.push(node.path) console.log('未选->选中', data) } else { if (data.length) { // 将[ [ 1, 2, 3 ], [ 1, 2, 4 ], [ 1, 2, 5 ] ]数据转为["1,2,3", "1,2,4", "1,2,5"],因为数组不能比较 const map = data.map(n => n.join(',')) // 找出node.path删除 const idx = map.findIndex(q => q === node.path.join(',')) if (idx > -1) { data.splice(idx, 1) } console.log('已选->取消选中', data) } } // 如果不添加以下代码,当使用组件的属性 clearable 的时候,会出现删除错误的问题,因为数据是有顺序的 const joinData = data.map(n => n.join(',')) // 将满足条件的数据过滤出来 const tempData = this.gradeLabelToList.filter(n => joinData.find(m => m === n)) let retData = [] // 再将数据数据构造回[ [ 1, 2, 3 ], [ 1, 2, 4 ], [ 1, 2, 5 ] ] retData = tempData.map(n => n.split(',').map(Number)) // 最后双向绑定v-model的数据 this.cascaderValue = retData }, treeToList (tree, out, pid) { if (out === undefined) { out = [] } tree.forEach(n => { const path = pid ? `${pid},` : '' const data = `${path}${n.value}` if (n.children) { this.treeToList(n.children, out, data) } else { out.push(data) } }) return out } } } </script>方法二:通过CSS样式
还有另一种方法,仅根据css样式,扩大radio或者checkbox的区域达到选中效果
存在问题:无法展开下一级
// css样式 <style lang="less"> .el-cascader-panel .el-radio, .el-checkbox { width: 100%; height: 100%; z-index: 10; position: absolute; top: 10px; right: 10px; } .el-cascader-panel .el-radio__input, .el-checkbox__input { visibility: hidden; } </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。