配送地址跨頁面同步方案)
簡介一套面向畢業(yè)設(shè)計的民航售票管理系統(tǒng)完整資料包基于ASP與SQL Server開發(fā)采用B/S結(jié)構(gòu)適合計算機相關(guān)專業(yè)學(xué)生用來完成課程設(shè)計或畢業(yè)論文參考。系統(tǒng)涵蓋會員注冊管理、管理員后臺、留言管理、航班查詢、網(wǎng)上訂票與網(wǎng)上退票等核心功能從需求分析、數(shù)據(jù)庫設(shè)計到編碼實現(xiàn)均有完整支持。整個壓縮包共96個文件以35個ASP頁面、42張GIF圖片、7個SWF動畫為主另含數(shù)據(jù)庫文件及畢業(yè)論文文檔整體僅1.14MB輕量便于本地運行與調(diào)試。目前已有139人學(xué)習(xí)下載。資料包含可直接部署的源代碼、配套數(shù)據(jù)庫和完整畢業(yè)論文并附有系統(tǒng)設(shè)計與實現(xiàn)文檔可幫助讀者快速理解民航售票業(yè)務(wù)的模塊劃分、數(shù)據(jù)庫表設(shè)計與ASP編程思路是畢業(yè)設(shè)計備題和ASP技術(shù)練手的實用參考。 我們來做一版純前端的方案。核心思路把配送至頁保存的地址寫進(jìn) localStorage商品詳情頁的“由我享用 / 送TA禮物”列表從 localStorage 讀取并支持勾選刪除訂單確認(rèn)頁再從 localStorage 讀取被勾選的地址來完成回填。整體流程用戶在 A 商品詳情頁點擊“由我享用 / 送TA禮物”進(jìn)入配送至頁配送至頁選擇配送方式、填寫收貨地址點擊保存保存后地址寫入 localStorage并跳轉(zhuǎn)回 A 商品詳情頁A 商品詳情頁的列表展示已保存地址可勾選“由我享用/送TA禮物”也可刪除用戶進(jìn)入 B 商品詳情頁同樣能看到同一份地址列表因為 localStorage 是全局共享的勾選某條地址后點擊“立即購買”跳轉(zhuǎn)訂單確認(rèn)頁時從 localStorage 讀取勾選狀態(tài)把地址回填到訂單確認(rèn)頁。下面給出最簡實現(xiàn)你可以直接復(fù)制到現(xiàn)有項目里對照修改。1. localStorage 數(shù)據(jù)結(jié)構(gòu)設(shè)計建議統(tǒng)一用兩個 keyshippingAddresses保存全部地址列表數(shù)組對象。selectedShippingId保存當(dāng)前選中的地址 id用于“由我享用/送TA禮物”的勾選狀態(tài)以及訂單確認(rèn)頁回填。每條地址對象結(jié)構(gòu){ id: Date.now() Math.random().toFixed(4), // 確保唯一方便刪除 receiver: 張三, phone: 13800000000, province: 浙江省, city: 杭州市, district: 西湖區(qū), detail: 文一西路 100 號, deliveryType: express, // express 快遞 / pickup 門店自提 tag: 由我享用 // 或 送TA禮物 }當(dāng)然你也可以把 tag 單獨拆出去但最簡單的做法是把它作為地址的一個屬性保存。這樣后續(xù)勾選時可以區(qū)分是“由我享用”還是“送TA禮物”。2. 配送至頁保存地址并回寫 localStorage頁面流程里用戶填完表單點擊“保存”我們做這些事校驗表單必填項組裝地址對象從 localStorage 讀出舊列表或初始化為空數(shù)組往數(shù)組頭部 unshift 新地址方便用戶看到最新保存的把新地址的 id 設(shè)置為當(dāng)前選中項寫入selectedShippingId跳轉(zhuǎn)回來源商品詳情頁可以用window.history.back()或location.href。代碼示例function saveAddress(formData) { // 1. 基本校驗不通過則 return if (!formData.receiver || !formData.phone || !formData.detail) { alert(請?zhí)顚懲暾肇浶畔?; return false; } // 2. 構(gòu)造地址對象 const newAddress { id: Date.now() _ Math.floor(Math.random() * 1000), receiver: formData.receiver, phone: formData.phone, province: formData.province, city: formData.city, district: formData.district, detail: formData.detail, deliveryType: formData.deliveryType || express, tag: formData.tag 送TA禮物 ? 送TA禮物 : 由我享用 }; // 3. 讀取舊列表 const existing JSON.parse(localStorage.getItem(shippingAddresses) || []); // 4. 新增到頭部并保存 existing.unshift(newAddress); localStorage.setItem(shippingAddresses, JSON.stringify(existing)); // 5. 設(shè)置當(dāng)前選中地址 id localStorage.setItem(selectedShippingId, newAddress.id); // 6. 跳回商品詳情頁 history.back(); // 或者 location.href 商品詳情頁地址; return true; }邏輯說明用unshift保持最新地址在最上面后續(xù)列表展示時直接按數(shù)組順序渲染新保存的地址默認(rèn)設(shè)為選中這是為了貼近用戶操作習(xí)慣剛填完的地址大概率就是想用的id使用時間戳隨機數(shù)不需要依賴后端返回如果你希望保留“由我享用”和“送TA禮物”兩個獨立入口對應(yīng)兩套獨立標(biāo)簽可以在tag字段區(qū)分后續(xù)在商品詳情頁根據(jù)按鈕類型篩選顯示。3. 商品詳情頁“由我享用 / 送TA禮物”列表讀寫與刪除商品詳情頁打開時需要讀取 localStorage 里的地址列表判斷當(dāng)前商品詳情頁是從哪個入口進(jìn)來的由我享用 / 送TA禮物可以通過鏈接參數(shù)或者按鈕點擊時記錄的方式列表里展示符合條件的地址例如 tag 等于當(dāng)前入口的值支持刪除某條地址支持勾選某條地址并把選中 id 寫入selectedShippingId。這里給一個列表渲染與事件處理的示例let currentTag 由我享用; // 實際可根據(jù)頁面參數(shù)或點擊入口動態(tài)設(shè)置 function getAddressList() { return JSON.parse(localStorage.getItem(shippingAddresses) || []); } function getSelectedId() { return localStorage.getItem(selectedShippingId) || ; } // 渲染地址列表到容器 function renderAddressList() { const list getAddressList().filter(item item.tag currentTag); const selectedId getSelectedId(); const container document.getElementById(addressList); container.innerHTML list.map(item div classaddress-item label input typeradio nameselectedAddress value${item.id} ${item.id selectedId ? checked : } onchangeselectAddress(${item.id}) span${item.receiver} ${item.phone}/span span${item.province}${item.city}${item.district}${item.detail}/span /label button onclickdeleteAddress(${item.id})刪除/button /div ).join(); } // 勾選地址 function selectAddress(id) { localStorage.setItem(selectedShippingId, id); } // 刪除地址 function deleteAddress(id) { let list getAddressList(); list list.filter(item item.id ! id); localStorage.setItem(shippingAddresses, JSON.stringify(list)); // 如果刪除的是當(dāng)前選中項需要把選中項清空或重設(shè)為 null if (getSelectedId() id) { localStorage.removeItem(selectedShippingId); } renderAddressList(); }代碼說明通過tag過濾地址列表這樣“由我享用”入口和“送TA禮物”入口看到的列表是分開的使用 radio 單選更貼合“勾選一條地址去下單”的語義刪除時從數(shù)組中過濾掉對應(yīng)的 id如果刪掉的是當(dāng)前選中項需要同步清空selectedShippingId否則后續(xù)下單時會讀到已經(jīng)不復(fù)存在的地址renderAddressList里的onchange事件依賴selectAddress是全局函數(shù)如果你在模塊化開發(fā)中建議改成事件委托或綁定函數(shù)引用。4. 立即購買 與訂單確認(rèn)頁回填當(dāng)用戶點擊“立即購買”時需要把當(dāng)前選中的地址 id 和商品信息一起帶到訂單確認(rèn)頁。最簡做法有兩種URL query 傳參order.html?addressIdxxxskuId123sessionStorage 傳遞把訂單相關(guān)數(shù)據(jù)暫存到 sessionStorage由于商品詳情頁可能已經(jīng)存在于歷史棧中且訂單確認(rèn)頁刷新后 query 參數(shù)還在用 URL query 會更直觀。示例代碼function buyNow() { const selectedId localStorage.getItem(selectedShippingId); if (!selectedId) { alert(請先選擇收貨地址); return false; } // 攜帶地址 id 跳轉(zhuǎn)到訂單確認(rèn)頁 location.href ./orderConfirm.html?addressId selectedId skuId skuId; }訂單確認(rèn)頁側(cè)// 從 query 獲取 addressId function getQueryParam(key) { const url new URL(window.location.href); return url.searchParams.get(key); } function loadSelectedAddress() { const addressId getQueryParam(addressId); if (!addressId) return null; const list JSON.parse(localStorage.getItem(shippingAddresses) || []); const address list.find(item item.id addressId); if (address) { // 回填到訂單確認(rèn)頁的地址區(qū)域 showAddress(orderAddressEl, address); } else { alert(地址不存在或已被刪除請重新選擇); redirectToCart(); // 回到商品詳情頁重新選 } } function showAddress(el, address) { el.innerHTML div收貨人${address.receiver}/div div手機號${address.phone}/div div地址${address.province}${address.city}${address.district}${address.detail}/div div配送方式${address.deliveryType pickup ? 門店自提 : 快遞}/div ; }整體流程到這里就閉環(huán)了。訂單確認(rèn)頁提交訂單時也不需要額外傳地址直接從 localStorage 里根據(jù) addressId 再讀一次即可。5. 避坑要點這套方案整體不難但有幾個坑容易翻車提前注意radio 的 onchange 和 label 沖突在渲染時如果label包裹了input和文本在部分瀏覽器里點擊文本不會觸發(fā) radio 的 change 事件。建議在容器上用事件委托或者給label加onclick手動賦值。刪除當(dāng)前選中地址后沒有清空 selectedShippingId不刪除的話訂單確認(rèn)頁會 read 到一個不存在的地址導(dǎo)致回填缺失。上面的代碼里已經(jīng)處理但如果你用框架Vue/React需要在刪除時同步setSelectedId(null)。多個入口共用 localStorage 時的 key 沖突如果項目里其他地方也用shippingAddresses會互相覆蓋。建議給 key 加前綴例如mall_shipping_addresses。異步渲染時序問題如果你在 Vue 的mounted里讀取 localStorage注意renderAddressList要等在 DOM 渲染后再執(zhí)行或者用nextTick。否則事件綁定可能找不到元素。訂單確認(rèn)頁刷新后 addressId 還在但地址已被刪除頁面 load 時調(diào)用loadSelectedAddress發(fā)現(xiàn)查不到地址時要不就自動跳到商品詳情頁重新選要不彈窗提示。避免拿著一個失效的地址繼續(xù)提交。6. 擴展建議如果后續(xù)要對接真實接口這套前端方案可以平滑遷移刪除時調(diào)用后端接口刪除成功后再更新 localStorage保存地址時把后端返回的數(shù)據(jù)結(jié)構(gòu)如 addressId一并保存訂單確認(rèn)頁提交時向后端傳addressId后端再去查地址而不是信任前端傳的完整地址文本。純前端方案先跑通交互后續(xù)接后端只改數(shù)據(jù)源界面和流程不需要大改。希望這套最簡方案能幫到你有問題可以隨時對照調(diào)試。本文還有配套的精品資源點擊獲取