亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

在移動端使用vue-router和keep-alive的方法示例

2024-05-06 16:47:24
字體:
來源:轉載
供稿:網友

對于web開發和移動端開發,兩者在路由上的處理是不同的。對于移動端來說,頁面的路由是相當于棧的結構的。vue-router與keep-alive提供的路由體驗與移動端是有一定差別的,因此常常開發微信公眾號的我想通過一些嘗試來將兩者的體驗拉近一些。

目標

問題

首先一個問題是keep-alive的行為。我們可以通過keep-alive來保存頁面狀態,但這樣的行為對于類似于APP的體驗是有些奇怪的。例如我們的應用有首頁、列表頁、詳情頁3個頁面,當我們從列表頁進入詳情頁再返回,此時列表頁應當是keep-alive的。而當我們從列表頁返回首頁,再次進入列表頁,此時的列表頁應當在退出時銷毀,并在重新進入時再生成才比較符合習慣。

第二個問題是滾動位置。vue-router提供了 scrollBehavior 來幫助維護滾動位置,但這一工具只能將頁面作為滾動載體來處理。但我在實際開發中,喜歡使用flex來布局頁面,滾動列表的載體常常是某個元素而非頁面本身。

使用環境

對于代碼能正確運行的環境,這里嚴格假定為微信(或是APP中內嵌的web頁面),而非通過普通瀏覽器訪問,即:用戶無法通過直接輸入url來跳轉路由。在這樣的前提下,路由的跳轉是代碼可控的,即對應于vue-router的push、replace等方法,而唯一無法干預的是瀏覽器的回退行為。在這樣的前提下,我們可以假定,任何沒有通過vue-router觸發的路由跳轉,是 回退1個記錄 的回退行為。

改造前

這里我列出改造前的代碼,是一個非常簡單的demo,就不詳細說了(這里列表頁有兩個列表,是為了展示改造后的滾動位置維護):

// css* { margin: 0; padding: 0; box-sizing: border-box;}html, body { height: 100%;}#app { height: 100%;}
// html<div id="app"> <keep-alive>  <router-view></router-view> </keep-alive></div>
// jsconst Index = { name: 'Index', template: `<div>  首頁  <div>   <router-link :to="{ name: 'List' }">Go to List</router-link>  </div> </div>`, mounted() {  console.warn('Main', 'mounted'); },};const List = { name: 'List', template:  `<div style="display: flex;flex-direction: column;height: 100%;">  <div>列表頁</div>  <div style="flex: 1;overflow: scroll;">   <div v-for="item in list" :key="item.id">    <router-link style="line-height: 100px;display:block;" :to="{ name: 'Detail', params: { id: item.id } }">     {{item.name}}    </router-link>   </div>  </div>  <div style="flex: 1;overflow: scroll;">   <div v-for="item in list" :key="item.id">    <router-link style="line-height: 100px;display:block;" :to="{ name: 'Detail', params: { id: item.id } }">     {{item.name}}    </router-link>   </div>  </div> </div>`, data() {  return {   list: new Array(10).fill(1).map((_,index) => {    return {id: index + 1, name: `item${index + 1}`};   }),  }; }, mounted() {  console.warn('List', 'mounted'); }, activated() {  console.warn('List', 'activated'); }, deactivated() {  console.warn('List', 'deactivated'); },};const Detail = { name: 'Detail', template: `<div>  詳情頁  <div>   {{$route.params.id}}  </div> </div>`, mounted() {  console.warn('Detail', 'mounted'); },};const routes = [ { path: '', name: 'Main', component: Index }, { path: '/list', name: 'List', component: List }, { path: '/detail/:id', name: 'Detail', component: Detail },];const router = new VueRouter({ routes,});const app = new Vue({ router,}).$mount('#app');

當我們第一次從首頁進入列表頁時, mounted 和 activated 將被先后觸發,而在此后無論是進入詳情頁再回退,或是回退到首頁再進入列表頁,都只會觸發 deactivated 生命周期。

keep-alive

includes

keep-alive有一個 includes 選項,這個選項可以接受一個數組,并通過這個數組來決定組件的?;顮顟B:

// keep-aliverender () { const slot = this.$slots.default const vnode: VNode = getFirstComponentChild(slot) const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions if (componentOptions) {  const name: ?string = getComponentName(componentOptions)  const { include, exclude } = this  if (   (include && (!name || !matches(include, name))) ||   (exclude && name && matches(exclude, name))  ) {   return vnode  }  const { cache, keys } = this  const key: ?string = vnode.key == null   ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')   : vnode.key  if (cache[key]) {   vnode.componentInstance = cache[key].componentInstance   remove(keys, key)   keys.push(key)  } else {   cache[key] = vnode   keys.push(key)   if (this.max && keys.length > parseInt(this.max)) {    pruneCacheEntry(cache, keys[0], keys, this._vnode)   }  }  vnode.data.keepAlive = true } return vnode || (slot && slot[0])}

