vue實(shí)現(xiàn)前端保持篩選條件到url并進(jìn)行同步參數(shù)設(shè)計(jì)
前言
在有列表頁的系統(tǒng)中,常常為了提高用戶體驗(yàn),需要保持列表頁的篩選條件、分頁情況。需要做到刷新頁面,從詳情頁返回列表頁保留之前的篩選情況。你可能會說 vue 用 keep-alive 緩存列表頁不就行了?為什么不好呢?
因?yàn)檎_的做法是將篩選條件保存在 url 上,這樣可以復(fù)制給別人直接使用,并且你可以看到幾乎所有網(wǎng)站都是使用這種方法。接下來會帶大家了解有關(guān) url 參數(shù)的基礎(chǔ)知識和設(shè)計(jì)思路。并且封裝成了一個(gè) hook vue-use-sync-url,歡迎在你的項(xiàng)目中直接使用。
基礎(chǔ)知識
假設(shè) url 上的參數(shù)為 ?a=1&a=2&b=true
,來看看獲取參數(shù)的方法
const searchParams = new URLSearchParams(window.location.search); // ["1", "2"] searchParams.getAll("a"); // "1" searchParams.get(a); // ["true"] searchParams.getAll(b); // "true" searchParams.get(b);
添加
searchParams.append("a", "1"); searchParams.append("a", "2"); // ?a=1&a=2 searchParams.set("b", "3"); searchParams.set("b", "4"); // ?b=4
從上面的結(jié)果可以得知,無論什么值最后都會被解析成 string
類型, 如果存在兩個(gè)名字相同的 key,則會被解析為 string[]
。 所以從 url 參數(shù)獲取到的類型只會為 string | string[]
。
最后使用 history.pushState 來修改瀏覽器地址欄的 url 參數(shù)。與 history.replaceState 不同的是,一個(gè)是添加一條新記錄,一個(gè)是替換。在這里我們當(dāng)然是選擇添加新記錄了。
設(shè)計(jì)思路
首先肯定要知道哪些值需要同步到 url 參數(shù)上,所以我們定義了一個(gè) configs
參數(shù),來配置需要同步的值。類型為數(shù)組,這樣可以讓用戶自定義順序,每項(xiàng)需要傳入一個(gè) key 值。
hook 內(nèi)部返回一個(gè) syncToUrl
方法,傳入包含配置的所有 key 的值。用戶可以在自己需要的時(shí)候同步 url。
const { syncToUrl } = useSyncUrl({ configs: [{ key: "title" }, { key: "status" }] }) // 同步 syncToUrl(values)
假設(shè) title
與輸入框綁定,且沒有值,傳入 syncToUrl
的是 ""
,這就沒有必要同步到 url 上了。所以我們添加一個(gè)配置 omitEmptyString
,如果值為空字符串,則忽略。
[{ key: "title", omitEmptyString: true }]
同理,可以增加 omitNull
、omitUndefined
。這三個(gè)默認(rèn)都設(shè)為 true
。
接下來,我們先明白兩個(gè)概念。在頁面第一次加載、執(zhí)行瀏覽器前進(jìn)回退操作時(shí),需要將 url 參數(shù)的值轉(zhuǎn)換到當(dāng)前頁面的組件中,在這里我們稱其為 decode
。
在頁面中篩選結(jié)束點(diǎn)擊提交或切換頁碼時(shí),需要將這些值轉(zhuǎn)換成參數(shù)并設(shè)置到 url 的參數(shù)上,在這里我們稱其為 encode
。
decode
了解后,我們就可以知道上面例子中 key: "status"
,可以想成是一個(gè) Select
組件,值為 boolean
類型。從基礎(chǔ)知識可以得知,從 url 取下來的值為 string
類型。 需要使用 decode
轉(zhuǎn)換成 boolean
類型。
const values = reactive({ title: "", status: false }); const booleanValues = { true: true, false: false, } const { syncToUrl } = useSyncUrl({ configs: [ { // title 的值是字符串類型,所以不需要 decode key: "title", }, { key: "status", // 參數(shù)是從 url 上 key 為 status 的值 decode: (value) => booleanValues[value] } ], onDecode: (params) => { Object.keys(params).forEach(key => { values[key] = params[key] }); // 設(shè)置完成后,在這里請求數(shù)據(jù) } })
在 decode
中,我們將值 return 出去,在 onDecode
中將每個(gè)配置項(xiàng)返回的值統(tǒng)一收集起來,設(shè)置完成后,請求列表數(shù)據(jù)。像 title
這種值本身是字符串的就不用寫 decode
。假設(shè) url 上的參數(shù)為 ?title=11&status=true
,這里的 params
的值就為
{ title: "11", status: true }
decode
也可以返回一個(gè)對象,如果是對象也會被收集到 onDecode
中。如果不想被收集,可以返回空對象 {}
。所以如果你想在 decode
中進(jìn)行賦值也可以,但要返回 {}
。
decode: (value) => { return { a: "1", b: "2" } } // 不會被收集 decode: (value) => { return {}; }
encode
const values = reactive({ rangeDate: ["2022-10-1", "2022-10-2"] }); useSyncUrl({ configs: [ { key: "rangeDate", encode: (value) => { return { starDate: value[0], endDate: value[1] } } } ] })
encode
可以將值轉(zhuǎn)換成你想要的格式同步到 url 上。這個(gè)例子中如果不寫 encode
,通過了解上面的基礎(chǔ)知識,則會被轉(zhuǎn)換成兩個(gè) rangeDate 的鍵值對。這里自定義轉(zhuǎn)換成了 starDate 和 endDate。所以還要配合 decode
使用。
decode: (value) => ...
但是這個(gè) value 返回的是 url 上 key 為 "rangeDate" 的值,我們要怎么 decode
starDate 和 endDate 呢?所以增加一個(gè)配置項(xiàng) decodeKeys
來實(shí)現(xiàn)。。
{ key: "rangeDate", decodeKeys: ["starDate", "endDate"], decode: value => { return { rangeDate: [value.starDate, value.endDate] } } }
通過上面基礎(chǔ)知識可以得知,url 的值只能為 string | string[]
,所以 encode
返回的值也只能是 EncodeResult | Record<string, EncodeResult>
。內(nèi)部將 number
和 boolean
轉(zhuǎn)換成了 string
。
type EncodeResult = string | number | boolean | (string | number | boolean)[];
這時(shí)候就有問題了,我想將一個(gè)比較復(fù)雜類型的值同步到 url 上怎么辦?這時(shí)候就要用到 encodeURIComponent
和 decodeURIComponent
了,如果你不認(rèn)識,可以上 MDN 學(xué)習(xí)。這里判定數(shù)據(jù)一定為正確的,實(shí)際使用中在 decode
這步中 JSON.parse 可能會報(bào)錯(cuò),你需要自行處理一下,因?yàn)?url 可能會被人為修改。
const values = reactive({ obj: { a: { b: { c: true } } }, }); const { syncToUrl } = useSyncUrl({ configs: [ { key: "obj", encode: (value) => encodeURIComponent(JSON.stringify(value)), decode: (value) => JSON.parse(decodeURIComponent(value)), }, ], });
詳情頁返回列表頁
假如你的詳情頁有一個(gè)按鈕點(diǎn)擊返回列表頁,要怎么保留上次的篩選條件呢?因?yàn)?vue-router
的 push 操作,不能直接傳 url 參數(shù)的字符串,只能傳對象,所以返回一個(gè)參數(shù)對象。
localStorage.setItem("listSearch", window.location.search); // 在詳情頁 router.push(`/list${localStorage.getItem("listSearch")}`) 或 const { searchParams } = useSyncUrl(...) localStorage.setItem("listSearch", JSON.stringify(searchParams)) // 在詳情頁 router.push({ path: "/list", query: JSON.parse(localStorage.getItem("listSearch")) })
結(jié)語
源碼放在 github 了,readme 中還有測試地址,可以來試一試。
以上就是vue實(shí)現(xiàn)前端保持篩選條件到url并進(jìn)行同步參數(shù)設(shè)計(jì)的詳細(xì)內(nèi)容,更多關(guān)于vue篩選條件url同步參數(shù)設(shè)計(jì)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue結(jié)合vue-electron創(chuàng)建應(yīng)用程序小結(jié)
這篇文章主要介紹了vue結(jié)合vue-electron創(chuàng)建應(yīng)用程序,本文給大家介紹了安裝electron有兩種方式,兩種方式創(chuàng)建的項(xiàng)目結(jié)構(gòu)大不相同,需要的朋友可以參考下2024-03-03Vue生命周期中的八個(gè)鉤子函數(shù)相機(jī)
這篇文章主要為大家介紹了Vue生命周期中的八個(gè)鉤子函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2021-12-12vue.js模版插值的原理與實(shí)現(xiàn)方法簡析
這篇文章主要介紹了vue.js模版插值的原理與實(shí)現(xiàn)方法,結(jié)合實(shí)例形式簡單分析了vue.js模板插值的基本功能、原理、實(shí)現(xiàn)方法與注意事項(xiàng),需要的朋友可以參考下2023-04-04antdv vue upload自定義上傳結(jié)合表單提交方式
這篇文章主要介紹了antdv vue upload自定義上傳結(jié)合表單提交方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10vue實(shí)現(xiàn)短信驗(yàn)證碼登錄功能(流程詳解)
無論是移動端還是pc端登錄或者注冊界面都會見到手機(jī)驗(yàn)證碼登錄這個(gè)功能,輸入手機(jī)號,得到驗(yàn)證碼,這篇文章主要介紹了基于vue實(shí)現(xiàn)短信驗(yàn)證碼登錄功能,需要的朋友可以參考下2019-12-12