首页IT科技vue实现二级联动(vue3如何使用vant-picker封装省市二级联动)

vue实现二级联动(vue3如何使用vant-picker封装省市二级联动)

时间2025-05-05 11:33:50分类IT科技浏览4235
导读:怕什么真理无穷,进一步有进一步的欢喜呀,不得不承认的就是,兴趣和擅长是一个良性迭代的循环啊,你擅长某件事情,就会越喜欢它,越喜欢,就越愿意花时间,进而越擅长。所以代码码起来吧哈哈哈...

怕什么真理无穷            ,进一步有进一步的欢喜呀                  ,不得不承认的就是      ,兴趣和擅长是一个良性迭代的循环啊         ,你擅长某件事情                  ,就会越喜欢它         ,越喜欢      ,就越愿意花时间                  ,进而越擅长            。所以代码码起来吧哈哈哈

近期用上了vue3            ,还顺手写了个小需求   ,用vant-picker封装一个省市的二级联动                  ,并且在从后端接口获取省市的数据               ,点开弹出框需要展示默认的选项,比如点击广东省-深圳市输入框               ,弹出的picker级联选择器需要默认广东 -深圳                  。

如下图:

好                  ,那么话不多说   ,接下来一步一步来实现      。

首先            ,项目中引入vant-ui

import { Popup, Picker } from vant components: { [Picker.name]: Picker, [Popup.name]: Popup, },

vant官网中                  ,地区联动的形式是这样的

而我的数据格式是这样的

[ { "citys": [ { "cityName": "北京市" } ], "provinceName": "北京市" }, { "citys": [ { "cityName": "天津市" } ], "provinceName": "天津市" }, { "citys": [ { "cityName": "上海市" } ], "provinceName": "上海市" }, { "citys": [ { "cityName": "重庆市" } ], "provinceName": "重庆市" },]

然后对数据做了处理      ,处理成官网的形式         ,这样就可以联动了

const columnsData = chinaAreaDataType.map((item, index) => { const children: { text: string }[] = [] item.citys.forEach((item) => { children.push({ text: item.cityName, }) }) return { text: item.provinceName, children } })

其中关于一些vue3父子组件的传值就不过多赘述了                  ,有需要可自行查看官方文档

接下来说一说         ,点开弹出框需要展示默认的选项怎么实现的吧      ,此处                  ,vant官网给出了一个api            ,不过没有使用示例   ,捣鼓了半天         。

使用setIndexes设置获取到的索引值                  ,就可以实现点开弹出框需要展示默认的选项了               ,在onMounted中通过ref去设置相应的索引即可                  。

onMounted(() => { const cityName = toRef(props, areaValue).value.split(-) const findProvinceName = columnsData.findIndex((value) => value.text === cityName[0]) const findCityName = columnsData[findProvinceName].children.findIndex((value) => value.text === cityName[1]) areaPicker.value?.setIndexes([findProvinceName, findCityName]) })

你以为这样就结束了吗,no no no,还要在popup 中设置lazy-render为false               ,这样就结束拉~

好吧废话不多说                  ,上子组件代码

子组件代码PickerArea

<template> <div class="container"> <van-popup v-model:show="refShowOverlay" position="bottom" :lazy-render="false" round> <van-picker ref="areaPicker" show-toolbar :columns="columnsData" value-key="text" @change="handleChangeArea" @cancel="handleCancelArea" @confirm="handleConfirmArea" > <template v-slot:cancel> <div class="icon--button"> <img src="" /> </div> </template> <template v-slot:title> <p class="title">{{ title }}</p> </template> <template v-slot:confirm> <div class="icon--button"> <img src="" /> </div> </template> </van-picker> </van-popup> </div> </template> <script lang="ts"> import { defineComponent, ref, toRef, watch, reactive, onMounted } from vue import { Popup, Picker, Field } from vant import chinaAreaDataType from ./chinaAreaData.json export default defineComponent({ name: TasPickerArea, components: { [Picker.name]: Picker, [Popup.name]: Popup, [Field.name]: Field, }, props: { areaValue: { type: String, default: , }, show: { type: Boolean, default: false, }, showDatePicker: { type: Boolean, default: false, }, title: { type: String, default: 请选择地区, }, }, setup(props, { emit }) { const refShowOverlay = ref(false) const computedShowOverlay = toRef(props, showDatePicker) const areaPicker = ref<typeof Picker>() const handleCancelArea = () => { emit(close, false) } const columnsData = chinaAreaDataType.map((item, index) => { const children: { text: string }[] = [] item.citys.forEach((item) => { children.push({ text: item.cityName, }) }) return { text: item.provinceName, children } }) const handleChangeArea = (area: Array<{ text: string }>) => { emit(change-area, area) } const handleConfirmArea = (area: Array<{ text: string }>) => { emit(confirm-area, area) handleCancelArea() } watch(computedShowOverlay, (nV) => { refShowOverlay.value = nV }) onMounted(() => { const cityName = toRef(props, areaValue).value.split(-) const findProvinceName = columnsData.findIndex((value) => value.text === cityName[0]) const findCityName = columnsData[findProvinceName].children.findIndex((value) => value.text === cityName[1]) areaPicker.value?.setIndexes([findProvinceName, findCityName]) }) return { refShowOverlay, areaPicker, columnsData, handleChangeArea, handleCancelArea, handleConfirmArea, } }, }) </script> <style lang="scss" scoped src="https://www.jb51.net/article/index.scss" />

父组件代码

<template> <div> <van-field v-model="areaValue" label="地区" placeholder="请输入地区" @click="handleClickOFF" /> <tas-picker-china-area :show-date-picker="show" @close="show = false" @confirm-area="handleConfirmArea" @change-area="handleChangeArea" :areaValue="areaValue" /> </div> </template> <script lang="ts"> import { computed, defineComponent, ref, watch, reactive, toRefs } from vue import { Field } from vant import { px2remWithUnit } from @/utils/ui import { getThemeVarValue } from @/config/ui import { showDialog } from ./components/TasDialog/dialog import TasPickerChinaArea from @/components/TasPickerChinaArea/index.vue export default defineComponent({ name: TasButton, components: { [Field.name]: Field, TasPickerChinaArea, }, setup() { const show = ref(false) const refShowDatePicker = ref(true) const areaValue = ref(广东省-深圳市) const handleClickOFF = () => { show.value = !show.value } const handleConfirmArea = (area: Array<{ text: string }>) => { areaValue.value = `${area[0].text} - ${area[1].text}` } const handleChangeArea = (area: Array<{ text: string }>) => {} return { show, areaValue, refShowDatePicker, handleClickOFF, handleConfirmArea, handleChangeArea, } }, }) </script>

css代码

.container { overflow: hidden; &::v-deep(.van-picker-column) { font-size: 32px; } ::v-deep(.van-picker__toolbar) { height: auto; padding: 30px 45px; border-bottom: 1px solid rgba(0, 0, 0, 0.1); } } .icon--button img { width: 52px; } .title { font-size: 32px; font-weight: 500; color: #000000; line-height: 45px; }

以上为个人经验   ,希望能给大家一个参考            ,也希望大家多多支持本站         。

声明:本站所有文章                  ,如无特殊说明或标注      ,均为本站原创发布      。任何个人或组织         ,在未征得本站同意时                  ,禁止复制            、盗用                  、采集      、发布本站内容到任何网站         、书籍等各类媒体平台                  。如若本站内容侵犯了原著者的合法权益         ,可联系我们进行处理            。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
windows软件模糊(win10应用显示模糊怎么修复)