vue3如何使用vant-picker封裝省市二級(jí)聯(lián)動(dòng)
怕什么真理無(wú)窮,進(jìn)一步有進(jìn)一步的歡喜呀,不得不承認(rèn)的就是,興趣和擅長(zhǎng)是一個(gè)良性迭代的循環(huán)啊,你擅長(zhǎng)某件事情,就會(huì)越喜歡它,越喜歡,就越愿意花時(shí)間,進(jìn)而越擅長(zhǎng)。所以代碼碼起來(lái)吧哈哈哈
近期用上了vue3,還順手寫(xiě)了個(gè)小需求,用vant-picker封裝一個(gè)省市的二級(jí)聯(lián)動(dòng),并且在從后端接口獲取省市的數(shù)據(jù),點(diǎn)開(kāi)彈出框需要展示默認(rèn)的選項(xiàng),比如點(diǎn)擊廣東省-深圳市輸入框,彈出的picker級(jí)聯(lián)選擇器需要默認(rèn)廣東 -深圳。
如下圖:
好,那么話不多說(shuō),接下來(lái)一步一步來(lái)實(shí)現(xiàn)。
首先,項(xiàng)目中引入vant-ui
import { Popup, Picker } from 'vant' components: { [Picker.name]: Picker, [Popup.name]: Popup, },
vant官網(wǎng)中,地區(qū)聯(lián)動(dòng)的形式是這樣的
而我的數(shù)據(jù)格式是這樣的
[ { "citys": [ { "cityName": "北京市" } ], "provinceName": "北京市" }, { "citys": [ { "cityName": "天津市" } ], "provinceName": "天津市" }, { "citys": [ { "cityName": "上海市" } ], "provinceName": "上海市" }, { "citys": [ { "cityName": "重慶市" } ], "provinceName": "重慶市" },]
然后對(duì)數(shù)據(jù)做了處理,處理成官網(wǎng)的形式,這樣就可以聯(lián)動(dòng)了
const columnsData = chinaAreaDataType.map((item, index) => { const children: { text: string }[] = [] item.citys.forEach((item) => { children.push({ text: item.cityName, }) }) return { text: item.provinceName, children } })
其中關(guān)于一些vue3父子組件的傳值就不過(guò)多贅述了,有需要可自行查看官方文檔
接下來(lái)說(shuō)一說(shuō),點(diǎn)開(kāi)彈出框需要展示默認(rèn)的選項(xiàng)怎么實(shí)現(xiàn)的吧,此處,vant官網(wǎng)給出了一個(gè)api,不過(guò)沒(méi)有使用示例,搗鼓了半天。
使用setIndexes設(shè)置獲取到的索引值,就可以實(shí)現(xiàn)點(diǎn)開(kāi)彈出框需要展示默認(rèn)的選項(xiàng)了,在onMounted中通過(guò)ref去設(shè)置相應(yīng)的索引即可。
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]) })
你以為這樣就結(jié)束了嗎,no no no,還要在popup 中設(shè)置lazy-render為false,這樣就結(jié)束拉~
好吧廢話不多說(shuō),上子組件代碼
子組件代碼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="@/assets/icons/lineCross.svg" /> </div> </template> <template v-slot:title> <p class="title">{{ title }}</p> </template> <template v-slot:confirm> <div class="icon--button"> <img src="@/assets/icons/lineHook.svg" /> </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: '請(qǐng)選擇地區(qū)', }, }, 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="./index.scss" />
父組件代碼
<template> <div> <van-field v-model="areaValue" label="地區(qū)" placeholder="請(qǐng)輸入地區(qū)" @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; }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue3?源碼分析reactive?readonly實(shí)例
這篇文章主要為大家介紹了Vue3?源碼分析reactive?readonly實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10vue使用i18n實(shí)現(xiàn)國(guó)際化的方法詳解
這篇文章主要給大家介紹了關(guān)于vue使用i18n如何實(shí)現(xiàn)國(guó)際化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09詳解Vue SPA項(xiàng)目?jī)?yōu)化小記
這篇文章主要介紹了詳解Vue SPA項(xiàng)目?jī)?yōu)化小記,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07詳解vue中父子組件傳遞參數(shù)props的實(shí)現(xiàn)方式
這篇文章主要給大家介紹了在vue中,父子組件傳遞參數(shù)?props?實(shí)現(xiàn)方式,文章通過(guò)代碼示例介紹的非常詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定的參考價(jià)值,需要的朋友可以參考下2023-07-07基于Vue2實(shí)現(xiàn)數(shù)字縱向滾動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了如何基于Vue2實(shí)現(xiàn)數(shù)字縱向滾動(dòng)效果,從而達(dá)到顯示計(jì)時(shí)器滾動(dòng)效果,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03vue動(dòng)態(tài)添加store、路由和國(guó)際化配置方式
這篇文章主要介紹了vue動(dòng)態(tài)添加store、路由和國(guó)際化配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03