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>
相关推荐
devincob3 小时前
js原生、vue导出、react导出、axios ( post请求方式)跨平台导出下载四种方式的demo
javascript·vue.js·react.js
编程社区管理员3 小时前
React 发送短信验证码和验证码校验功能组件
前端·javascript·react.js
葡萄城技术团队3 小时前
迎接下一代 React 框架:Next.js 16 核心能力解读
javascript·spring·react.js
全马必破三3 小时前
React“组件即函数”
前端·javascript·react.js
三思而后行,慎承诺3 小时前
React 底层原理
前端·react.js·前端框架
座山雕~3 小时前
html 和css基础常用的标签和样式
前端·css·html
課代表3 小时前
JavaScript 中获取二维数组最大值
javascript·max·数组·递归·array·最大值·二维
灰小猿4 小时前
Spring前后端分离项目时间格式转换问题全局配置解决
java·前端·后端·spring·spring cloud
im_AMBER4 小时前
React 16
前端·笔记·学习·react.js·前端框架
02苏_4 小时前
ES6模板字符串
前端·ecmascript·es6