這里我注意到,可以動態的修改這個數組,來使得本來處于保活狀態的組件/頁面失活。

afterEach

那我們可以在什么時候去維護/修改includes數組呢?vue-router提供了 afterEach 方法來添加路由改變后的回調:

updateRoute (route: Route) { const prev = this.current this.current = route this.cb && this.cb(route) this.router.afterHooks.forEach(hook => {  hook && hook(route, prev) })}

在這里雖然 afterHooks 的執行是晚于路由的設置的,但組件的 render 是在 nextTick 中執行的,也就是說,在keep-alive的render方法判斷是否應當從緩存中獲取組件時,組件的?;顮顟B已經被我們修改了。

劫持router.push

這里我們將劫持router的push方法:

let dir = 1;const includes = [];const routerPush = router.push;router.push = function push(...args) { dir = 1; routerPush.apply(router, args);};router.afterEach((to, from) => { if (dir === 1) {  includes.push(to.name); } else if (dir === -1) {  includes.pop(); } dir = -1;});

我們將router.push(當然這里需要劫持的方法不止是push,在此僅用push作為示例)和瀏覽器的回退行為用不同的 dir 標記,并根據這個值來維護includes數組。

然后,將includes傳遞給keep-alive組件:

// html<div id="app"> <keep-alive :include="includes">  <router-view></router-view> </keep-alive></div>// jsconst app = new Vue({ router, data() {  return {   includes,  }; },}).$mount('#app');

維護滾動

接下來,我們將編寫一個 keep-position 指令(directive):

Vue.directive('keep-position', { bind(el, { value }) {  const parent = positions[positions.length - 1];  const obj = {   x: 0,   y: 0,  };  const key = value;  parent[key] = obj;  obj.el = el;  obj.handler = function ({ currentTarget }) {   obj.x = currentTarget.scrollLeft;   obj.y = currentTarget.scrollTop;  };  el.addEventListener('scroll', obj.handler); },});

并對router進行修改,來維護position數組:

const positions = [];router.afterEach((to, from) => { if (dir === 1) {  includes.push(to.name);  positions.push({}); } ...});

起初我想通過指令來移除事件偵聽(unbind)以及恢復滾動位置,但發現使用unbind并不方便,更重要的是指令的幾個生命周期在路由跳轉到?;畹捻撁鏁r都不會觸發。

因此這里我還是使用 afterEach 來處理路由維護,這樣在支持回退多步的時候也比較容易去擴展:

router.afterEach((to, from) => { if (dir === 1) {  includes.push(to.name);  positions.push({}); } else if (dir === -1) {  includes.pop();  unkeepPosition(positions.pop({}));  restorePosition(); } dir = -1;});const restorePosition = function () { Vue.nextTick(() => {  const parent = positions[positions.length - 1];  for (let key in parent) {   const { el, x, y } = parent[key];   el.scrollLeft = x;   el.scrollTop = y;  } });};const unkeepPosition = function (parent) { for (let key in parent) {  const obj = parent[key];  obj.el.removeEventListener('scroll', obj.handler); }};

最后,我們分別給我們的列表加上我們的指令就可以了:

