日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

组件封装 - 省市区联动组件

發(fā)布時(shí)間:2024/3/13 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 组件封装 - 省市区联动组件 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

首先, 講述一下這個(gè)組件需要實(shí)現(xiàn)的需求:

1. 在頁面顯示完整用戶選擇的省市區(qū)信息

2. 此組件是作用在別的組件里面, 接收父組件傳入完整的省市區(qū)信息; 提供模板中使用

3. 根據(jù)后端規(guī)定的字段名定義一個(gè)對(duì)象; 將用戶修改后的省市區(qū)數(shù)據(jù)放入這個(gè)對(duì)象中, 供需要的父組件使用

有三種情況, 父組件會(huì)向此組件傳入完整的省市區(qū)信息

我所講述的這一個(gè)組件是應(yīng)用在一個(gè)電商平臺(tái)所需要的省市區(qū)聯(lián)動(dòng)組件

1. 用戶沒有登錄時(shí), 父組件傳入一個(gè)定死的收貨地址信息

2. 用戶登錄后, 父組件傳入從數(shù)據(jù)庫中獲取當(dāng)前登錄賬號(hào)的默認(rèn)收貨地址信息

3. 用戶修改后, 因?yàn)樗械氖∈袇^(qū)數(shù)據(jù)都是在此組件里面; 所以記錄用戶修改后的省市區(qū)數(shù)據(jù)會(huì) emit 給父組件; 由父組件傳給此組件, 然后此組件通過 props 接收提供給模板使用

為什么第三種情況這樣做, 是因?yàn)榈谝环N和第二種情況都是父組件傳給此組件一個(gè)完整的省市區(qū)數(shù)據(jù); 這就說明, 此組件如何顯示省市區(qū)都是有父組件來決定的

所以, 此組件里面不能直接進(jìn)行修改, 而是由父組件傳入

好了, 說了些基本邏輯; 大家可能還是一頭霧水, 不知道我在說啥, 現(xiàn)在就上代碼顯示

首先, 完成基本布局

布局分析:

1. 大盒子里面包含兩個(gè)子盒子, 一是顯示配送地址信息盒子; 二是所有省市區(qū)信息盒子

2. 配送地址信息盒子里面就是兩個(gè) span , 一個(gè)是顯示信息盒子; 另外一個(gè)是 icon

<template><div class="xtx-city"><!-- 默認(rèn)顯示或選擇完畢的元素 --><div class="select"><!-- 默認(rèn)顯示的span信息 --><span class="placeholder">請(qǐng)選擇配送地址</span><!-- 用戶選擇完畢之后替換掉默認(rèn)顯示的span --><span class="value"></span><i class="iconfont icon-angle-down"></i></div><!-- 所有的省市區(qū)信息元素 --><div class="option"><span class="ellipsis" v-for="i in 24" :key="i">北京市</span></div></div> </template><script> export default {name: 'XtxCity' } </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>

現(xiàn)在來完成基本的交互

思路分析:

1. 定義控制省市區(qū)盒子(option), 顯示隱藏的變量(active); 默認(rèn)值為 false

2. 定義 option?元素顯示的方法(open), 將 active 變量值變成 true

3. 定義 option?元素隱藏的方法(close), 將?active 變量值變成 false

4. 定義一個(gè)調(diào)用 open 和 close 的方法(toggleOption), 通過判斷 active 的值; 動(dòng)態(tài)的調(diào)用 open 和close方法

5. 當(dāng)用戶點(diǎn)擊頁面其他地方的時(shí)候, 應(yīng)當(dāng)將 option 元素隱藏

