uniapp 树状数据无限极 进行展示并选择

两个文件 demo.vue -- olylis-cascader.vue

提示:可以对照接口返回的参数名来修改,把value=id,label=name

demo.vue

html 复制代码
<template>
    <olylis-cascader :options="treeData" :value="selectedValue" @change="handleChange" :is-show-nav="false">
        <!-- 可自定义节点 -->
<!--        <template v-slot="{ data }">-->
<!--            <view>-->
<!--                {{ data.label }} : {{ data.value }}-->
<!--            </view>-->
<!--        </template>-->
    </olylis-cascader>
</template>

<script>
	//	第二个文件的地址,自己修改
    import olylisCascader from './olylis-cascader'

    export default {
        name: 'demo',
        components: {olylisCascader},
        data() {
            return {
                selectedValue: [],
                treeData: [
                    {
                        value: 1,
                        label: '一级 1',
                        children: [{
                            value: 11,
                            label: '二级 1-1',
                            children: [{
                                value: 111,
                                label: '三级 1-1-1'
                            }]
                        }],
                    }, {
                        value: 2,
                        label: '一级 2',
                        children: [{
                            value: 21,
                            label: '二级 2-1',
                            children: [{
                                value: 211,
                                label: '三级 2-1-1'
                            }]
                        }, {
                            value: 22,
                            label: '二级 2-2',
                            children: [{
                                value: 221,
                                label: '三级 2-2-1'
                            }]
                        }]
                    }, {
                        value: 3,
                        label: '一级 3',
                        children: [{
                            value: 31,
                            label: '二级 3-1',
                            children: [{
                                value: 311,
                                label: '三级 3-1-1'
                            }]
                        }, {
                            value: 32,
                            label: '二级 3-2',
                            children: [{
                                value: 321,
                                label: '三级 3-2-1'
                            }]
                        }]
                    }
                ]
            }
        },
        //现在这里写死,可以自己加个接口换数据
        methods: {
        	// 每次点击都会返回点击的内容
            handleChange(selectedValue, clickItem) {
                console.log('handleChange', selectedValue, clickItem)
                this.selectedValue = selectedValue
            }
        }
    }
</script>

<style scoped>

</style>

olylis-cascader.vue

这里我标下可能需要替换参数名的地方,如果是需要id,name 之类的

html代码应该都能看懂,知道那些替换,我重点是下面的方法里是标注下

html 复制代码
<template>
	<view ref="cascaderRef" class="cascader">
		<view v-if="isShowNav" class="bread-crumb clearfix">
			<view class="bread-crumb-root">当前:</view>                                   
			<view class="bread-crumb-item" v-for="(item, index) in breadCrumbList" :key="item.value" >
				<text class="bread-crumb-text" @click="clickNav(item, index)">{{item.label}}</text>
				<view v-if="index < breadCrumbList.length - 1" class="bread-crumb-icon">></view>
			</view>
		</view>
		<view class="cascader-content">
			<scroll-view scroll-x scroll-with-animation :scroll-left="scrollLeft" style="height:100%;">
				<view class="options-row clearfix" :style="rowStyle">
						<view class="options-column" v-for="(opitons, columnIndex) in optionsList" :key="columnIndex" :style="columnStyle">
						<scroll-view scroll-y style="height:100%">
							<view class="options-item" v-for="item in opitons" :class="{'active': selectedValue[columnIndex] === item.value}" :key="item.value" @click="clickItem(item, columnIndex)">
								<slot :data="item">{{item.label}}</slot>
							</view>
						</scroll-view>
					</view>
				</view>
			</scroll-view>
		</view>
	</view>
</template>

