最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue單頁緩存方案分析及實現(xiàn)

 更新時間:2018年09月25日 15:18:40   作者:afterwawa  
這篇文章主要介紹了vue單頁緩存方案分析及實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

實現(xiàn)全站的頁面緩存,前進刷新,返回走緩存,并且能記住上一頁的滾動位置,參考了很多技術(shù)實現(xiàn),github上的導(dǎo)航組件實現(xiàn)的原理要么使用的keep-alive,要么參考了keep-alive的源碼,但是只用keep-alive沒法實現(xiàn)相同path,不同參數(shù)展示不同view,這就有點坑了,所以需要結(jié)合自己要實現(xiàn)的功能,適當(dāng)改造keep-alive,為了實現(xiàn)每次前進都能刷新,返回走緩存還能自動定位的功能,文章陸續(xù)從以下幾個方面展開講:兩套技術(shù)方案可選,最后定的技術(shù)方案的原因,實現(xiàn)的功能和原理,踩過的坑

方案一:vue的keep-alive組件

 具體使用如下: 

<keep-alive max="10">
  <router-view/>
 </keep-alive>

為什么這么使用?

如vue官網(wǎng)(https://cn.vuejs.org/v2/api/#keep-alive)介紹:

<keep-alive> 包裹動態(tài)組件時,會緩存不活動的組件實例,而不是銷毀它們。和 <transition> 相似,<keep-alive> 是一個抽象組件:它自身不會渲染一個 DOM 元素,也不會出現(xiàn)在父組件鏈中。

當(dāng)組件在 <keep-alive> 內(nèi)被切換,它的 activated 和 deactivated 這兩個生命周期鉤子函數(shù)將會被對應(yīng)執(zhí)行。主要用于保留組件狀態(tài)或避免重新渲染。

因為緩存的需要通常出現(xiàn)在切換頁面時,所以就需要結(jié)合vue-router的router-view來實現(xiàn)

為什么keep-alive能實現(xiàn)緩存?

render () {
 const slot = this.$slots.default
 const vnode: VNode = getFirstComponentChild(slot)
 const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
 if (componentOptions) {
  // check pattern
  const name: ?string = getComponentName(componentOptions)
  const { include, exclude } = this
  if (
  // not included
  (include && (!name || !matches(include, name))) ||
  // excluded
  (exclude && name && matches(exclude, name))
  ) {
  return vnode
  }

  const { cache, keys } = this
  const key: ?string = vnode.key == null
  // same constructor may get registered as different local components
  // so cid alone is not enough (#3269)
  ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
  : vnode.key
  if (cache[key]) {
  vnode.componentInstance = cache[key].componentInstance
  // make current key freshest
  remove(keys, key)
  keys.push(key)
  } else {
  cache[key] = vnode
  keys.push(key)
  // prune oldest entry
  if (this.max && keys.length > parseInt(this.max)) {
   pruneCacheEntry(cache, keys[0], keys, this._vnode)
  }
  }

  vnode.data.keepAlive = true
 }
 return vnode || (slot && slot[0])
 }

如上keep-alive源碼,其中render函數(shù)是這樣實現(xiàn)的,要渲染的試圖組件作為插槽內(nèi)容被獲取到,當(dāng)渲染到路徑匹配到的視圖組件時會根據(jù)vnode存儲的內(nèi)容拿到對應(yīng)的name,一次將這些組件實例放到變量cache中,這樣根據(jù)路由就可以找到緩存的vnode,返回給createComponent方法去執(zhí)行initComponent,vue組件渲染這塊的代碼如下

function initComponent (vnode, insertedVnodeQueue) {
 if (isDef(vnode.data.pendingInsert)) {
 insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert)
 vnode.data.pendingInsert = null
 }
 vnode.elm = vnode.componentInstance.$el
 if (isPatchable(vnode)) {
 invokeCreateHooks(vnode, insertedVnodeQueue)
 setScope(vnode)
 } else {
 // empty component root.
 // skip all element-related modules except for ref (#3455)
 registerRef(vnode)
 // make sure to invoke the insert hook
 insertedVnodeQueue.push(vnode)
 }
}

這里會有 vnode.elm 緩存了 vnode 創(chuàng)建生成的 DOM 節(jié)點。所以對于首次渲染而言,除了在 <keep-alive> 中建立緩存,和普通組件渲染沒什么區(qū)別。從進入到返回的大致執(zhí)行流程如下

能實現(xiàn)的功能

能夠把要緩存的組件渲染的vnode記到cache里邊,當(dāng)返回的時候用緩存里邊的dom直接渲染,還有keep-alive組件提供的include 和 exclude屬性,可以有條件的緩存想緩存的組件,如果配置了 max 并且緩存的長度超過了這個max的值,還要從緩存中刪除第一個