<template><div class="xtx-city" ref="target"><div class="select" @click="toggleOption" :class="{active}"><span class="placeholder">請(qǐng)選擇配送地址</span><span class="value"></span><i class="iconfont icon-angle-down"></i></div><div class="option" v-if="active"><span class="ellipsis" v-for="i in 24" :key="i">北京市</span></div></div> </template><script> import { ref } from 'vue' import { onClickOutside } from '@vueuse/core' export default {name: 'XtxCity',setup () {// 控制option選項(xiàng)顯示隱藏變量, 默認(rèn)隱藏const active = ref(false)// 展開option元素方法const open = () => {active.value = true}// 關(guān)閉option元素方法const close = () => {active.value = false}// 根據(jù)active狀態(tài)來改變options元素的顯示隱藏const toggleOption = () => {if (active.value) close()else open()}// 點(diǎn)擊其他地方, 關(guān)閉option元素方法const target = ref(null)onClickOutside(target, () => {close()})return { active, toggleOption, target }} } </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;}}...... } </style>

?最后完成省市區(qū)聯(lián)動(dòng)的邏輯交互

思路分析:

1. 首先封裝調(diào)用接口函數(shù), 獲取所有的省市區(qū)數(shù)據(jù)(使用的是阿里的省市區(qū)json數(shù)據(jù))

2. 用戶可以頻繁的進(jìn)行點(diǎn)擊, 所以; 需要做緩存

3. 定義變量(cityList), 接收返回回來的數(shù)據(jù)(在數(shù)據(jù)還沒有返回時(shí), 顯示loading效果)

4. 在 open 方法被調(diào)用的時(shí)候, 調(diào)用接口函數(shù); 向?cityList 賦值(cityList的值是全部的初始的數(shù)據(jù), 頁面需要的數(shù)據(jù)是計(jì)算屬性計(jì)算得到的數(shù)據(jù))

5. 定義后端需要的字段對(duì)象(changeResult), 其中有省市區(qū)的地域編號(hào)和名稱

6. 定義一個(gè)方法(changeOption), 用戶點(diǎn)擊進(jìn)行選擇時(shí); 將用戶選擇的當(dāng)前數(shù)據(jù)傳給此方法

7.?changeOption 方法內(nèi)判斷, 用戶點(diǎn)擊的是省或市或區(qū); 對(duì)?changeResult 對(duì)象中的字段進(jìn)行賦值

8. 使用計(jì)算屬性(currList), 內(nèi)部再返回一個(gè)變量(currList), 通過?changeResult 對(duì)象中的省市區(qū)的地域編號(hào)動(dòng)態(tài)的改變 currList 的值; 最終?currList 提給給模板渲染數(shù)據(jù)

9. 用戶選擇到區(qū)一級(jí)時(shí), 將完整的省市區(qū)數(shù)據(jù) emit 給父組件, 調(diào)用 close 方法

10. 用戶再次進(jìn)行修改省市區(qū)數(shù)據(jù)時(shí), 情況?changeResult 對(duì)象中先前的數(shù)據(jù)

11. 當(dāng)用戶選擇錯(cuò)誤時(shí), 點(diǎn)擊頁面其他地方; 需要對(duì)?changeResult 對(duì)象中的數(shù)據(jù)進(jìn)行重置

<template><div class="xtx-city" ref="target"><div class="select" @click="toggleOption" :class="{active}"><span class="placeholder" v-if="!fullLocation">請(qǐng)選擇配送地址</span><span class="value" v-else>{{ fullLocation }}</span><i class="iconfont icon-angle-down"></i></div><div class="option" v-if="active"><!-- loading效果 --><div v-if="loading" class="loading"></div><template v-else><span class="ellipsis" @click="changeOption(item)" v-for="item in currList" :key="item.code">{{ item.name }}</span></template></div></div> </template><script> import { ref, computed, reactive } from 'vue' import { onClickOutside } from '@vueuse/core' import axios from 'axios' export default {name: 'XtxCity',props: {fullLocation: {type: String,default: ''}},setup (props, { emit }) {// 1. 獲取省市區(qū)數(shù)據(jù)方法(初始數(shù)據(jù))const getCityData = () => {const url = 'https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.json'return new Promise((resolve, reject) => {// 2. 做緩存// 有緩存if (window.cityData) {resolve(window.cityData)} else {// 沒有緩存axios.get(url).then(({ data }) => {window.cityData = dataresolve(window.cityData)})}})}// 3. 存儲(chǔ)獲取的省市區(qū)數(shù)據(jù)const cityList = ref([])// 當(dāng)數(shù)據(jù)還在加載時(shí), 顯示loading效果const loading = ref(false)// 4. 展開option元素方法const open = () => {active.value = trueloading.value = truegetCityData().then(res => {cityList.value = resloading.value = false}).catch(err => err)// 10. 再次打開的時(shí)候, 清空先前的數(shù)據(jù)for (const key in changeResult) {changeResult[key] = ''}}// 5. 定義依據(jù)后端字段需要的數(shù)據(jù)和父組件需要的數(shù)據(jù)const changeResult = reactive({// 省地域編號(hào)和名稱provinceCode: '',provinceName: '',// 市地域編號(hào)和名稱cityCode: '',cityName: '',// 區(qū)地域編號(hào)和名稱countyCode: '',countyName: '',// 完整的省市區(qū)數(shù)據(jù)fullLocation: ''})// 6. 修改省市區(qū)數(shù)據(jù)的方法const changeOption = (item) => {// 7. 用戶點(diǎn)擊當(dāng)前的省數(shù)據(jù)if (item.level === 0) {changeResult.provinceCode = item.codechangeResult.provinceName = item.name} else if (item.level === 1) {changeResult.cityCode = item.codechangeResult.cityName = item.name} else {changeResult.countyCode = item.codechangeResult.countyName = item.name// 拼接好完整的數(shù)據(jù)changeResult.fullLocation = `${changeResult.provinceName} ${changeResult.cityName} ${changeResult.countyName}`// 9. 提供給父組件使用emit('change', changeResult)close()}}// 8. 根據(jù)當(dāng)前的省市區(qū)數(shù)據(jù), 獲取對(duì)應(yīng)的下一級(jí)數(shù)據(jù)列表const currList = computed(() => {// 全部數(shù)據(jù)(不能直接的去影響cityList的數(shù)據(jù), 重新定義變量; 對(duì)此變量進(jìn)行修改即可)let currList = cityList.value// 用戶選擇省數(shù)據(jù)// 主要是判斷changeResult中省市區(qū)的地域編碼是否存在; 從而動(dòng)態(tài)的改變的currList值// 且 currList 是模板渲染的主要數(shù)據(jù), 所以用戶選擇的數(shù)據(jù)會(huì)隨著選擇變化而變化if (changeResult.provinceCode) {currList = currList.find(item => item.code === changeResult.provinceCode).areaList}// 用戶選擇當(dāng)前省的市數(shù)據(jù)if (changeResult.cityCode) {currList = currList.find(item => item.code === changeResult.cityCode).areaList}// 用戶選擇當(dāng)前市的區(qū)數(shù)據(jù)if (changeResult.countyCode) {currList = currList.find(item => item.code === changeResult.countyCode).areaList}return currList})// 11. 點(diǎn)擊其他地方, 關(guān)閉option元素方法const target = ref(null)onClickOutside(target, () => {close()// 重置數(shù)據(jù)for (const key in changeResult) {changeResult[key] = ''}})// 控制option選項(xiàng)顯示隱藏變量, 默認(rèn)隱藏const active = ref(false)// 根據(jù)active狀態(tài)來改變options元素的顯示隱藏const toggleOption = () => {if (active.value) close()else open()}// 關(guān)閉option元素方法const close = () => {active.value = false}return { active, toggleOption, target, loading, cityList, currList, changeOption, changeResult }} } </script><style scoped lang="less"> .xtx-city {.......option {.......loading {height: 290px;width: 100%;background: url(../../assets/images/loading.gif) no-repeat center;}} } </style>

父組件代碼?

<template><p class="g-name">{{ goods.name }}</p><p class="g-desc">{{ goods.desc }}</p><p class="g-price"><span>{{ goods.price }}</span><span>{{ goods.oldPrice }}</span></p><div class="g-service"><dl><dt>促銷</dt><dd>12月好物放送,App領(lǐng)券購(gòu)買直降120元</dd></dl><dl><dt>配送</dt><dd>至 <XtxCity @change="changeCity " :fullLocation="fullLocation" /></dd></dl><dl><dt>服務(wù)</dt><dd><span>無憂退貨</span><span>快速退款</span><span>免費(fèi)包郵</span><a href="javascript:;">了解詳情</a></dd></dl></div> </template><script> import { ref } from 'vue' export default {name: 'GoodName',props: {goods: {type: Object,default: () => {}}},setup (props) {// 當(dāng)用戶沒有登錄的時(shí)候, 需要顯示默認(rèn)的數(shù)據(jù)const provinceCode = ref('110000')const cityCode = ref('119900')const countyCode = ref('110101')const fullLocation = ref('北京市 市轄區(qū) 東城區(qū)')// 判斷用戶時(shí)候有登錄if (props.goods.userAddresses) {// 如果存在, city組件就需要渲染用戶的默認(rèn)收貨地址信息const defaultAddr = props.goods.userAddresses.find(addr => addr.isDefault === 1)if (defaultAddr) {provinceCode.value = defaultAddr.provinceCodecityCode.value = defaultAddr.cityCodecountyCode.value = defaultAddr.countyCodefullLocation.value = defaultAddr.fullLocation}}// 接收子組件傳入的數(shù)據(jù)const changeCity = (data) => {provinceCode.value = data.provinceCodecityCode.value = data.cityCodecountyCode.value = data.countyCodefullLocation.value = data.fullLocation}return { fullLocation, changeCity }} } </script><style lang="less" scoped> .g-name {font-size: 22px } .g-desc {color: #999;margin-top: 10px; } .g-price {margin-top: 10px;span {&::before {content: "¥";font-size: 14px;}&:first-child {color: @priceColor;margin-right: 10px;font-size: 22px;}&:last-child {color: #999;text-decoration: line-through;font-size: 16px;}} } .g-service {background: #f5f5f5;width: 500px;padding: 20px 10px 0 10px;margin-top: 10px;dl {padding-bottom: 20px;display: flex;align-items: center;dt {width: 50px;color: #999;}dd {color: #666;&:last-child {span {margin-right: 10px;&::before {content: "?";color: @xtxColor;margin-right: 2px;}}a {color: @xtxColor;}}}} } </style>

??

總結(jié)

以上是生活随笔為你收集整理的组件封装 - 省市区联动组件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。