欧美成人午夜精品久久久,国产?V天堂一区二区三区,欧美精品va在线观看,亚洲一区二区三区免费在线观看,av无码精品一区二区久久,欧美性爱视频不卡一区三区,欧美乱人伦视频在线观看,国产一级牲交高潮

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營的一線實(shí)戰(zhàn)洞察。

Vuex 4 狀態(tài)管理全解析:核心原理、模塊拆分與高頻踩坑

Vuex 4 狀態(tài)管理全解析:核心原理、模塊拆分與高頻踩坑 Vuex 這玩意兒現(xiàn)在提起來有點(diǎn)微妙。新項(xiàng)目里 Pinia 基本是默認(rèn)選項(xiàng)很多人一上手 Vue 3 就沒碰過 Vuex。但你去翻一翻手上維護(hù)的那些跑了三四年的中后臺系統(tǒng)十有八九還在store/index.js里躺著幾十個 mutation改一個字段要先找 action、再找 mutation、最后才敢動 state。這時候你要是連 Vuex 的執(zhí)行鏈路都說不清楚排查問題基本靠猜。這篇就把 Vuex 的知識點(diǎn)掰開揉碎講透從“到底什么時候該用它”到“store 怎么拆模塊”再到“為什么我的 commit 沒生效”這類真實(shí)踩坑全部過一遍。適合兩類人看一類是剛接手老項(xiàng)目、被mapState和各種root: true繞暈的新手另一類是想把狀態(tài)管理這塊徹底搞清楚、以后不管換 Pinia 還是別的庫都能快速上手的同學(xué)。代碼以 Vuex 4 Vue 3 為主線涉及 Vue 2 的差異我會單獨(dú)標(biāo)出來。1. 先搞清楚什么時候真的需要 Vuex1.1 狀態(tài)管理的邊界到底在哪我在帶人的時候發(fā)現(xiàn)一個特別普遍的問題很多人學(xué)完 Vuex 的第一反應(yīng)是“好東西全塞進(jìn)去”。結(jié)果一個只有三個頁面的小工具store 里堆了二十多個字段其中一半是某個組件內(nèi)部的彈窗開關(guān)。這就屬于把狀態(tài)管理當(dāng)成了全局變量倉庫最后維護(hù)成本比不用還高。判斷一個狀態(tài)該不該進(jìn) store我一般看三條第一這份數(shù)據(jù)是不是被兩個以上互不相鄰的組件同時使用。父子組件之間傳值props加emit就夠了爺孫層級深一點(diǎn)provide/inject也能解決。只有當(dāng)兄弟組件、或者跨了好幾層的遠(yuǎn)房親戚都要讀寫同一份數(shù)據(jù)時才輪到 Vuex 出場。第二這份數(shù)據(jù)是不是跨越了路由。比如登錄態(tài)、用戶信息、權(quán)限菜單從 A 頁面跳到 B 頁面還得用這種放在組件里必然會隨著組件銷毀而丟失必須提上去。第三這份數(shù)據(jù)變更后是不是需要留下可追溯的痕跡。Vuex 配 devtools 能記錄每一次 mutation 的時間旅行對于復(fù)雜的表單聯(lián)動、購物車增刪改這個調(diào)試能力值不少時間。反過來說哪些不該進(jìn) store組件的 loading 狀態(tài)、某個列表的滾動位置、彈窗的顯隱開關(guān)這些都屬于“局部狀態(tài)”跟著組件生命周期走才是最干凈的。我見過有人把dialogVisible放進(jìn) store結(jié)果兩個頁面復(fù)用同一個彈窗組件時互相干擾排查了半天才發(fā)現(xiàn)是狀態(tài)被共享了。記住一句話狀態(tài)放得越高耦合就越重能不升就不升。還有一種常見誤區(qū)是把接口返回的原始數(shù)據(jù)全量塞進(jìn) store然后組件里再filter一遍。這樣做的問題在于 store 變成了緩存層但你又沒做失效策略最后數(shù)據(jù)新舊不一致的 bug 特別難查。我的習(xí)慣是 store 只存“經(jīng)過業(yè)務(wù)加工、有明確語義”的狀態(tài)原始響應(yīng)體在 action 里處理完就丟掉。1.2 Vuex 和 Pinia 到底怎么選這個話題繞不開。Pinia 確實(shí)是官方現(xiàn)在主推的方案API 更簡潔、TypeScript 支持更好、沒有 mutation 這一層。但“新項(xiàng)目用 Pinia”不等于“Vuex 就沒用了”。我整理了一張對照表你對著自己項(xiàng)目的情況看就行。對比維度Vuex 4Pinia變更入口mutation 提交action 觸發(fā)直接改 stateaction 里也能改模塊機(jī)制modules namespaced 嵌套每個 store 天然獨(dú)立TypeScript 支持需要額外類型聲明較繁瑣原生推導(dǎo)幾乎零配置devtools 時間旅行支持粒度到 mutation支持粒度到 action代碼量一個功能要寫 state/getter/mutation/action 四份基本一份 setup 或 option 就夠?qū)W習(xí)曲線概念多鏈路長概念少接近組合式函數(shù)存量項(xiàng)目兼容原生可與 Vuex 共存逐模塊遷移適合場景老項(xiàng)目維護(hù)、團(tuán)隊(duì)已有約定新項(xiàng)目、TS 重度使用我的實(shí)際經(jīng)驗(yàn)是已經(jīng)在跑的 Vuex 項(xiàng)目別為了追新去動它。遷移本身不難難的是遷移期間兩套狀態(tài)管理并存帶來的心智負(fù)擔(dān)以及測試覆蓋不足時的回歸風(fēng)險。真要遷也是按模塊一個個搬先把用戶模塊搬過去跑一周沒問題再搬下一個。反倒是新起的項(xiàng)目沒有歷史包袱直接上 Pinia 更省事。不過有一點(diǎn)要說清楚Vuex 那套“mutation 必須同步、action 處理異步”的約束雖然寫起來啰嗦但它強(qiáng)迫你把“改數(shù)據(jù)”和“做業(yè)務(wù)”分開這個思維在團(tuán)隊(duì)協(xié)作里是有價值的。很多 Pinia 新手直接在 action 里一頓this.xxx yyy出了問題連是哪一步改的都定位不到。所以就算你用的是 Pinia也建議保留“純函數(shù)式改狀態(tài)”的習(xí)慣。1.3 一張判斷清單幫你決定要不要引入我給自己團(tuán)隊(duì)寫過一個很土但很好用的清單五個問題中三個以上才考慮上 Vuex有沒有一份數(shù)據(jù)被三個以上的組件讀取且這些組件不在同一條父子鏈上這份數(shù)據(jù)會不會因?yàn)槁酚汕袚Q而需要保留這份數(shù)據(jù)的修改是否需要多人協(xié)作、且改動點(diǎn)分散在多個文件出問題時是否需要回放“誰在什么時候改了什么”項(xiàng)目規(guī)模是不是已經(jīng)超過二十個頁面或者五個以上的業(yè)務(wù)模塊如果只中一兩條老老實(shí)實(shí)用props加組合式函數(shù)封裝別給自己找事。狀態(tài)管理的本質(zhì)是降低溝通成本不是炫技。2. Vuex 的五個核心概念一次捋直2.1 state單一狀態(tài)樹和它的設(shè)計原則Vuex 把所有狀態(tài)收攏到一棵樹里官方叫單一狀態(tài)樹Single Source of Truth。好處是任何一個時刻你都能通過store.state拿到應(yīng)用完整的數(shù)據(jù)快照調(diào)試的時候特別直觀。壞處是這棵樹如果沒人管長到幾百個字段之后新人進(jìn)來根本看不懂哪個字段屬于哪個業(yè)務(wù)。我的做法是按業(yè)務(wù)域切分而不是按數(shù)據(jù)類型切分。什么叫按數(shù)據(jù)類型切就是state.list、state.detail、state.loading這么平鋪看著整齊實(shí)際上一旦業(yè)務(wù)變多就全亂。按業(yè)務(wù)域切就是user、order、permission各占一塊每個模塊自洽。具體到寫法Vuex 4 里定義模塊的 state 一定要用函數(shù)返回對象// store/modules/user.js const state () ({ profile: null, token: , roles: [], permissionLoaded: false })為什么必須是函數(shù)因?yàn)槟K在注冊時會被合并進(jìn)根 state如果直接寫對象字面量多個組件實(shí)例或者熱更新場景下會共享同一份引用出現(xiàn)“A 頁面改了 B 頁面也變了”的靈異事件。這個坑我在服務(wù)端渲染的項(xiàng)目里踩過一次排查了整整一個下午。另外 state 里的字段命名要帶語義。data、info、list這種詞盡量別用orderList、userProfile、pendingTaskCount一眼就知道是什么。字段一多命名就是最好的文檔。2.2 getters派生狀態(tài)和它的緩存機(jī)制getters 可以理解為 store 里的 computed。它的返回值會基于依賴做緩存依賴不變就不重新計算。這個特性用好了能省不少性能用不好反而會成為 bug 來源。const getters { isLogin: state Boolean(state.token), displayName: state state.profile?.nickname || state.profile?.username || 未登錄, // 依賴其他 getter第二個參數(shù)是當(dāng)前模塊的 getters welcomeText: (state, getters) ${getters.displayName}歡迎回來, // 依賴根 state第四個參數(shù)是 rootState hasPermission: (state, getters, rootState) code { return state.roles.includes(code) || rootState.user.roles.includes(code) } }這里有個關(guān)鍵點(diǎn)getter 返回函數(shù)時緩存就失效了。上面hasPermission返回的是一個函數(shù)每次調(diào)用都會重新執(zhí)行因?yàn)?Vue 沒法追蹤函數(shù)內(nèi)部用到的參數(shù)。這種寫法適合做權(quán)限判斷這類需要傳參的場景但別在模板里高頻調(diào)用它尤其是列表渲染里v-for每一項(xiàng)都調(diào)一次性能會明顯下降。真要這么用先在 computed 里把結(jié)果算好。還有一個容易翻車的地方getter 里返回新對象。比如// 不推薦每次都返回新數(shù)組緩存形同虛設(shè) filteredList: state state.list.filter(item item.active)因?yàn)閒ilter每次執(zhí)行都會產(chǎn)生新數(shù)組引用Vue 的依賴追蹤會認(rèn)為結(jié)果變了導(dǎo)致依賴這個 getter 的組件反復(fù)更新。如果這個列表很大、更新又頻繁頁面會明顯卡頓。正確做法是把過濾邏輯放到組件 computed 里或者用shallowRef之類的思路做手動緩存。我在一個萬級數(shù)據(jù)的表格項(xiàng)目里就吃過這個虧后來把 getter 改成了只做簡單映射流暢度立刻回來了。2.3 mutations為什么它必須是同步的這是 Vuex 里被問得最多的問題?!拔揖驮?mutation 里發(fā)個請求怎么了”答案藏在 devtools 的工作原理里。devtools 記錄狀態(tài)變化的方式是每執(zhí)行一次 mutation就拍一張 state 的快照存進(jìn)時間線。如果你在 mutation 里發(fā)異步請求那么“mutation 開始執(zhí)行”和“state 真正被改”之間存在時間差devtools 拍到的那張快照可能是請求還沒回來的中間態(tài)。等你點(diǎn)時間旅行回到某一步看到的狀態(tài)和實(shí)際不符調(diào)試就徹底失去了意義。所以 Vuex 強(qiáng)制 mutation 同步是為了保證每一幀快照都是確定性的。const mutations { SET_PROFILE(state, payload) { state.profile payload }, SET_TOKEN(state, token) { state.token token }, ADD_ROLE(state, role) { if (!state.roles.includes(role)) { state.roles.push(role) } }, RESET(state) { // 重置時不要直接替換整個 state 對象Vue 會丟失響應(yīng)式追蹤 Object.assign(state, { profile: null, token: , roles: [], permissionLoaded: false }) } }mutation 的命名我統(tǒng)一用全大寫加下劃線這是社區(qū)慣例好處是在 devtools 列表里一眼就能和 action 區(qū)分開。action 用小駝峰比如fetchProfile。這套約定看起來是小事但團(tuán)隊(duì)人多的時候能省掉很多溝通。還有一個細(xì)節(jié)mutation 里不要做副作用。什么叫副作用發(fā)請求、寫 localStorage、彈 toast這些都算。mutation 應(yīng)該是一個純函數(shù)給它同樣的輸入state 就變成同樣的結(jié)果。這樣你寫單元測試的時候只需要斷言 state 變化不用 mock 一堆東西。2.4 actions異步編排和業(yè)務(wù)邏輯的落腳點(diǎn)action 是 Vuex 里唯一允許寫異步的地方它不直接改 state而是通過commit觸發(fā) mutation。這個設(shè)計看起來多繞了一層實(shí)際上把“業(yè)務(wù)流程”和“數(shù)據(jù)變更”解耦了。const actions { async fetchProfile({ commit, state, dispatch }, force false) { if (state.profile !force) { return state.profile } const res await api.getUserProfile() commit(SET_PROFILE, res.data) // 跨模塊調(diào)用要加 root: true await dispatch(permission/loadRoutes, res.data.roles, { root: true }) return res.data }, async login({ commit, dispatch }, { username, password }) { const { token } await api.login({ username, password }) commit(SET_TOKEN, token) await dispatch(fetchProfile, true) }, logout({ commit }) { commit(RESET) commit(permission/RESET, null, { root: true }) } }action 的返回值很重要。因?yàn)?action 內(nèi)部是 Promise你可以在組件里await store.dispatch(login, form)拿到結(jié)果后再做跳轉(zhuǎn)或者提示。很多老代碼里 action 不 return組件只能靠 watch 某個 state 來判斷成功與否這種寫法非常脆弱。養(yǎng)成習(xí)慣action 有結(jié)果就 return 出去??缒K dispatch 的{ root: true }是新手最容易漏的參數(shù)。不加這個參數(shù)Vuex 會只在當(dāng)前模塊內(nèi)查找 action找不到就靜默失敗或者報unknown action type。我第一次遇到的時候盯著代碼看了半小時最后發(fā)現(xiàn)就是少了個 root。2.5 modules 和 namespaced拆分與隔離項(xiàng)目一大單文件 store 必然爆炸。modules 就是用來拆的而namespaced: true決定了拆完之后彼此是否隔離。// store/index.js import { createStore } from vuex import user from ./modules/user import permission from ./modules/permission import cart from ./modules/cart export default createStore({ strict: import.meta.env.DEV, modules: { user: { namespaced: true, ...user }, permission: { namespaced: true, ...permission }, cart: { namespaced: true, ...cart } } })開不開命名空間我的答案是業(yè)務(wù)模塊一律開。不開的話所有模塊的 mutation 都注冊在全局兩個模塊都定義了SET_LOADING后注冊的會覆蓋前一個這種 bug 隱蔽性極強(qiáng)。開了之后方法名變成user/SET_LOADING雖然寫起來長一點(diǎn)但邊界清晰。全局的通用狀態(tài)比如 app 級別的主題、語言可以單開一個不開命名空間的 root 模塊但數(shù)量要克制。嵌套模塊的調(diào)用鏈路也要理清楚。假設(shè)有個setting模塊掛在user下面那么在setting的 action 里調(diào)用兄弟模塊路徑要寫成dispatch(cart/addItem, item, { root: true })。這個 root 參數(shù)指的是“從根開始找”不管你現(xiàn)在在哪一層。記不住的話就記一句只要跨出當(dāng)前模塊就帶 root: true。3. 從零搭一個能落地的 Store 結(jié)構(gòu)3.1 目錄設(shè)計和模塊拆分原則先看目錄這是我用了幾年、覺得最不容易亂的一種src/ ├── store/ │ ├── index.js // 入口注冊模塊和插件 │ ├── plugins/ │ │ └── persist.js // 持久化插件 │ ├── modules/ │ │ ├── user.js // 用戶信息、登錄態(tài) │ │ ├── permission.js // 路由權(quán)限、菜單 │ │ └── cart.js // 業(yè)務(wù)模塊示例 │ └── helpers.js // 通用工具比如生成 mutation types拆分粒度怎么定我的一般原則是一個模塊對應(yīng)一個業(yè)務(wù)域而不是一個頁面。比如訂單列表和訂單詳情都屬于 order 模塊不要拆成兩個。反過來用戶和權(quán)限雖然是相關(guān)的但職責(zé)不同用戶管“我是誰”權(quán)限管“我能看什么”拆開更好維護(hù)。模塊內(nèi)部的結(jié)構(gòu)我習(xí)慣按state → getters → mutations → actions → 導(dǎo)出的順序?qū)懞?Vuex 的執(zhí)行鏈路一致讀代碼的人從上往下看正好是數(shù)據(jù)流向。文件末尾統(tǒng)一導(dǎo)出export default { namespaced: true, state, getters, mutations, actions }有一點(diǎn)要注意如果模塊之間有數(shù)據(jù)依賴不要在模塊文件里直接import另一個模塊的 state那樣會造成循環(huán)依賴。正確方式是通過rootState讀取或者用dispatch讓對方的 action 來處理。3.2 完整實(shí)現(xiàn)一個購物車模塊光說概念沒意思直接上一個能跑的。假設(shè)我們要做一個購物車需求是加商品、改數(shù)量、刪除、算總價、選中狀態(tài)管理。// store/modules/cart.js const state () ({ items: [], // { id, name, price, count, checked } submitting: false }) const getters { totalCount: state state.items.reduce((sum, i) sum i.count, 0), checkedItems: state state.items.filter(i i.checked), totalPrice: (state, getters) { // 金額用分做單位避免浮點(diǎn)誤差最后再除以 100 const cents getters.checkedItems.reduce((sum, i) sum i.price * 100 * i.count, 0) return cents / 100 }, isAllChecked: state state.items.length 0 state.items.every(i i.checked) } const mutations { ADD_ITEM(state, product) { const exist state.items.find(i i.id product.id) if (exist) { exist.count 1 } else { state.items.push({ ...product, count: 1, checked: true }) } }, UPDATE_COUNT(state, { id, count }) { const item state.items.find(i i.id id) if (item) { item.count Math.max(1, Math.min(99, count)) } }, TOGGLE_CHECK(state, id) { const item state.items.find(i i.id id) if (item) item.checked !item.checked }, TOGGLE_ALL(state, checked) { state.items.forEach(i { i.checked checked }) }, REMOVE_ITEM(state, id) { state.items state.items.filter(i i.id ! id) }, SET_SUBMITTING(state, flag) { state.submitting flag }, CLEAR(state) { state.items [] } } const actions { async checkout({ commit, state, rootState }) { if (!state.items.length) return { ok: false, msg: 購物車是空的 } const payload state.items .filter(i i.checked) .map(i ({ productId: i.id, count: i.count })) commit(SET_SUBMITTING, true) try { const res await api.submitOrder({ items: payload, userId: rootState.user.profile?.id }) commit(REMOVE_ITEM_BATCH, res.data.removedIds) return { ok: true, orderId: res.data.orderId } } catch (e) { return { ok: false, msg: e.message } } finally { commit(SET_SUBMITTING, false) } } } export default { namespaced: true, state, getters, mutations, actions }這里有幾個我自己踩過坑之后固定下來的寫法。金額全部用“分”來算最后展示時再轉(zhuǎn)回元0.1 0.2那種經(jīng)典浮點(diǎn)問題在電商場景真的會出事。數(shù)量做了Math.max(1, Math.min(99, count))的鉗制防止用戶在輸入框里手打負(fù)號或者超大批量。checkout的返回值統(tǒng)一成{ ok, msg }結(jié)構(gòu)組件層不用 try-catch直接看ok就行。另外REMOVE_ITEM_BATCH我在 mutations 里沒寫實(shí)際項(xiàng)目中應(yīng)該補(bǔ)上避免循環(huán)提交單條刪除。這類細(xì)節(jié)在真實(shí)業(yè)務(wù)里會因?yàn)榕坎僮鲗?dǎo)致幾十次 commitdevtools 面板直接被刷屏。3.3 組件里怎么調(diào)用四種方式對比Vuex 提供的調(diào)用方式有好幾種很多人只會mapState遇到方法就不知道咋辦了。列個表對照著記場景選項(xiàng)式寫法組合式寫法setup讀 statecomputed(() this.$store.state.user.profile)const profile computed(() store.state.user.profile)讀 getterthis.$store.getters[user/isLogin]computed(() store.getters[user/isLogin])觸發(fā) mutationthis.$store.commit(user/SET_TOKEN, t)store.commit(user/SET_TOKEN, t)觸發(fā) actionawait this.$store.dispatch(user/login, f)await store.dispatch(user/login, f)批量映射...mapState(user, [profile])storeToRefs(store.state.user)配合解構(gòu)組合式 API 里推薦用useStore加storeToRefsimport { computed } from vue import { useStore } from vuex import { storeToRefs } from pinia // 注意Vuex 沒有官方 storeToRefs這里用 toRefs 替代 export default { setup() { const store useStore() // 直接解構(gòu)會丟失響應(yīng)式必須轉(zhuǎn)成 ref const { profile, token } toRefs(store.state.user) const isLogin computed(() store.getters[user/isLogin]) function handleAdd(product) { store.commit(cart/ADD_ITEM, product) } return { profile, token, isLogin, handleAdd } } }補(bǔ)充一句上面代碼里storeToRefs是 Pinia 的 APIVuex 項(xiàng)目要用 Vue 的toRefs配合store.state.模塊名。這個區(qū)別我見過不止一個人寫混。toRefs只能處理普通響應(yīng)式對象store.state本身就是響應(yīng)式的所以能用但store.getters不行因?yàn)?getters 是每次訪問時動態(tài)計算的得用computed包一層。選項(xiàng)式 API 里用輔助函數(shù)會簡潔很多import { mapState, mapGetters, mapActions } from vuex export default { computed: { ...mapState(cart, [items, submitting]), ...mapGetters(cart, [totalPrice, isAllChecked]), // 自己再算的派生值 isEmpty() { return this.items.length 0 } }, methods: { ...mapActions(cart, [checkout]), async onSubmit() { const res await this.checkout() if (res.ok) { // 跳轉(zhuǎn)邏輯 } } } }有個小坑要提醒mapState映射出來的名字如果和組件data里的字段重名Vue 會告警而且行為不確定。命名的時候盡量錯開或者在映射時用對象形式重命名...mapState(cart, { cartItems: items })。3.4 嚴(yán)格模式、持久化插件和 devtools 配置嚴(yán)格模式我強(qiáng)烈建議只在開發(fā)環(huán)境開const store createStore({ strict: import.meta.env.DEV, modules: { ... } })嚴(yán)格模式下任何不經(jīng)過 mutation 的 state 修改都會拋錯[vuex] do not mutate vuex store state outside mutation handlers。這個檢查很耗性能因?yàn)樗枰疃缺O(jiān)聽整棵 state 樹。生產(chǎn)環(huán)境開嚴(yán)格模式在大型應(yīng)用里能明顯感覺到卡頓。用 Vite 的話import.meta.env.DEV就是現(xiàn)成的webpack 環(huán)境用process.env.NODE_ENV ! production。持久化這塊Vuex 本身不提供社區(qū)有插件但也都不太維護(hù)了我一般手寫一個三十行的插件// store/plugins/persist.js const KEY APP_STORE_V1 export default function createPersistPlugin(paths []) { return store { // 恢復(fù) const raw localStorage.getItem(KEY) if (raw) { try { const saved JSON.parse(raw) paths.forEach(path { const [module, field] path.split(/) const target module ? store.state[module] : store.state if (saved[path] ! undefined) { target[field] saved[path] } }) } catch (e) { localStorage.removeItem(KEY) } } // 保存做節(jié)流避免頻繁寫入 let timer null store.subscribe((mutation, state) { clearTimeout(timer) timer setTimeout(() { const data {} paths.forEach(path { const [module, field] path.split(/) const target module ? state[module] : state data[path] target?.[field] }) localStorage.setItem(KEY, JSON.stringify(data)) }, 300) }) } }用它的時候只白名單需要的字段createStore({ plugins: [createPersistPlugin([user/token, cart/items])] })為什么只白名單而不是全量存因?yàn)閟ubmitting、loading這類瞬時狀態(tài)被持久化下來刷新頁面后按鈕會一直處于 loading 狀態(tài)用戶以為卡死了。我見過一個項(xiàng)目把整個 store 都存了 localStorage結(jié)果用戶重新打開頁面上次沒提交完的表單數(shù)據(jù)混著新數(shù)據(jù)出現(xiàn)問題反饋了一堆。4. 高頻踩坑與排查實(shí)錄4.1 報錯信息對照表先會看再看懂Vuex 的報錯信息其實(shí)寫得挺清楚只是新手不知道往哪查。整理一張表遇到問題先對號入座報錯內(nèi)容大概率原因處理方式[vuex] unknown mutation type: xxx模塊沒開 namespaced或漏寫模塊前綴檢查模塊配置commit 時補(bǔ)上模塊名/[vuex] unknown action type: xxx跨模塊調(diào)用漏了{(lán) root: true }dispatch 第三個參數(shù)加上 root[vuex] unknown getter: xxxgetters 沒導(dǎo)出或訪問路徑錯確認(rèn) export default 里有 gettersdo not mutate vuex store state outside mutation handlers開發(fā)環(huán)境嚴(yán)格模式直接改了 state把所有賦值搬進(jìn) mutation[vuex] module namespace not found in mapState()模塊名拼錯或模塊還沒注冊檢查 createStore 的 modules 鍵名Cannot read property xxx of undefined模塊 state 寫成了對象但被復(fù)用state 改成函數(shù)返回數(shù)據(jù)改了但頁面沒更新直接改數(shù)組下標(biāo)或?qū)ο笮略鰧傩杂?mutation 里整體替換或Vue.setVue 2這張表我自己貼在工位旁邊貼了兩年新人來的時候直接拍照。說實(shí)話Vuex 報錯里 80% 都是“路徑寫錯”或者“沒開命名空間”這兩類剩下 20% 是響應(yīng)式丟失。4.2 響應(yīng)式丟失的幾種典型情況Vue 2 時代最經(jīng)典的問題state.list[0] newItem頁面不更新。原因是Object.defineProperty攔截不到數(shù)組下標(biāo)賦值。Vue 3 換成 Proxy 之后這個問題基本解決了但如果你維護(hù)的是 Vue 2 Vuex 3 的項(xiàng)目還是得注意數(shù)組按下標(biāo)賦值用splice或者整體替換數(shù)組對象新增屬性用Vue.set(obj, key, val)刪除屬性用Vue.delete(obj, key)Vue 3 里雖然 Proxy 能攔截新增和刪除但還是有兩個容易忽略的點(diǎn)。一是reactive對象被解構(gòu)之后失去響應(yīng)式比如const { profile } store.state.user后面profile就是普通對象了怎么改頁面都不動。二是把 state 里的對象直接賦給組件里的變量做雙向綁定v-model一改就直接改了 state繞過 mutation開發(fā)環(huán)境立刻報嚴(yán)格模式錯誤。正確的v-model寫法是這樣computed: { keyword: { get() { return this.$store.state.cart.keyword }, set(val) { this.$store.commit(cart/SET_KEYWORD, val) } } }啰嗦是啰嗦但這條鏈路是完整的devtools 能記錄到每一次輸入。如果嫌麻煩就在組件內(nèi)用本地 ref提交時再一次性寫回 store。4.3 性能問題什么時候 store 成了瓶頸Vuex 的性能問題我遇到過的就那么幾類但每一類都很要命。第一類是大列表全量放進(jìn) store。有個項(xiàng)目把五千條訂單數(shù)據(jù)放在 state 里每次篩選都要經(jīng)過 getter頁面卡得沒法用。后來改成 store 只存篩選條件列表數(shù)據(jù)留在組件里通過 action 拿問題立刻解決。記住store 適合存“狀態(tài)”不適合存“數(shù)據(jù)集合”。第二類是在 getter 里做重計算。比如對列表做排序、格式化日期、算分組小計這些操作如果依賴頻繁變化getter 會被反復(fù)觸發(fā)。我的做法是把這類計算移到組件 computed或者在 store 里緩存一份計算結(jié)果只在源數(shù)據(jù)變化時重算。第三類是過度訂閱。mapState把整個模塊的 state 都映射進(jìn)來其中某個字段高頻變化導(dǎo)致組件整體重新渲染。用computed精確取需要的字段能緩解一部分更好的辦法是把高頻變化的狀態(tài)比如輸入框的值、鼠標(biāo)坐標(biāo)留在組件本地不要進(jìn) store。還有一種不太容易發(fā)現(xiàn)的devtools 開著跑生產(chǎn)構(gòu)建。Vuex 的 devtools 集成在開發(fā)模式下才有但如果你不小心在生產(chǎn)包里引入了開發(fā)版本的 Vue性能會差好幾倍。打包配置里確認(rèn)一下mode和define有沒有問題這個坑我踩過一次找了一周。4.4 老項(xiàng)目遷移與工程化建議如果手上的 Vuex 項(xiàng)目要重構(gòu)我建議按這個順序推進(jìn)別一把梭。第一步先把所有this.$store的直接調(diào)用收斂成統(tǒng)一的 API 層。寫一個src/store/api.js把常用的讀寫封裝成函數(shù)比如useUser()、useCart()。這一步不改邏輯只是加一層殼風(fēng)險極低。第二步把模塊的 mutation 命名規(guī)范化。原來可能叫setUser、updateUser、changeUser統(tǒng)一成SET_USER。這一步靠grep加人工核對工作量不大但收益明顯后面遷移 Pinia 時一一對應(yīng)就能改。第三步按模塊遷移。先挑一個依賴最少的模塊比如cart改成 Pinia 的defineStore然后在入口同時注冊兩套。Vuex 和 Pinia 是可以共存的只要別讓同一個業(yè)務(wù)狀態(tài)兩邊都存就行。第四步清理。所有模塊遷完之后刪掉 Vuex 依賴把mapState之類的 import 全部替換。這一步用 ESLint 的自定義規(guī)則能掃出一部分剩下的靠編譯報錯兜底。遷移過程中有個細(xì)節(jié)值得說Pinia 的storeToRefs和 Vuex 的toRefs行為不完全一樣直接在組件里解構(gòu)很容易出問題。我當(dāng)時的做法是先把所有組件里的解構(gòu)都改成computed遷完之后再按需優(yōu)化。寧可多寫幾行也別在響應(yīng)式上翻車。5. 幾個真實(shí)場景下的套路組合5.1 登錄態(tài)與路由守衛(wèi)的配合登錄態(tài)是最典型的需要 store 的場景但它和路由守衛(wèi)的配合有個時序問題必須處理。守衛(wèi)在頁面渲染前執(zhí)行這時候如果 store 里的用戶信息還沒加載權(quán)限判斷就會失敗用戶被誤踢回登錄頁。我的處理方式是token 從 localStorage 同步恢復(fù)用戶信息異步加載但守衛(wèi)里做“是否已加載”的判斷沒加載就先觸發(fā) action 并等待。// permission.js router.beforeEach(async (to, from, next) { const store useStore() const token store.state.user.token if (!token) { return to.meta.public ? next() : next({ path: /login, query: { redirect: to.fullPath } }) } if (!store.state.user.permissionLoaded) { try { await store.dispatch(user/fetchProfile) await store.dispatch(permission/loadRoutes) } catch (e) { store.commit(user/RESET) return next(/login) } } if (to.meta.roles !store.getters[user/hasPermission](to.meta.roles)) { return next(/403) } next() })這里的關(guān)鍵是permissionLoaded這個標(biāo)記位。沒有它每次路由跳轉(zhuǎn)都要重新拉一次用戶信息接口壓力大不說頁面還會閃。有了它第一次加載完之后所有跳轉(zhuǎn)都是同步判斷體驗(yàn)就順了。異步路由用router.addRoute動態(tài)注冊注冊完再next({ ...to, replace: true })重新進(jìn)入一次否則會白屏。5.2 跨模塊協(xié)作別讓模塊之間互相 import項(xiàng)目一大模塊之間必然有協(xié)作。比如下單成功后要清空購物車、刷新訂單列表、更新用戶積分。這三件事分屬三個模塊怎么串起來最差的做法是在order模塊里import cart from ./cart然后直接調(diào)。這樣寫會形成循環(huán)依賴打包時可能報錯運(yùn)行時也可能拿到 undefined。正確做法是通過 action 互相 dispatch// order 模塊的 action async createOrder({ commit, dispatch }, payload) { const res await api.createOrder(payload) commit(ADD_ORDER, res.data) // 跨模塊通知各自處理各自的邏輯 await dispatch(cart/clearChecked, null, { root: true }) await dispatch(user/refreshPoints, null, { root: true }) return res.data }這樣order模塊不需要知道cart內(nèi)部怎么實(shí)現(xiàn)只要知道有這么個 action 就行。耦合度低測試也好寫。如果模塊數(shù)量多、協(xié)作關(guān)系復(fù)雜可以再引入一個“編排層”專門寫跨模塊的 action把業(yè)務(wù)流程集中在一處。還有個小技巧跨模塊讀取數(shù)據(jù)用 getters不要直接讀rootState.xxx.yyy。getters 是一層抽象將來內(nèi)部結(jié)構(gòu)變了只要 getter 的返回不變調(diào)用方就不用改。5.3 表單草稿和列表緩存的取舍后臺系統(tǒng)里最常見的兩個需求表單填一半切走了回來要恢復(fù)列表翻到第五頁點(diǎn)進(jìn)詳情再返回要停在第五頁。表單草稿我的做法是不進(jìn) store用sessionStorage加組件內(nèi)的watch做防抖保存。原因很簡單草稿是頁面級的狀態(tài)多個表單同時編輯時放 store 會互相干擾還要處理各種清理邏輯。sessionStorage 天然按標(biāo)簽頁隔離關(guān)掉就沒了符合直覺。列表緩存反而適合進(jìn) store。因?yàn)楹Y選條件、頁碼、排序方式這些是需要跨路由保留的而且詳情頁返回時要用。做法是在list模塊里存一份query對象列表頁onMounted時讀出來發(fā)起請求條件變化時同步更新。要注意的是從菜單重新點(diǎn)進(jìn)列表時應(yīng)該重置從詳情返回時應(yīng)該保留這個區(qū)分靠路由的meta.keepAlive或者判斷from路徑來做。const actions { async loadList({ state, commit }, { reset false } {}) { if (reset) { commit(RESET_QUERY) } const res await api.getList(state.query) commit(SET_LIST, res.data) } }reset參數(shù)由調(diào)用方?jīng)Q定模塊本身不猜。這種“讓調(diào)用方明確表達(dá)意圖”的設(shè)計比在模塊里寫一堆 if 判斷當(dāng)前路由要清晰得多。6. 我個人在實(shí)際項(xiàng)目里的幾點(diǎn)體會寫到這里Vuex 的主要知識點(diǎn)基本都覆蓋了。最后分享幾個不太適合寫進(jìn)文檔、但實(shí)際干活時確實(shí)管用的經(jīng)驗(yàn)。第一別怕寫重復(fù)代碼。Vuex 的四段式state/getters/mutations/actions看起來很啰嗦但每多寫一行將來排查問題時就少猜一次。我曾經(jīng)為了省事把 mutation 和 action 合并成一個函數(shù)結(jié)果 devtools 里全是匿名調(diào)用出問題時完全不知道是誰改的。后來老老實(shí)實(shí)拆開調(diào)試效率反而高了。第二給 store 加注釋比加文檔有用。每個模塊文件頂部寫清楚這個模塊管什么、依賴誰、被誰依賴比單獨(dú)維護(hù)一份文檔靠譜得多。文檔會過期代碼不會。我現(xiàn)在接手新項(xiàng)目第一件事就是看 store 模塊的頂部注釋五分鐘就能摸清業(yè)務(wù)脈絡(luò)。第三調(diào)試時善用 devtools 的 import/export。Vuex 面板可以把當(dāng)前狀態(tài)導(dǎo)出成 JSON也能導(dǎo)入一份狀態(tài)來復(fù)現(xiàn)問題。遇到用戶反饋的詭異 bug讓對方導(dǎo)出一份狀態(tài)文件本地導(dǎo)入后就能完全復(fù)現(xiàn)當(dāng)時的場景比反復(fù)溝通效率高太多。這個功能知道的人不多但真的好用。第四測試只測 action 和 getter。state 和 mutation 太簡單測了也是形式主義。真正有價值的是 action 里的業(yè)務(wù)流程和 getter 里的計算邏輯這兩塊寫單測覆蓋率能上一個大臺階。測 action 的時候記得 mock 掉commit和dispatch用jest.fn()或者vi.fn()都行斷言調(diào)用參數(shù)就夠了。最后提一句狀態(tài)管理這塊工具會換但“什么狀態(tài)該放在哪一層、變更走什么路徑、如何保證可追溯”這三個問題不會變。把 Vuex 這套東西吃透換成 Pinia、換成任何別的方案思路都是通用的。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
欧美视频五区| 国产精品涩涩涩视频网站| 精品国产va久久久久| 五月激情天| 色婷婷六月精品| 色婷婷亚洲综合av| 亚洲黄网AV| 9月色婷婷| 亚洲 激情 中文| 中文字幕婷婷在线| 97婷婷五月丁香| 婷婷丁香五另类网站| 亚洲欧洲自拍图片专区五月天| 亚洲啪啪精品| www.99精品日操伊人乱碰在线| 婷婷五月天视频| 日韩一区二区在线播放| 超碰精品在线| 日韩欧美一级大黄网站| xx久久| 国产肥白大熟妇BBBB视频| 色婷婷亚洲婷婷在线观看| 亚洲综合新99视频| 青青草性爱视频| 综合玖玖偷拍| 97五月天婷婷综合激情网| 狠狠色丁香| 啪啪 综合网| 天天天天天操| 欧美天天干五月丁香| 色九月欧美| 亚洲丁香花五月丁香花| 五月丁香婷婷成人网| 久久久www| 丁香五月婷婷色| 色五月激情五月丁香五月婷婷啪啪综合 | 五月天无码| 人人操 色| 超碰成人公开| 大香蕉视频99| 国产在线视频1234| 久婷自拍视频| 久久婷婷婷| 大香蕉人人网| 伊人婷婷大香蕉| 大香蕉丁香| 碰人人97| 99超级碰碰| 91AV视频| 日本色天堂| 久婷婷五月综合欧美| 欧美激情 日韩无码 婷婷 五月天| 欧美精品XXXXBBBB| 久久爱综合| 色天使色综合| 五月丁香综合在线| 思思热思在线精品视频| 精品成人无码A片观看香草视频| 综合狠狠五月婷婷| 婷婷五月天精品| 深情五月天| 婷婷五月丁香网| 欧美日韩aaaa| 久久99婷婷| 97视频91| 开心五月色婷婷综合开心网| 在线日本www| 微拍92| 国产三级在线播放| 亚洲高清在线| 国产一区男女| 五月天婷婷色色网| 国产熟妇的荡欲午夜视频| 国外亚洲成AV人片在线观看| 色99免费视频中文| 精品乱码视频| 婷婷五月天激情五月天网站| 99碰网站| 99久| 婷婷成人网五月天| 五月天综合在线观看视频| 色99在线观看| 日本人妻伦在线中文字幕| 亚洲乱码日产精品BD| 婷婷五月天 丁香五月天 裸体 | 色五月av伊人| 婷婷五月天电影区小说区| 九九热视| 亚洲日韩一页精品发布| 国产成人AV在线播放| 日韩影院三级| 亚洲精品午夜国产va久久成人| 天天爽天天爽| 久草九一| 狠狠色五月激情| 丁香五月六月激情| 伊人婷婷五月天| 色色综合网www| 人人插9| 激情综合五月婷| 99视频精品8| 99热在线观看免费精品| 日韩乱轮AV| 第四色大香蕉| 五月激情婷婷开心| 婷婷色综合| 亚洲AV无码电影| 五月丁香六月婷婷啪啪| 97色色综合| CHINESE熟女老女人HD视频| 超碰免费观看| 欧美天天性| 另类图片激情五月| 色五月婷婷天堂| 婷婷伊在线| 亚洲婷婷免费| 色啪久| 色色操| 吉澤明步Av一區二區| 狠狠插狠狠操| 无码啪啪| 亚洲操逼网| 香蕉视频性爱BB做爱| 在线五月婷婷小电影| 五月综合婷婷五月| 丁香六月综合| 操射国产日本| 婷婷天堂综合网| 新久久五月天激情| 大香蕉久| 人妻射精AV| 欧美日韩成人高清在线| 色婷婷综合丁香五月天| 亚洲天天| 色综合香蕉| 婷婷丁香五月天狠狠| 九九99久久| 琪琪色热色色| 99在线69| 成人五月天综合网| 亚洲综合激情五月久久| 女人天堂av| 99这里只有精品|v| 天天五月香欧美| www色婷婷| 97碰成超视频免费视频| 丁香五月区| 欧美在线视频9| 婷婷涩五月天综合| 91精品啪| 丁香六月婷婷综合| 99 re视频一区| 天天干天天操天天拍| 免费超碰在线观看| 这里只有精品网| 色亭亭九月| 99人人操人人摸| 五月婷婷电影院| 婷婷五月丁香伊人网| AV电影在线播放| 婷婷丁香社区网| 夜夜爽天天干| 九九热免费| 国产精品久久久久久妇女6080| 凹凸探花电影| 一级韩国产精品毛| 五月天婷婷免费| 99ri国产在线| 国产精品99久久久久久久女警 | 久久狠狠干| 91互操| 丁香伊人网| 人人操日| 六月婷婷综合| 丁香五月婷婷亚洲激情四射| 国产精品视频免费看| Caop在线| 天天射影院| 婷五月天在线草| 久久人妻熟女一区二区| 99热这里有精品| www.五月婷婷.com| 亚洲激情四射色| 九九九九这里只有精品| 综合色99| 亚洲正能量欧美| www.色婷婷.com| 日本色色色| 999九九九久久久99HD| 丁香五月婷婷在线观看| 天天做天天视天天谢| 免费无码毛片一区二区A片| 天插天啪天啪天啪| 五月天婷婷香蕉狠狠超碰综合| 天天狠狠夜夜狠狠2023| 五月激情久久综合网| 五月综合丁| 久久久久激情| 五月色网| 五月婷婷内射网| 久久电影五月天丁香电影| 婷婷五月天天爽| 人人爽在线视频综合网| 在线天堂9| 久久久久人妻| 亚洲五月婷婷| 色色色色网站| 99免费视频精品| 操逼三区| 亚洲成人av在线观看 | 五月丁香自拍| 丁香婷婷六月在线资源观看| 思思热99er在线视频| 丝雨一区二区| 超喷97免费在线视频| 99久精品视频| 色五月天成人| 欧美va欧美va差| 久久婷婷五月天| 在线不卡的视频| 婷婷深爱五月| 97视频久久| 丁香婷婷啪啪啪| 99热超碰在线| 97人人做| 丁香五月欧美激情| 久久在线大香蕉| 精品久久久久成人码免费动漫 | 久久99久久99久久99人受| 五月丁香综合激情| 激情综合色婷婷六月天| 这里只有精品在线免费视频| 日日操,日日爽| 久久婷婷色| 97久操| 怡红院AV亚洲一区二区三区H| 丁香婷婷色情| 色五月色图| 激情丁香图片| 美女五月狠狠| 狠狠干,狠狠操| 六月丁香婷婷尤物| 亚洲mm色| 九六五月天婷婷| 久婷| 色五月综合资源推荐| 五月丁香六月情婷婷久久| 久久色五月天| 五月天婷婷青青| 99久热这里只有精品视频删减版| 婷婷香蕉| 五月天亚洲最大成人| 大香蕉久久| 99精品视频偷拍| www.91AV.COM| www.9797国产| 九九五月天| 性色婷婷| 五月丁香色婷婷伊人| 婷婷天堂综合| 操操操av| 精品久久久久久久人妻| 色色色色av色色色色| 激情性五月天免费小说视频| 国产欧洲欧洲精品久久| 色婷婷狠| 风流少妇A片一区二区蜜桃| 国产成人网站在线观看| 国产熟妇乱子伦hd| 婷婷综合伊人| 婷婷久久亚洲| 爱草视频在线| 婷婷国产成人| 人人摸人人摸| 婷婷五月激情黄色| 性爱激情小说AV五月丁香花| 九月丁香| www五月天激情com| 99视频网址| 五月综合丁香婷婷| 蜜桃人妻无码AV天堂三区| AA片在线观看视频在线播放| 激情婷婷22月间| 婷婷丁香五月天操逼| 久久中国毛毛片爱久久| 免费AV播放| 婷婷丁香久久五月综合| 久久九九热视频| 日韩黄色电影| 777精品久无码人妻蜜桃| 潘金莲AAAAAAAAAA| 天堂久久精品| 激情婷婷五月天日本系列| 色五月亚洲| 久热婷婷| 久9热插入| 色五月婷婷色| 六月色播| 极品人妻VIDEOSSS人妻| 91打屁股视频网站| 亚洲 小说 欧美 激情 另类| 爆乳熟妇一区二区三区爆乳照片| 91久久精品国产91性色TV| 免费日本aⅴ中文字幕 | 激情五月色婷婷| 综合网色| 免费观看2018www黄色操逼网站| 色综合九九色综合88| 精a品a视a频| 思99热精品久久只有精品| 夜夜干夜夜操| 国产看真人毛片爱做A片| 亚洲色综久久五月| 婷婷深爱网| 激情久久五月天| 一本色道久久88综合日韩精品| 99久久五月天| 久久这里只有国产视频| 精品久久99| 成人一区在线观看| 呦呦视频无码播放| 色区久久| site:xiongshengzz.com| 五月WWW| 日韩无码色色| 色婷婷久久久| 97精品自拍视频| 亚洲黄网AV| 欧美色色色| 99热这里全都是精品| 在线观看国产高清视频免费网站| 99无码视频| 天天操天天曰| 婷婷五月另类网站| 五月激情网络| 五月成人丁香av91| 激情五月天之五月婷婷| 久久免费精彩视频| 婷婷五月花免费视频在线| 日日干日日| 99久久国产综合精品五月天喷水\| 综合色久| 五月丁香综合激情网| 色婷婷AⅤ| 天天操天天操| 农村熟妇高潮精品A片| 亚洲天堂爱爱| 99久久99九九九99九他书对| a九九热www| 日韩AAAAAAAAAAA片| 亚洲精品又粗又大又爽A片| 玖玖国产视频一区| 99爱在线视频| 欧洲亚洲免费视频9| 超碰人人射| 99丁香五月婷| 超碰女人天堂| 婷婷 久综合| 久久草大香蕉| 婷婷五月 丁香六月| 五月丁香五月综合欧美| 久久五月六月| AV成人在线网站| 天天干天天干天天干天天干天天干天天干天天| 九九热青草| 激情五月丁香色婷婷| 日日夜夜干| 婷婷五月开心中文字幕色| 99亚洲精品| 战争与艾拉电影免费观看| 婷婷亚洲综合| 五月丁香AV在线| 日本玖玖在线| 丁香五月色五月| 91精品久久久久久久久久久久| 丁香五月情| 日韩成人无码人妻| 激情五月激情综合网| 丁香五月激情天AV无码| 嫩草极品| 亚洲成人中心| 婷婷五月在线综合| 婷婷碰碰| 无码人妻电影| 开心久久爱五月天| 9 1在线视频| 欧美精产国品一二三区| 美妞av| www.9操| 五月综合缴情网| 影院久久久| 91婷婷丁香五月| www久久久| 五月天婷婷综合网| 色情婷婷五月天| 庭庭久久内射| 三级片AAA久久久AAA久久久AAA | 亚洲第二AV| 人人九色| 激情五月丁香激情综合网| 五月激情婷婷偷拍| 99热在线观看精品| 激情小说五月欧美亚洲丁香| 国产在线中文字幕| 久久99草五月婷婷| 夜夜撸天天操| 婷婷五月六| 亚洲综合在线伊人婷| 操老逼综合网| 午夜婷婷| 婷婷五月天狠狠搞干| 网色99| 丁香婷婷成年| 久久a热| 色六月视频| 91日本在线观看| 丁香五月婷婷免费视频| 亚洲日日操| 天天操夜夜爱| 久久视频婷婷视频| 99这里有精品视频| 色婷婷色五月综合| 色青青电影色五月| 六月婷婷激情| 9久视频| 色99在线观看| 五月激情婷婷六月丁香| 久99热| 97婷婷丁香五月综合| 99热这里只有精品青草| 婷婷的色色五月天| 五月婷婷色激情| 99色综合网| 亚洲另类av| 国产精品18久久久| 97人人操人人干| 婷婷五月天丁香社区| 婷婷五月丁香基| 国产av基地| 五月婷婷黄网站大全| 欧洲色色| 国产精品色色| 思思热视频在线观看| 天天爱天天操| 五月婷婷综合丁香视频| 五月天激情小说欧美激情| 五月亭亭激情综合| 亚洲精品乱码久久久久久综合| 碰97久久| 色婷婷中文在线| 久久99免费视频| Blackedraw视频一区二区| 六月丁丁香| 五月丁香亭亭操逼| 色婷久九| 丁香五月手机在线| 久99久在线| 91九色精品| 丁香五月天成人网站| 女力报到正好爱上你| xxx综合在线| 99热99热在线观看| 色综合天天网| 2025天天爽天天摸| www.五月丁香av| 99惹精品视频| 五月天啪啪| 五月丁香六月婷婷网站| 色爱亚洲| 婷婷在线视频| 丁香五月久久| 成人无码髙潮喷水A片| www.色五月| 丁香五月天激情视频| 五月婷婷激情综合网| 色五月综合在线| 六月丁丁香| 能看的av| 九九综合影音先锋| 成人啪啪色婷婷久| 五月丁香激情四射| 色六月天天激情综合网| 色高清无码视频| 丁香五月23111| 色婷婷狠狠干芒果TV| 99热6色| 另类视频五月天| 国产精品视频| 婷婷综合五月| 色婷婷91激情小说| 国产在线黄色| 亚洲五月天伊人| 五月婷久久在线| 亚洲精品国产精品乱码视99| 99热最新| 婷婷丁香激情五月天色色色| 久久999久久999久久999久久| 五月婷婷六月丁香综合| 五月天成人在线视频丁香| 激情丁香五月激情婷婷| 久久久久人妻精品| 五月天成人综合| 婷婷五月丁香第四色超碰在线| 加勒比久热| 日本久久婷| 丁香花五月天| 五月婷婷亚洲| 天天草女人| 1024成人在线观看| 国熟女视频| 色久丁香五| 五月天色综合| 99热精品网| 激情六| 五月丁香六月婷婷亚洲综合| 99热久| 精品九九久久| 99热无码精品| 秋霞AV淫| 色色六月| 色必久悠悠影院| 丁香色婷婷| 97碰在线视频| 任你爽精品免费视频6| 国产欧美日韩一区二区三区| 國語久久婷| 激情人妻蜜夜系列区| 无码髙清| http://www.sd-xiangsu.com/| 99热最新| 中文字幕精品在线观看| 夜夜操天天爽| 无码少妇高潮喷水A片免费| enecarbon-materials.com污K127封锁请涟系@wip1688 | 成人电影一区| 久久综合首页| 夜夜骑夜夜撸| 99热在线观看成人| 欧美久久五月婷婷| 91碰碰视频| 激情五月丁香色婷婷| 丁香五月婷婷AV| 99婷婷综合| 热久久思思热思思| 久久机热/这里只有精品| 色色五月丁香婷婷综合| www.lingjunshare.com| 婷婷久久综合| 青青草搞屄视频网站| 大香蕉网站,大香蕉综合| 五月丁香久久激情综合| 密乳视频| 亚洲三级无码| 六月丁香婷婷尤物| 无码激情AAAAA片-区区| 色婷婷五月基地在线| 五月天色色色| 97人人干| 狠狠操狠狠插| 六月欧美综合色情| 日韩成人综合网| 丁香九月激情| 狠狠搞狠狠操| 天天拍夜夜撸| 黑人糟蹋人妻HD中文字幕 | 日本无va视频| 99精品偷自拍| 色婷婷五月婷婷五月婷婷五月| 五月婷婷激情网| 九九视频精品这里只有| 狠狠插狠狠插| 日日干日日色| 超碰狠狠干99| 99热这里只有精品在线播放| 奇米影视在线视频| 99热成人| 欧美在线看| 九九九九国产| 涩涩五月天综合| 天天天天干| 五月综亚洲| 狠狠狠狠青草| 色情丁香五月婷婷精品| 久久婷婷五月综合成人d啪| 五月婷婷综合激情网| 91黄址| 亚洲网视屏| 99热亚洲| 亚洲婷婷成人五月天| 97超级啪啪在线观看| 婷婷开心久久| 99黄色在线视频精品熟女| 97久久久久| 激情六| 五月婷婷色欲| 亚洲六月婷婷| 日日干五月天婷婷| 人人爱干人人爱草| 三年高清大片免费观看国语| 九九视频这里只有精品| 丁香婷婷六月天| 色色五月天激情| 丁香五月激情视频在线| 99热在线资源| 丁香六月婷婷| 色色色色网| 色婷婷在线播放| 欧美日韩中文国产一区发布| 九九九九这里只有精品| 久久久激情| 综合aV在线| 99色在线观看视频| 婷婷五月丁香基| 婷婷色情五月| 黑人巨粗进入警花疼哭A片| 久久丁香久久| 99精品视频免费在线播放| 五月停视频天堂| 久久婷婷综| tingtingzonghewang| 五月色亚洲| www.色婷婷| 日欧大屏操| 久久丁香五月婷婷激情综合网| 在线超碰免费| 99久re热视频精品98| 亚洲99精品欧美一区| 开心五月六月婷婷| 中文字幕第四色.999| 日本天天色| 久热99热| 久久久精品色色色| 色婷婷视频| 另类视屏| 久久99精品久| 色爆五月| 91碰碰| 天天综合色丁香| 日日干干天天干| 激情视频网址| 26uuu丁香婷婷五月| 日木WWW视频| 天天爽天天干| WWW.婷婷五月天.COM| 俺去啦综合网| 伦99热| www,8050,午夜三级| 国产资源在线视频| 伊人婷婷综合| AV中文字幕夜夜操b天天摸bb| 国产亚洲在线观看| 丁香久久| 狠狠干狠狠色| 六月丁香色色| 精品99视频| 婷婷午夜天| 久久视频九九视频| 亚洲综合网激情五月天| 婷婷色色五月天| 99精品在线观看视频| 色色色9 9 9| 亚洲成人丁香花| 牛牛澡牛牛爽| 岛国在线观看91| 国产乱妇无乱码大黄AA片| 天天色视频| 久久伊人五月天| 色婷婷丁香| 激情久久久久| 久碰视频| www久| 激情综合网色播五月| 91一起操| 激情六月婷婷| 无码免费人妻A片AAA毛片西瓜| 99九九精品| 97色色网| 婷婷丁香五月天综合激情| 538在线精品| 亚洲日韩乱码一区二区三区四区| 狠狠精品干练久久久无码中文字幕| 99视频在线| 97色婷| 大战熟女丰满人妻AV| 久热在线中文字幕色999舞| 怡红院AV亚洲一区二区三区H| 少妇熟女视频一区二区三区| 色情终和网| 欧美三级韩国三级日本三斤| 成人短视频免费| 中文字幕成人影视| 九九黄色网| 99在线免费视| 人人干Av| 久热超碰91| 久久作爱| 婷婷五月综合色中文字幕| 99色这里| 综合五月激情| 日本九九网| 思思热视频在线| 成人无码精品1区2区3区免费看| 日韩黄色影院| 偷偷操99| 美女天天久久| 亚洲成人黄色网| 五月天伊人综合| 狠狠色噜噜狠狠狠888| 免看黄大片AA | 一区二区传媒视频| 久久久婷婷婷| 国产精品蜜臀99| 色欲午夜无码久久久久久张津瑜| 久久久性爱视频| 99久久户外勾搭| 十区AV| 青青热久久综合| 丁香六月婷婷色XXXXX| 日韩欧美一级大黄网站| 色婷婷性爱网| 色综合com| 精久久色| 色婷婷狠狠| 91久久久久| 欧美久久婷婷| 亚洲第一色区| 五月丁香婷婷欧美| 五月婷视频在线观看| 五月丁香啪啪| 五月天婷婷综合免费| 九月丁香| 久久9热| 激情五月丁香在线观看直播| 色六月婷婷| 91人妻人人操| 丁香五月自拍| www.henhenl| 五月婷婷 婷婷五月 一区二区 久久久 | 激情婷婷综合网| 久久99激情| 97欧美在线| 99九九这里有免费视频| 亚洲热手机在线观看| 久久婷婷视频| Www.sesese丁香| 五月婷五月婷伊人伊人五月婷| 亚洲综合1024| 99ri6在线视频| 丁香 婷婷五月| av久热| 久久久精品99| 2025年最新亚洲在线欧美| 色婷婷亚洲婷婷| 成人av播放| 天天透天天爱| 超碰99成人在线| wwccc久久久| 色综合天天综合成人网| 五月丁香 啪啪| 五月丁香六月婷婷网| 日韩一级一片内射视频4K| 久久五月天婷婷视频| 亚洲在线操| 色五月大| 99爱爱网| 182TV大香蕉| 色婷婷五月天视频网站| 久婷婷久草| 99黄色| 色日本颜射| 综合色五月天| 99精品视频在线观看| 婷婷五月成人有| 青青草五月天| 99噜噜噜在线播放| 99色在线| 美女五月天婷婷| 人妻人人操| 婷婷四月 成人 狠狠干| 99精品无码| 色五月涩涩婷婷蜜桃| 国产精品色| ss五月天激情| 青草青草视频2免费观看| 久久99热这里只有精品23| 日韩九区| 极品 少妇 内射| 久久久天堂国产精品女人| 五月婷婷影院| 99国产小视频免费观看| 九九热免费视频| 五月婷婷伊人网| 色色色色色色色色色影院| 综合激情综合啪啪| 99久久婷婷国产综合精品电影| 国产色五月婷婷| 九九色中文| 人妻久久久久久| 久久资源网五月婷| 人人干人人看| 69婷婷丁香午夜| 亚洲午夜国产成人电影VA国产欧…| 六月丁香成人网| 97久操视频| 91九色丨国产丨爆乳| 丁香五月婷婷亚洲人| 国产精品久久久久久亚洲毛片| 亚洲激情视频网| 久久天堂女人| 黄色片区子| 久久综合网免费视频| 2018夜夜草| 网站免费一站二站| 婷婷伊人| 丁香五月婷婷啪啪视频| 欧美Va婷色| 伊人婷婷青青cao| 99丁香婷婷综合网| 天天综合精品| 久久五月丁香伊人青草| 国产精品成人网址| 99久久婷| 五月婷在线色视频| 五月婷婷九九热| 99成人| 色XX综合网| 婷婷久久五月| 欧美日韩婷婷五月天| 丁香激情五月| 337p午夜影院| 婷婷丁香成人五月天| 天天干天天插| 狠狠色噜噜狠狠狠888| 人人草成人视频| 狼人伊人干| 亚洲综合色网| 俺去也五月天| 五月天激情亚洲| www婷婷| 色色综合网。| 精品人妻一区二区| 五月丁香五月婷婷| 五月视频日本免费观看| 久久五月天网| 大香焦啪啪啪| 99热这| 婷婷伊人网| 综合久久丁香婷婷,五月婷婷六月丁香,开心激情综合网,六月丁香在线观看,婷婷丁 | 激情又色又爽又黄的A片 | 五月婷在线| 9999热精品| 性做久久久久久久免费看| 色噜噜狠噜噜视频| 色色日韩无码| 狠狠色丁香久久久婷| 久久婷婷六月综合综合| 色偷偷AV亚洲男人的天堂| WWW,五月| 亚洲成人在线五月天| 亚州激情在线视频| 丁香五月婷婷黑人妻黄色电影院| 中文婷婷狠狠| 丰满少妇猛烈A片免费看观看 | 任你草| 五月天天天天天天天天天天天天天天天婷婷婷 | 五月天久久丁香| 99热这里只有在线播放| 久久综合干| 日韩在线成人电影| 色五月天 丁香| 免费看欧美成人A片无码| 激情婷婷| 激情久久五月天| 六月婷婷八月丁香| 深夜激情网| 五月天激情网页| 婷婷五月天亚洲天堂| 久热超碰| 久久五月视频| 在线成人网站| 伊人婷婷大香蕉| 五月婷婷综合影院| 99啪啪骑| 天天肏天天肏| 五月久久| 99色免费| 热热99爱爱| 99热很操老逼| 青青草网武则天| 婷婷五月在线| 色综合色婷色基地| aaaa.黄| 97超级碰碰碰| 九九精品亚洲| www.99热在线观看| www99精品| 狼人久草| 五月天激情综合首页| 深爱婷婷基地| 婷婷五月天另类视频| 日韩成人五月天| 狠狠干五月丁香| 另类激情五月| 激情五月婷婷在线| 婷婷噜噜| 五月丁香五月婷婷| 九九婷婷综合| 这里只有精品在线观看视频| 色色色综合网| 99ER热精品视频| 亚洲午夜成人av电影网| 人人操9| 精品一区二区三区三区| 另类 在线| 激情久久五月天| 天搞天天天天天| henhencao国产在线| 欧美色色色| 久久婷婷综合五月天| 婷婷色片| 99综合| AV在线免费观看不卡| 综合超碰熟| 色综合久久88色综合天天99| 蜜桃婷婷五月| 婷婷香五月综合激情| 直接看的av| 91啪啪| 97色婷婷| 99日视频在线| 婷婷精品免费久久| 五月丁香 久久久| 天天日,天天插| 综合久久综合| 丰满少妇乱A片无码| 91日精品| 丁香五月婷婷亚洲色图| 丁香五月无码| 久婷婷| 中文字幕丰满孑伦无码专区| 欧美婷婷综合网| 婷婷丁香人妻天久久| 久久人人人人妻| 99热精品在线| 亚洲亚洲人成综合网络| 丁香五月天天| 99色啊| 色丁香五月婷婷| 亚洲人妻av伦理| 超碰高清在线| 国产综合激情五月久久| 射久久丁香五月| 成人无码精品1区2区3区免费看| 五月婷婷亚洲色图| 91九色在线| 超pen个人视频97| 五月天激情四射网站| 天天综合五月| 91九色丨国产丨爆乳| 五月婷婷影视| 91狠狠综合久久久久久| 天天日日综合| 中文字幕无码人妻少妇免费视频| 激情丁香五月AV| 五月六月丁香婷婷在线观看| 婷婷久久五月天| 9精品久久999| 欧美天天草人人草| 激情五月婷婷综合| 少妇人妻人伦A片| 五月天啪啪视频| 婷婷五月天亚洲| 99久久国产宗和精品1上映| 久久婷婷五月丁香网| 日本成人噜噜| 疯狂做受XXXX高潮A片动画| 九九色综合网| 色五月婷婷色五月婷婷色五月婷婷| 久久久com| 色播婷婷五月天| 激情五月丁香婷婷| 婷婷五月丁香图片人人操| 久久永久网址| AV操逼网| 婷婷五月中文字幕| 天天搞天天色综合| 爽tv | 色色色99韩| 玖玖热视频| 久久婷婷色色| 91精品综合久久婷婷九色| 欧美色必爱| 色婷婷六月开心中文字| 色人久久| 婷色人人狠| 99综合| 99人妻碰碰碰久久久久禁片| 日日夜夜干| 日本一级大片| 可以看的AV网站| 国内9l视频自拍老熟女九色| 天天爱天天做天天爽| WWW.国产| 亚洲婷婷月丁香五月| 九九热这里只有精品6| 97碰碰视频在线观看| 亚洲熟女色| 综合久久五月天| 色婷婷偷拍| 91丨九色丨熟女|老版| 久久玖玖综合| 97热这里精品在线视频| 激情啪啪五月| 91尤物九色在线| 成人av中文字幕| 国产9色在线/日韩| 色婷婷久久综合| 另类专区在线观看| 97久久视频| 六月五月丁香五月欧美| 97综合在线| 天天成人五月天| 免费黄网不卡AV| 这里只有精品9| 中文在线视频久9| 激情六月婷婷| 婷婷成人综合| 天天干天天拍| 丁香综合伊人AV| 99亚洲精品综合在线| 丁香五月婷久久| 男人視頻站| 99色干| 99久久久国产大片区| 五月丁香啪| 天天夜天天色天天| 九九综合88| 成人婷婷| 五五月丁香花激情综合网| 欧美成人AAA片一区国产精品| 色色无码| 亚洲黄色影视| 色噜噜狠狠色综无码久久合欧美| 激情美女五月天激情在线| 91啦丨九色丨刺激中文| 五月婷婷深深爱| 五月婷婷在线视频免费观看| 性欧美大战久久久久久久83| 丁香五月亚综合图片| 99久在线观看| 欧亚成人A片一区二区| 超碰1999| 9l视频自拍9l九色成人| 国产片XXXXA片国语对白| 综合激情五月天六月婷免费视频| 五月丁香婷草| 性做爰1一7伦| 久久九九色| 亚洲激情综合色站| 五月婷无码| 五月天丁香网站| 色婷婷4| 久草丁香婷婷五月天婷| 人人摸人人搞| 综合网五月天123| 九九re精品视频在线观看| 久热九九| 婷婷免费视频| 琪琪秋霞| 射久久丁香五月| 国产毛多水多女人A片| 久久99热这里只有精品 | 91丨九色丨43老版熟女| 五月天六月婷| 五月综合亚洲色| 久久aaaaa| 欧美激情综合色综合啪啪五月| 五月色色激情网| 天天看片日日夜夜| 視频福利乱色| 欧美私人家庭影院| 天天噜日日噜综合无码| 五月天婷婷激情春色小说| 婷婷黄色| 丁香五月天社区婷婷| av九九| 国产97色在线| 天天爽天天摸人妻综合网| 婷婷五月激情的图片| 九九热青青草| 成人做爰高潮A片免费视频| 综合网啪啪| 五月丁香啪啪伦理电影| 99热99热在线观看| 99黄色在线视频精品熟女| 99在线视频操999| 激情五月婷婷| 99热新网址| 免费不卡狠操美女视频网| www天天干| 婷婷六月丁香激情| 极品色丁香| 五月天大香蕉视频| 天天揷综合网| 久热99| 激情五月综合| 玖玖99免费视频| 天天狠狠夜夜狠狠2023| 婷婷五月天熟妇| 日本va网站| 色热久资源| 久久综合中文| 91色噜噜狠狠狠狠色综合| 在线一起草av| 99网址在线观看| 五月丁香婷婷成人网| AV大香蕉| 丁香五月天激情综合| 欧美婷婷丁香五月社区| 丰满人妻一区二区三区| 婷婷王月天影院| 女力报到正好爱上你| 天天撸夜夜爽| 婷婷五月丁香基| 五月色丁香成人| 综合激情网五月激情 | 超碰免费成人| 五月婷婷啪啪啪| 久久草中文日韩欧美| 日韩黄色电影| 激情亭亭五月| 久久精品99久久久久久| 五月婷婷深深爱| 五月婷婷导航| 99男人的天堂| 97人人看| 久久婷色| 99热在线看| 9久热| 国产古装妇女野外A片 | 人妻乱码久久久| 亚洲第一色网站| 色另类五月天| 五月丁香在线婷婷蜜桃| 亚洲成人乱码av网站| 激情婷婷五月天在线观看| 色欲五月婷婷| 79色色色色| 色五月激情五月天| 婷婷丁香五月天中文字幕| 99亚洲色色| 精品欧美一区二区三区久久久| 91久久婷婷人人澡草| 久久久人妻系列| 婷婷五月天综合在线 | 婷婷久久内射| 婷婷97碰碰| 热九九在线| 99色播| 婷婷综合精品视频97| 婷婷五月色惰| 色婷视频| 人妻丰满精品一区二区A片| 亚洲字幕AV一区二区三区四区| 久9热视频在线| 九九色院| 精品国产va久久久久| 欧美猛片| 狠狠操狠狠操AV| 337p大胆噜噜噜噜噜91Av| 9999久久久久| 无码AV大香线蕉伊人| 九九99香蕉在线视频播放| 丁香九月婷婷| 99热九九在线| 综合性爱网| 精品一二三区久久AAA片| 超碰妻人人| 综合久久久| 2020久久婷婷五月| 丁香五月电影| 五月激情婷婷在线| 9久热精品在线视频| www.99热这里精品| 久久综合99| 天天爽夜夜爽天天爽夜夜爽| 啪啪操超碰| 极品人妻XXXXOOOO| 激情五月婷婷啪啪| 思思久久网| 五月丁香黄色视频| se99视频| 五月丁香综合网| 激情四射五月天偷偷看婷婷| 天天插天天插天天插| 欧美日朝成人| 婷婷五月天淫荡| 激情五月丁香五月| 婷婷五月花西瓜| 99精品视频免费观看| 亚洲成人av在线观看 | 在线成人网站| www.com久久久久久久久久久久久久久久久| 91九色在线视频| 久久这里99| 五月婷婷丁香在线| 久久蜜臀婷婷| 91在线观看www| 国产av天堂| 久久婷婷东京热大香樵| 国内婷婷丁香社区在线播放| 国产亚洲精品久久一区二区三区| 曰韩少妇内射免费播放| 黄色成人网站在线播放| 丁香五月六月欧美| 激情深爱五月天| 伊人网啪啪| 五月天激情.com| 激情五月综合网| 国产操B视频| 亚洲AV色婷婷人禽五月天| 激情AV| 97AV在线视频| 色亭亭五月天丁香综合AV - 百度 - 百度| 天天插天天插| 97超碰综合| 七七九色| 色久一| 久久99成人性爱高清视频| 天天操夜夜操| 影音先锋一区二区三区| 久久精品这里只有精品免费首页| 久久久国产精品黄毛片| 丁香五月激情六月欧亚激情综合导航 | 欧美成人日韩| AV在线二十六页| 我要看激情五月天| 乱岳熟女50岁| 九九热这里只有精品556| 欧美日本国产欧美日本韩国99| 激情婷婷22月间| 久久久人妻门| 天天狠狠综合精区| 色婷婷在线视频久| 五月婷婷激情综合| 激情五月天视频| 99ri国产在线| 日本婷婷在线| 天天做天天爽| 欧美超碰人人| 久久99性爱| 日韩欧美性爱| 婷婷五月天在线综合| 成人小说色图婷婷五月| 91人妻视频| 丁香婷婷狠狠97| 五月婷婷花| 九久久九精品视频| 99热99这里免费的精品| 91色性感五月婷婷丁香| 天天 青草 丝袜制服 在线| 欧美成人AAA片一区国产精品| 丁香五月婷婷亚洲综合精品在线| 嫩草AV久久伊人妇女超级A| 亚洲激情丁香五月基地| 五月天电影网|