<div style="flex: 1;overflow: scroll;" v-keep-position="'list1'"> <!-- --></div><div style="flex: 1;overflow: scroll;" v-keep-position="'list2'"> <!-- --></div>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91亚洲精品久久久久久久久久久久| 最新国产精品亚洲| 26uuu日韩精品一区二区| 成人在线激情视频| 国产成人精品免高潮费视频| 中文欧美日本在线资源| 欧美在线视频免费播放| 亚洲最大成人在线| 久久天天躁狠狠躁夜夜躁| 日韩欧美精品在线观看| 欧美电影在线观看高清| 日韩中文在线观看| 亚洲精品美女视频| 欧美性色19p| 亚洲国产美女久久久久| 精品久久久国产精品999| 成人黄色影片在线| 欧美性猛交xxxx偷拍洗澡| 欧美激情性做爰免费视频| 另类专区欧美制服同性| 国产第一区电影| 亚洲桃花岛网站| 日本中文字幕成人| 亚洲激情视频在线播放| 91亚洲精品在线| 日本中文字幕成人| 欧美放荡办公室videos4k| 日本欧美一二三区| 欧美巨猛xxxx猛交黑人97人| 国产剧情久久久久久| 久久精品国产精品亚洲| 国产精品久久久久免费a∨| 久久久久久久av| 欧美色视频日本版| 国产一区视频在线| 中文字幕久久亚洲| 91社影院在线观看| 欧美激情视频一区二区三区不卡| 欧美又大粗又爽又黄大片视频| 国内精品久久久久久久久| 日韩美女免费线视频| 黑人巨大精品欧美一区免费视频| 欧美性猛交xxxxx免费看| 在线视频日韩精品| 国产精品偷伦一区二区| 亚洲欧美日韩国产成人| 秋霞av国产精品一区| 国产成人久久久| 国产午夜一区二区| 亚洲成av人片在线观看香蕉| 91夜夜揉人人捏人人添红杏| 北条麻妃一区二区在线观看| 欧美专区国产专区| 欧洲精品毛片网站| 欧洲亚洲免费视频| 亚洲tv在线观看| 精品二区三区线观看| 欧美成人精品三级在线观看| 成人在线激情视频| 中文字幕日韩欧美在线| 日韩在线观看精品| 欧美黑人狂野猛交老妇| 亚洲第一区在线| 亚洲视频视频在线| 欧美国产亚洲视频| 日韩精品极品在线观看播放免费视频| 欧美午夜精品久久久久久人妖| 久久久亚洲影院你懂的| 久久久久久com| 国产精品视频免费在线| 色综合久久精品亚洲国产| 丝袜美腿精品国产二区| 亚洲xxxx妇黄裸体| 日韩电影中文字幕一区| 国产精品va在线| 欧美一区二区大胆人体摄影专业网站| 国产成人欧美在线观看| 91精品国产91久久久久| 亚洲精品午夜精品| 成人妇女淫片aaaa视频| 欧美色欧美亚洲高清在线视频| 国产精品成人av在线| 亚洲最大福利视频网站| 精品一区二区电影| 日韩欧美高清在线视频| 亚洲免费视频在线观看| 亚洲精品欧美极品| 国产精品直播网红| 国产成人avxxxxx在线看| 亚洲香蕉成人av网站在线观看| 国产精品wwwwww| 欧美日韩精品在线视频| xvideos国产精品| 国产亚洲精品va在线观看| 伦伦影院午夜日韩欧美限制| 久久综合88中文色鬼| 亚洲美女久久久| 91经典在线视频| 国产一区二区三区中文| 亚洲2020天天堂在线观看| 狠狠做深爱婷婷久久综合一区| 欧美在线视频免费播放| 一区二区三区视频免费在线观看| 亚洲第一精品夜夜躁人人躁| 一区二区在线视频播放| 国产91精品久久久久久久| 岛国av一区二区| 色偷偷噜噜噜亚洲男人| 日韩精品视频免费在线观看| 中文字幕不卡在线视频极品| 欧美精品手机在线| 在线视频欧美日韩精品| 国产日韩在线视频| 久久在线精品视频| 97碰在线观看| 欧美一级视频在线观看| 国产成人久久久精品一区| 国产精品美腿一区在线看| 欧美日韩视频在线| 国产一区二区三区欧美| 97视频在线观看成人| 欧美丰满少妇xxxx| 色综合色综合久久综合频道88| 欧美国产视频日韩| 亚洲第一黄色网| 亚洲欧美色婷婷| 国产亚洲人成a一在线v站| 国产精品久久久久久久久男| 2019中文字幕全在线观看| 欧美国产在线电影| 欧美猛交ⅹxxx乱大交视频| 国产精品男人爽免费视频1| 久热精品视频在线观看一区| 日韩女在线观看| 国产精品久久久久久网站| 一区二区三区国产视频| 51ⅴ精品国产91久久久久久| 2019中文字幕免费视频| 6080yy精品一区二区三区| 国产亚洲一区二区在线| www.欧美三级电影.com| 国产精品久久视频| 亚洲天堂男人天堂| 欧美性猛交xxxx久久久| 日本人成精品视频在线| 精品免费在线视频| 精品福利在线视频| 九九精品在线观看| 久久亚洲精品中文字幕冲田杏梨| 日韩美女视频中文字幕| 不用播放器成人网| 欧美大片在线影院| 欧美成人免费一级人片100| 2020国产精品视频| 欧洲精品在线视频| 日韩久久精品成人| 色综久久综合桃花网| 久久久女人电视剧免费播放下载| 亚洲爱爱爱爱爱| 亚洲人成网7777777国产| 国内精品模特av私拍在线观看| 欧美精品久久久久久久久| 欧美成人免费播放| 国产一区二区三区丝袜|