<script>
	function getStyleString (styleObject) {
		return Object.keys(styleObject).map(propName => (propName + ':' + styleObject[propName] + ';')).join('')
	}
	
	export default {
		name: 'cascader',
		props: {
			columnWidth: {
				type: Number,
				default: null
			},
			value: {
				type: Array,
				default() {return []}
			},
			options: {
				type: Array,
				default() {return []}
			},
			isShowNav: {
				type: Boolean,
				default: true
			}
		},
		data() {
			return {
				WIDTH: 300,
				COLUMN_WIDTH: 150,
				selectedValue: [],
				optionsList: []
			}
		},
		computed: {
			breadCrumbList() {                                                                    // id
				return this.selectedValue.map((item, i) => this.optionsList[i].find(option => option.value === item))
			},
			rowStyle() {
				return getStyleString({
					width: this.COLUMN_WIDTH * (Math.max(2, this.optionsList.length)) + 'px'
				})
			},
			columnStyle() {
				return getStyleString({
					width: this.COLUMN_WIDTH + 'px'
				})
			},
			scrollLeft() {
				return Math.max(0, this.COLUMN_WIDTH * (this.optionsList.length - 2))
			}
		},
		watch: {
			value(val) {
				this.handleValue(val)
			},
			options(val) {
				this.handleValue(this.value)
			}
		},
		created() {
			this.handleValue(this.value)
		},
		mounted() {
			this.init()
		},
		methods: {
			init() {
				const query = uni.createSelectorQuery().in(this);
				query.select('.cascader').boundingClientRect(data => {
					this.WIDTH = data.width ? data.width : 150
					this.COLUMN_WIDTH = this.WIDTH / 2
				}).exec();
			},
			handleValue(val) {
				this.selectedValue = []
				this.optionsList = this.getOptionsList(val, this.options)
				this.selectedValue = val
			},
			getOptionsList(values, options, currentList = []) {
				if (!options || options.length === 0) return currentList
				currentList.push(options)
				if (values.length === 0) return currentList
				                                    // id
				const next = options.find(item => item.value === values[0])
				const nextValue = values.slice(1)
				const nextOptions = next.children
				return this.getOptionsList(nextValue, nextOptions, currentList)
			},
			clickNav(item, index) {
				this.clickItem(item, index)
			},
			clickItem(item, columnIndex) {
				const selectedValue = this.selectedValue.slice(0, columnIndex)
				const optionsList = this.optionsList.slice(0, columnIndex + 1)
				                                    // id
				selectedValue.splice(columnIndex, 1, item.value)
				this.selectedValue = selectedValue
				if (item.children) optionsList.splice(columnIndex + 1, 1, item.children)
				this.optionsList = optionsList
				this.$emit('change', selectedValue, item)
			}
		}
	}
</script>

<style lang="scss" scoped>
	.clearfix::after {
		content: "";
		display: block;
		height: 0;
		clear: both;
		visibility: hidden;
	}

	.cascader {
		height: 100%;
		
		.bread-crumb {
			height: 30px;
			line-height: 30px;
			border-bottom: 1px solid #d8d8d8;
			padding: 0 10px;
			font-size: 12px;
			
			.bread-crumb-root {
				float: left;
			}
			
			.bread-crumb-item {
				float: left;
			}
			
			.bread-crumb-text {
				color: #0083FF;
			}
			
			.bread-crumb-icon {
				display: inline-block;
				padding: 0 5px;
			}
		}
		
		.cascader-content {
			height: calc(100% - 30px);
		}
		
		.options-row {
			height: 100%;
		}
		
		.options-column {
			float: left;
			height: 100%;
			
			box-sizing: border-box;
			
			&:not(:last-child) {
				border-right: 1px solid #d8d8d8;
			}
		}
		
		.options-item {
			padding: 10px 10px;
			
			&.active {
				color: #ff6600;
			}
		}
	}
</style>
相关推荐
百事可乐☆12 分钟前
uniapp 九宫格抽奖
uni-app
xing251620 分钟前
pytest-html
前端·html·pytest
茂茂在长安30 分钟前
Linux 命令大全完整版(11)
java·linux·运维·服务器·前端·centos
Violet51531 分钟前
ECMAScript规范解读——this的判定
javascript
知识分享小能手1 小时前
Html5学习教程,从入门到精通,HTML5 简介语法知识点及案例代码(1)
开发语言·前端·javascript·学习·前端框架·html·html5
IT、木易1 小时前
大白话React第二章深入理解阶段
前端·javascript·react.js
晚安7201 小时前
Ajax相关
前端·javascript·ajax
图书馆钉子户1 小时前
怎么使用ajax实现局部刷新
前端·ajax·okhttp
bin91531 小时前
DeepSeek 助力 Vue 开发:打造丝滑的单选按钮(Radio Button)
前端·javascript·vue.js·ecmascript·deepseek
qianmoQ2 小时前
第五章:工程化实践 - 第五节 - Tailwind CSS 常见问题解决方案
前端·css