[20191031更新]解決頁面A->頁面A的場景問題vue
[20190828更新]適配vue-router 3.1.xnode
中間由於弄比較複雜的在線聊天,耽誤了一個月,抱歉。先說下結果,目前已經在多個環境下通過驗證,包括ios、Android、微信公衆號、微信小程序(對,小程序也能搞純H5項目),都是較複雜的業務,全都是在webview下的純H5單頁項目,可以完美解決咱們業務上的需求。ios
在npm上推送了1.0.0版本,咱們內部項目已經開始正式使用。歡迎使用,歡迎Star,但願能幫到你。git
項目地址github
不瞭解解決了什麼問題的小夥伴能夠看看前情提要web
先說一下你們最關心的性能問題,比Vue
自帶的keep-alive
組件要好不少,由於keep-alive
緩存一次以後在keep-alive
組件destroyed
以前全部的緩存是不會銷燬的,可是vue-page-stack
是根據UI層級關係進行緩存和銷燬的。下面使用vue-devtool
展現二者的不一樣vue-router
vue-page-stack
將棧上的UI存儲,回退的時候再拿出來激活,而且將不用的組件緩存清除;而
keep-alive
會把你激活過的全部組件都緩存下來
上次也說過了,是參考的keep-alive
的代碼,下面粘出部分代碼,以供參考npm
render() {
let key = this.$route.query[keyName];
const slot = this.$slots.default;
// 獲取當前頁面的vnode
const vnode = getFirstComponentChild(slot);
if (!vnode) {
return vnode;
}
// 查看當前頁面是否有緩存
let index = getIndexByKey(key);
if (index !== -1) {
// 有緩存的話就取出緩存,而且清除排在他後面的全部vnode
vnode.componentInstance = stack[index].vnode.componentInstance;
// destroy the instances that will be spliced
for (let i = index + 1; i < stack.length; i++) {
stack[i].vnode.componentInstance.$destroy();
stack[i] = null;
}
stack.splice(index + 1);
} else {
// 沒有緩存就是新的頁面,須要存儲或者是replace當前頁面
if (history.action === config.replaceName) {
// destroy the instance
stack[stack.length - 1].vnode.componentInstance.$destroy();
stack[stack.length - 1] = null;
stack.splice(stack.length - 1);
}
// 向棧裏面push
stack.push({ key, vnode });
}
vnode.data.keepAlive = true;
return vnode;
}
複製代碼
Vue 單頁應用導航管理器小程序
push
或者forward
的時候從新渲染頁面,Stack中會添加新渲染的頁面back
或者go(負數)
的時候不會從新渲染,從Stack中讀取先前的頁面,會保留好先前的內容狀態,例如表單內容,滾動條滑動的位置等back
或者go(負數)
的時候會把不用的頁面從Stack中移除replace
會更新Stack中當前頁面npm install vue-page-stack
# OR
yarn add vue-page-stack
複製代碼
import Vue from 'vue'
import VuePageStack from 'vue-page-stack';
// vue-router is necessary
Vue.use(VuePageStack, { router });
複製代碼
// App.vue
<template>
<div id="app">
<vue-page-stack>
<router-view ></router-view>
</vue-page-stack>
</div>
</template>
複製代碼
<script src="https://unpkg.com/vue-page-stack/dist/vue-page-stack.js"></script>
複製代碼
Vue.use(VuePageStack.default, { router });
複製代碼
註冊的時候能夠指定VuePageStack的名字和keyName微信小程序
use Vue.use
to install vue-page-stack
使用以前須要註冊插件
Vue.use(VuePageStack, options);
// example
Vue.use(VuePageStack, { router });
複製代碼
Options 說明:
Attribute | Description | Type | Accepted Values | Default |
---|---|---|---|---|
router | vue-router instance | Object | vue-router instance | - |
name | VuePageStack name | String | 'VuePageStack' | 'VuePageStack' |
keyName | stack-key name | String | 'stack-key' | 'stack-key' |
註冊的時候能夠指定VuePageStack的名字和keyName
Vue.use(VuePageStack, { router, name: 'VuePageStack', keyName: 'stack-key' });
複製代碼
若是想在頁面前進或者後退的時候添加一些動畫,能夠經過stack-key-dir
進行判斷
// App.vue
$route(to, from) {
if (to.params['stack-key-dir'] === 'forward') {
this.transitionName = 'forward';
} else {
this.transitionName = 'back';
}
}
複製代碼
爲何會給路由添加keyName
這個參數,是爲了支持瀏覽器的後退,前進事件,這個特性在webApp,微信公衆號和小程序很重要。目前沒找到代替的辦法,若是有思路歡迎討論哈。
獲取當前頁面實例部分參考了Vue
源碼中keep-alive
的部分
這個插件同時借鑑了vue-navigation和vue-nav,很感謝他們給的靈感。