存在的問題

存在的問題是存儲vnode節(jié)點的key是name,也就是定義路由時組件對應(yīng)的name,這就會導(dǎo)致同樣的path,不同參數(shù)的時候打開的是從cache里邊拿到的vnode,會渲染出同樣的視圖出來,但是很多業(yè)務(wù)場景都是根據(jù)參數(shù)來顯示不同內(nèi)容,而keep-alive底層并沒有對此做擴展,可以看下keep-alive源碼

 const key: ?string = vnode.key == null
  ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
  : vnode.key
  if (cache[key]) {
  vnode.componentInstance = cache[key].componentInstance
  // make current key freshest
  remove(keys, key)
  keys.push(key)
  } else {
  cache[key] = vnode
  keys.push(key)
  // prune oldest entry
  if (this.max && keys.length > parseInt(this.max)) {
   pruneCacheEntry(cache, keys[0], keys, this._vnode)
  }
  }

vnode.key就是路由里邊定義的name,所以要用這套方案來實現(xiàn)的根據(jù)不同參數(shù)展示不同視圖的功能就要對這里的key做改造,但是keep-alive是vue自帶的,沒法改底層,然后就誕生了我的第二套方案

方案二:navigation組件,scrollbehavior 

github上找到類似功能的組件vue-navigation,這個vue組件可以實現(xiàn)返回走緩存,底層原理跟keep-alive一樣,實際上是改寫了keep-alive組件,前進刷新時新增了一個參數(shù)VNK,這樣在路由發(fā)生變化的時候都會用給url帶一個參數(shù),并且cache的key取值依賴這個參數(shù),借鑒這個組件的思路,做了一個類似keep-alive的組件,其中key的值是getKey方法獲取的,改寫以后的render方法如下

 render () {
  var vnode = this.$slots.default ? this.$slots.default[0] : null
  if (vnode) {
  vnode.key = vnode.key || (vnode.isComment ? 'comment' : vnode.tag)
  const { cache, keys } = this
  var key = getKey(this.$route, keyName)
  if (vnode.key.indexOf(key) === -1) {
   vnode.key = '__navigation-' + key + '-' + vnode.key
  }
  if (cache[key]) {
   if (vnode.key === cache[key].key) {
   vnode.componentInstance = cache[key].componentInstance
   } else {
   cache[key].componentInstance.$destroy()
   cache[key] = vnode
   }
   remove(keys, key)
   keys.push(key)
  } else {
   cache[key] = vnode
   keys.push(key)
   // prune oldest entry
   if (this.max && keys.length > parseInt(this.max)) {
   pruneCacheEntry(cache, keys[0], keys, this._vnode)
   }
  }
  vnode.data.keepAlive = true
  }
  return vnode
 }

getKey方法實現(xiàn)

//url上新增參數(shù)vnk的值

export function genKey() {
 // const t = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
 const t = 'xxxxxxxx'
 return t.replace(/[xy]/g, function (c) {
 const r = Math.random() * 16 | 0
 const v = c === 'x' ? r : (r & 0x3 | 0x8)
 return v.toString(16)
 })
}
//
export function getKey(route, keyName) {
 return `${route.name || route.path}?${route.query[keyName]}`
}

通過新寫一個install方法掛載這個導(dǎo)航組件到vue上就可以實現(xiàn)前進刷新,返回走緩存,并且可以配置最大緩存數(shù),后續(xù)開源到github

最后剩下返回上一頁記住上一頁的位置,之所以沒有用開源的這個組件的記位置,是因為直接套用需要改整體布局,height:100%;樣式造成$(windows).scrollTop失效,整體考慮改造成本較大,還是使用了vue-router提供的scrollBehavior,在路由配置里引入

實現(xiàn)如下:

