全國地區資料會很大,我們可以直接用這個地址
https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.json
實作的效果如下:

考慮到城市組件也會在專案其它地方使用,所以把城市組件定義成全域組件,
來復習一下vue3.0中,將組件封裝成全域的:
1.src/components 下新建.vue檔案,用來放城市組件,
2.
3.
知道了實作的效果是: 當我點擊這個城市組件的時候,彈層顯示,再次點擊彈層隱藏,點擊組件外面區域也可關閉彈層,
vueuse/core中onClickOutside 可以監聽在元素之外點擊:
https://vueuse.org/core/onclickoutside/#onclickoutside
使用這個vueuse里面的Api記得先裝包!!!!
<template>
<div class="xtx-city" ref="target">
<div class="select" @click="toggle" :class="{active: show}">
<span class="placeholder">請選擇配送地址</span>
<span class="value"></span>
<i class="iconfont icon-angle-down"></i>
</div>
<div class="option" v-show="show">
<span class="ellipsis" v-for="i in 24" :key="i">北京市</span>
</div>
</div>
</template>
<script>
import { ref } from 'vue'
+ import axios from 'axios'
import { onClickOutside } from '@vueuse/core'
export default {
name: 'XtxCity',
setup () {
+ const url = 'https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.json'
const show = ref(false)
+ const getCityData = () => {
+ return axios({ url })
}
const close = () => {
show.value = false
}
const open = () => {
show.value = true
}
const toggle = () => {
show.value === true ? close() : open()
}
const target = ref(null)
onClickOutside(target, () => {
close()
})
return { show, toggle, open, close, target,+ getCityData }
}
}
</script>
<style scoped lang="less">
.xtx-city {
display: inline-block;
position: relative;
z-index: 400;
.select {
border: 1px solid #e4e4e4;
height: 30px;
padding: 0 5px;
line-height: 28px;
cursor: pointer;
&.active {
background: #fff;
}
.placeholder {
color: #999;
}
.value {
color: #666;
font-size: 12px;
}
i {
font-size: 12px;
margin-left: 5px;
}
}
.option {
width: 542px;
border: 1px solid #e4e4e4;
position: absolute;
left: 0;
top: 29px;
background: #fff;
min-height: 30px;
line-height: 30px;
display: flex;
flex-wrap: wrap;
padding: 10px;
> span {
width: 130px;
text-align: center;
cursor: pointer;
border-radius: 4px;
padding: 0 3px;
&:hover {
background: #f5f5f5;
}
}
}
}
</style>
開頭說到,渲染資料時,使用的一個地址,那么在代碼中如何運用? 使用時,我添加到了上面代碼段中,帶 + 號的
接下來,考慮一個問題,什么時候發請求,拿全國資料呢? 組件開始創建的時候嗎?
答案是:當這個彈出層打開時去發請求,因為用戶可能不點擊這個城市組件,如果你在組件創建的時候就去發請求,用戶不點擊,全國資料又很大,浪費資源
const citydata = ref([ ]) // 接收城市資料

如果用戶沒有登錄:當前商品資料中,后端會傳遞 userAddresses: null, 此時,我們應該用默認地址:北京市 市轄區 東城區

如果用戶已經登錄:當前商品資料中,后端會傳遞 userAddresses: 地址陣列:
因為我把城市組件單獨放在一個檔案中了,而上面這幅圖 里面的fullLocation是我請求下圖左側資料時回傳來的,對于我這個組件來說,屬于父傳子操作

這段代碼是寫在父組件中的
setup(){
// 默認情況
const provinceCode = ref('110000')
const cityCode = ref('119900')
const countyCode = ref('110101')
const fullLocation = ref('北京市 市轄區 東城區')
// 有默認地址
if (props.data.userAddresses) { // 如果userAddresses有值
//找userAddresses陣列中哪一項的isDefault ===1
const defaultAddr = props.data.userAddresses.find(addr => addr.isDefault === 1)
if (defaultAddr) { // 如果有,取到它的資料項
provinceCode.value = defaultAddr.provinceCode
cityCode.value = defaultAddr.cityCode
countyCode.value = defaultAddr.countyCode
fullLocation.value = defaultAddr.fullLocation
}
}
}
把資料傳給子組件
<XxxCity :fullLocation="fullLocation" />
子組件接收資料渲染
props: {
fullLocation: { type: String, default: '' }
},
接下來是實作子組件里面選省市區之后,父組件上的資料同步更新:

setup(props, { emit }){
const changeResult = reactive({
provinceCode: '',
provinceName: '',
cityCode: '',
cityName: '',
countyCode: '',
countyName: '',
fullLocation: ''
})
const changeItem = (item) => {
// 省份
if (item.level === 0) {
changeResult.provinceCode = item.code
changeResult.provinceName = item.name
}
// 市
if (item.level === 1) {
changeResult.cityCode = item.code
changeResult.cityName = item.name
}
// 區
if (item.level === 2) {
changeResult.countyCode = item.code
changeResult.countyName = item.name
changeResult.fullLocation = `${changeResult.provinceName} ${changeResult.cityName} ${changeResult.countyName}`
close() // close也是寫在了子組件中,所以直接呼叫即可
emit('change', changeResult)
}
}
//計算屬性,根據我點擊的省,自動去找市和區
const currList = computed(() => {
let currList = citydata.value
if (changeResult.provinceCode) {
currList = currList.find(it => it.code === changeResult.provinceCode).areaList
}
if (changeResult.cityCode) {
currList = currList.find(c => c.code === changeResult.cityCode).areaList
}
return currList
})
// return { currList ...........} 外面使用記得rerurn
}
父組件接收事件:
<dd>至 <XtxCity :fullLocation="fullLocation" @change="changeCity"/></dd>
const changeCity = (result) => {
provinceCode.value = result.provinceCode
cityCode.value = result.cityCode
countyCode.value = result.countyCode
fullLocation.value = result.fullLocation
}
return { ....., changeCity }
每次打開的時候,清空選擇結果:
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/290317.html
標籤:其他
上一篇:STM32 感應開蓋垃圾桶
