微信小程序使用Vant Weapp(1.10.10版本)van-cascader组件实现省市区懒加载选择

502 阅读1分钟

微信小程序使用Vant Weapp(1.10.10版本)van-cascader组件实现省市区懒加载选择

效果图如下:

image.png wxml代码:

<view class="container">
  <van-field value="{{ fieldValue }}" is-link readonly label="地区" placeholder="请选择所在地区" bind:tap="onClick" />
  <van-popup show="{{ show }}" round position="bottom">
    <van-cascader id="my-cascader" title="请选择所在地区" options="{{options}}" value="{{ cascaderValue }}"
      bind:close="onClose" bind:finish="onFinish" active-color="#ee0a24" bind:change="handleChange" />
  </van-popup>
</view>

js代码:

const { http } = getApp();
import { getAreaUrl } from '../../api/index'; //接口

Page({
	/**
	 * 页面的初始数据
	 */
	data: {
		show: false,
		options: [
			// 省市区数据
		],
		fieldValue: '',
		cascaderValue: '',
		level: 3 //选择到第几层
	},
	//完成时触发
	onFinish(e) {
		const { selectedOptions, value } = e.detail;
		const fieldValue = selectedOptions.map((option) => option.text).join('>');
		this.setData({
			fieldValue,
			cascaderValue: value,
			show: false
		});
	},

	onClick() {
		this.setData({
			show: true
		});
	},

	onClose() {
		this.setData({
			show: false
		});
	},
	handleChange(event) {
		let { level } = this.data;
		// 获取选中的值
		const { value, tabIndex } = event.detail;
		// 获取当前选中的对象
		const selectedOption = this.getSelectedOption(value);
		console.log(selectedOption);

		//判断台湾省的选中
		if (selectedOption.text == '台湾省' && tabIndex == 0) {
			this.getArea(0);
			return;
		}

		// 判断是否选择三级省市区的判断
		if (selectedOption.level == level) {
			return;
		}

		// 判断是否有子级数据
		if (!selectedOption.children || !selectedOption.children.length) {
			http.get(getAreaUrl + `/${value}`).then(({ data = {} }) => {
				// 更新当前选中对象的 children 属性和 value 值
				const arr = data.map((p) => ({
					text: p.areaName + '',
					value: p.areaCode + '',
					level: p.level,
					children: p.level == level ? undefined : [] //判断只渲染三级
				}));
				//赋值子集
				selectedOption.children = arr;
				selectedOption.value = value;
				this.setData({
					options: this.data.options,
					cascaderValue: value // 更新组件状态(重要)
				});
			});
		} else {
			// 更新 cascaderValue 值 更新组件状态
			this.setData({
				cascaderValue: value
			});
		}
	},
	// 根据 value 返回匹配的选项对象  value:当前点击的code
	getSelectedOption(value) {
		const options = this.data.options;
		//递归遍历循环
		let matchedOption;
		const addTree = (option) => {
			if (option.value === value) {
				matchedOption = option;
			}
			if (!matchedOption && option.children) {
				option.children.forEach((child) => addTree(child));
			}
		};
		//找对对应children
		options.forEach((option) => addTree(option));
		return matchedOption;
	},

	// 加载省份数据
	getArea(parentId) {
		http.get(getAreaUrl + `/${parentId}`).then(({ data = {} }) => {
			const provinces = data.map((p) => ({
				text: p.areaName + '',
				value: p.areaCode + '',
				level: p.level,
				children: p.areaCode != '710000' ? [] : undefined // 城市列表先占位,后续再加载  台湾省除外
			}));

			this.setData({ options: provinces });
		});
	},
	/**
	 * 生命周期函数--监听页面加载
	 */
	onLoad(options) {
		this.getArea(0);
	},

	/**
	 * 生命周期函数--监听页面初次渲染完成
	 */
	onReady() {},

	/**
	 * 生命周期函数--监听页面显示
	 */
	onShow() {},

	/**
	 * 生命周期函数--监听页面隐藏
	 */
	onHide() {},

	/**
	 * 生命周期函数--监听页面卸载
	 */
	onUnload() {},

	/**
	 * 页面相关事件处理函数--监听用户下拉动作
	 */
	onPullDownRefresh() {},

	/**
	 * 页面上拉触底事件的处理函数
	 */
	onReachBottom() {},

	/**
	 * 用户点击右上角分享
	 */
	onShareAppMessage() {}
});