var scrollBehavior = async (to, from, savedPosition) => {
 if (savedPosition) {
 return savedPosition
 } else {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
  resolve({ x: 0, y: to.meta.savedPosition || 0 })
  }, 300)
 })
 }
}
const router = new VueRouter({
 mode: 'history',
 scrollBehavior,
 routes: [{
 path: '',
 redirect: '/mobile/home.html',
 meta: {
  needMtaReport: true,
  parentsStyle: {
  height: '100%',
  minHeight: '100%'
  }
 }
 },
 {
 name: 'scienceCompetition',
 path: '/mobile/scienceCompetition.html',
 component: scienceCompetition
 }]
}

總結(jié):

1.單頁緩存下js加載解析編譯執(zhí)行的時間縮短了,返回的時候由于走緩存js腳本的占用時間完全可以忽略,從而整體上縮減了頁面的加載渲染時間

2. 因為項目以前不是單頁,代碼里邊定義了很多全局變量或者全局事件綁定,改成單頁后全局變量的值依然存在,就會導(dǎo)致業(yè)務(wù)邏輯出現(xiàn)bug,所以使用單頁需要注意全局變量或是事件的謹(jǐn)慎使用,具體的踩坑記錄在http://m.fzitv.net/article/147957.htm

3.通過push進入下一頁時,head里邊會累加前面頁面的靜態(tài)資源,訪問的頁面越多,最后的頁面掛的靜態(tài)的資源越多,返回的時候并不會減少已經(jīng)加載的靜態(tài)資源,單頁緩存是典型的空間換時間的方案,內(nèi)存的開銷比較大,能否對資源動態(tài)增減以及內(nèi)存占用的優(yōu)化一直在探索中,暫時沒有找到很好的解決方法。。。。。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue中使用elementUI組件手動上傳圖片功能

    vue中使用elementUI組件手動上傳圖片功能

    Vue是一套構(gòu)建用戶界面的框架, 開發(fā)只需要關(guān)注視圖層, 它不僅易于上手,還便于與第三方庫或既有項目的整合。這篇文章主要介紹了vue中使用elementUI組件手動上傳圖片,需要的朋友可以參考下
    2019-12-12
  • VUE腳手架的下載和配置步驟詳解

    VUE腳手架的下載和配置步驟詳解

    這篇文章主要介紹了VUE腳手架下載和配置,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Vue?data中隨意改一個屬性,視圖都會更新嗎?

    Vue?data中隨意改一個屬性,視圖都會更新嗎?

    這篇文章主要討論Vue?data中隨意改一個屬性,視圖都會更新嗎?下面來自面試官的問題然后做i出的一個問題總結(jié),具有一定的參考價值,需要的小伙伴可以參考一下
    2021-12-12
  • vue異步請求數(shù)據(jù)重新渲染方式

    vue異步請求數(shù)據(jù)重新渲染方式

    這篇文章主要介紹了vue異步請求數(shù)據(jù)重新渲染方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Vue2中配置Cesium全過程

    Vue2中配置Cesium全過程

    這篇文章主要介紹了Vue2中配置Cesium全過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • vue自定v-model實現(xiàn)表單數(shù)據(jù)雙向綁定問題

    vue自定v-model實現(xiàn)表單數(shù)據(jù)雙向綁定問題

    vue.js的一大功能便是實現(xiàn)數(shù)據(jù)的雙向綁定。這篇文章主要介紹了vue自定v-model實現(xiàn) 表單數(shù)據(jù)雙向綁定的相關(guān)知識,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-09-09
  • vue打包后顯示空白正確處理方法

    vue打包后顯示空白正確處理方法

    很多朋友遇到這樣的問題當(dāng)vue打包后顯示空白問題,遇到這樣的問題怎么處理呢?下面腳本之家小編給大家分享下vue打包后顯示空白正確處理方法,感興趣的朋友一起看看吧
    2017-11-11
  • vue3使用ref獲取dom結(jié)果為'null'的原因詳析

    vue3使用ref獲取dom結(jié)果為'null'的原因詳析

    這篇文章主要給大家介紹了關(guān)于vue3使用ref獲取dom結(jié)果為'null'的原因詳析,ref是Vue3中一個非常重要的功能,它可以用來獲取DOM節(jié)點,從而實現(xiàn)對DOM節(jié)點的操作,需要的朋友可以參考下
    2023-07-07
  • 解決betterScroll在vue中存在圖片時,出現(xiàn)拉不動的問題

    解決betterScroll在vue中存在圖片時,出現(xiàn)拉不動的問題

    今天小編就為大家分享一篇解決betterScroll在vue中存在圖片時,出現(xiàn)拉不動的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • Vue自定義Hook實現(xiàn)簡化本地存儲

    Vue自定義Hook實現(xiàn)簡化本地存儲

    這篇文章主要為大家詳細介紹了如何通過使用 Vue 3 的 Composition API 創(chuàng)建一個強大而靈活的自定義 Hook,簡化了在 localStorage 或 sessionStorage 中管理數(shù)據(jù)的流程,需要的可以參考下
    2023-12-12

最新評論

万宁市| 滦平县| 朝阳县| 哈巴河县| 都兰县| 瓦房店市| 云阳县| 南涧| 汉源县| 安福县| 夏河县| 比如县| 福建省| 舞阳县| 泸水县| 安吉县| 孟州市| 嘉鱼县| 平罗县| 樟树市| 绩溪县| 溆浦县| 酒泉市| 曲阜市| 三原县| 辛集市| 沙湾县| 新和县| 宜宾市| 桂阳县| 昭通市| 岗巴县| 衡南县| 宜春市| 平顺县| 屏东县| 丹棱县| 禹城市| 建德市| 铁岭市| 开远市|