├── examples ├── static │ └── .gitkeep ├── config │ ├── prod.env.js │ ├── dev.env.js │ └── index.js ├── build │ ├── dev-client.js │ ├── vue-loader.conf.js │ ├── build.js │ ├── webpack.dev.conf.js │ ├── webpack.base.conf.js │ ├── utils.js │ ├── dev-server.js │ └── webpack.prod.conf.js ├── index.html └── src │ ├── main.js │ ├── pages │ ├── List.vue │ ├── Index.vue │ └── Detail.vue │ ├── store │ └── index.js │ ├── router │ └── index.js │ ├── components │ └── Page.vue │ └── App.vue ├── .gitignore ├── src ├── routes.js ├── utils.js ├── components │ └── Navigation.js ├── index.js └── navigator.js ├── .editorconfig ├── .postcssrc.js ├── docs └── examples │ ├── static │ ├── css │ │ ├── app.e75e9573199a2eca689612e10834d038.css │ │ └── app.e75e9573199a2eca689612e10834d038.css.map │ └── js │ │ ├── manifest.77ca56a9f5bab52a513c.js │ │ ├── 0.b50a17303326a3e6c4a0.js │ │ ├── 1.a102ff9ff816ef7fcf2b.js │ │ ├── 2.c662248ac7d4c3397a0f.js │ │ ├── manifest.77ca56a9f5bab52a513c.js.map │ │ ├── 0.b50a17303326a3e6c4a0.js.map │ │ ├── 1.a102ff9ff816ef7fcf2b.js.map │ │ └── 2.c662248ac7d4c3397a0f.js.map │ └── index.html ├── .babelrc ├── LICENSE ├── package.json ├── README_CN.md ├── README.md └── dist ├── vue-navigation.umd.min.js ├── vue-navigation.esm.min.js ├── vue-navigation.esm.js └── vue-navigation.umd.js /examples/static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | .vscode/ 4 | node_modules/ 5 | npm-debug.log 6 | yarn-error.log 7 | examples/dist/ 8 | -------------------------------------------------------------------------------- /src/routes.js: -------------------------------------------------------------------------------- 1 | let routes = [] 2 | 3 | if (window.sessionStorage.VUE_NAVIGATION) { 4 | routes = JSON.parse(window.sessionStorage.VUE_NAVIGATION) 5 | } 6 | 7 | export default routes 8 | -------------------------------------------------------------------------------- /examples/config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/examples/static/css/app.e75e9573199a2eca689612e10834d038.css: -------------------------------------------------------------------------------- 1 | #app,body,html{height:100%;margin:0}p{margin:.5em 0}a{line-height:40px}#app{margin:0 auto;background-color:#f0f0f0;max-width:414px;height:100%}.fade-enter-active,.fade-leave-active{transition:opacity .25s}.fade-enter,.fade-leave-to{opacity:0} -------------------------------------------------------------------------------- /examples/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | examples 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "env", 5 | { 6 | "modules": false 7 | } 8 | ], 9 | "stage-2" 10 | ], 11 | "comments": false, 12 | "env": { 13 | "test": { 14 | "presets": [ 15 | "env", 16 | "stage-2" 17 | ], 18 | "plugins": [ 19 | "istanbul" 20 | ] 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var config = require('../config') 3 | var isProduction = process.env.NODE_ENV === 'production' 4 | 5 | module.exports = { 6 | loaders: utils.cssLoaders({ 7 | sourceMap: isProduction 8 | ? config.build.productionSourceMap 9 | : config.dev.cssSourceMap, 10 | extract: isProduction 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /docs/examples/index.html: -------------------------------------------------------------------------------- 1 | examples
-------------------------------------------------------------------------------- /examples/src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import App from './App' 5 | import router from './router' 6 | import store from './store' 7 | // import Navigation from '../../src' 8 | import Navigation from '../../dist/vue-navigation.esm' 9 | 10 | Vue.config.productionTip = false 11 | 12 | // you can use with vuex 13 | Vue.use(Navigation, { router, store }) 14 | // Vue.use(Navigation, {router}) 15 | 16 | /* eslint-disable no-new */ 17 | new Vue({ 18 | el: '#app', 19 | router, 20 | template: '', 21 | components: { App } 22 | }) 23 | -------------------------------------------------------------------------------- /docs/examples/static/css/app.e75e9573199a2eca689612e10834d038.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///./src/App.vue"],"names":[],"mappings":"AACA,eACE,YACA,QAAU,CAEZ,EACE,aAAe,CAEjB,EACE,gBAAkB,CAEpB,KACE,cACA,yBACA,gBACA,WAAa,CAEf,sCACE,uBAAwB,CAE1B,2BAEE,SAAU","file":"static/css/app.e75e9573199a2eca689612e10834d038.css","sourcesContent":["\nhtml, body, #app {\n height: 100%;\n margin: 0;\n}\np {\n margin: .5em 0;\n}\na {\n line-height: 40px;\n}\n#app {\n margin: 0 auto;\n background-color: #f0f0f0;\n max-width: 414px;\n height: 100%;\n}\n.fade-enter-active, .fade-leave-active {\n transition: opacity .25s\n}\n.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */\n{\n opacity: 0\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/App.vue"],"sourceRoot":""} -------------------------------------------------------------------------------- /examples/src/pages/List.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 34 | -------------------------------------------------------------------------------- /examples/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | const store = new Vuex.Store({ 7 | state: { 8 | app: 'examples' 9 | }, 10 | mutations: { 11 | // 'navigation/FORWARD': (state, {to, from}) => { 12 | // console.log('navigation/FORWARD', to, from) 13 | // }, 14 | // 'navigation/BACK': (state, {to, from}) => { 15 | // console.log('navigation/BACK', to, from) 16 | // }, 17 | // 'navigation/REPLACE': (state, {to, from}) => { 18 | // console.log('navigation/REPLACE', to, from) 19 | // }, 20 | // 'navigation/REFRESH': (state, {to, from}) => { 21 | // console.log('navigation/REFRESH', to, from) 22 | // }, 23 | // 'navigation/RESET': () => { 24 | // console.log('navigation/RESET') 25 | // } 26 | } 27 | }) 28 | 29 | export default store 30 | -------------------------------------------------------------------------------- /examples/src/pages/Index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 37 | -------------------------------------------------------------------------------- /examples/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | // import Index from '../pages/Index.vue' 4 | // import List from '../pages/List.vue' 5 | // import Detail from '../pages/Detail.vue' 6 | const Index = r => require.ensure([], () => r(require('../pages/Index.vue')), 'Index') 7 | const List = r => require.ensure([], () => r(require('../pages/List.vue')), 'List') 8 | const Detail = r => require.ensure([], () => r(require('../pages/Detail.vue')), 'Detail') 9 | 10 | Vue.use(Router) 11 | 12 | const router = new Router({ 13 | mode: 'hash', 14 | routes: [ 15 | { 16 | name: 'index', 17 | path: '/', 18 | component: Index 19 | }, 20 | { 21 | name: 'list', 22 | path: '/list', 23 | component: List 24 | }, 25 | { 26 | name: 'detail', 27 | path: '/list/:id', 28 | component: Detail 29 | }, 30 | ] 31 | }) 32 | 33 | export default router 34 | -------------------------------------------------------------------------------- /examples/build/build.js: -------------------------------------------------------------------------------- 1 | 2 | process.env.NODE_ENV = 'production' 3 | 4 | var ora = require('ora') 5 | var rm = require('rimraf') 6 | var path = require('path') 7 | var chalk = require('chalk') 8 | var webpack = require('webpack') 9 | var config = require('../config') 10 | var webpackConfig = require('./webpack.prod.conf') 11 | 12 | var spinner = ora('building for production...') 13 | spinner.start() 14 | 15 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 16 | if (err) throw err 17 | webpack(webpackConfig, function (err, stats) { 18 | spinner.stop() 19 | if (err) throw err 20 | process.stdout.write(stats.toString({ 21 | colors: true, 22 | modules: false, 23 | children: false, 24 | chunks: false, 25 | chunkModules: false 26 | }) + '\n\n') 27 | 28 | console.log(chalk.cyan(' Build complete.\n')) 29 | console.log(chalk.yellow( 30 | ' Tip: built files are meant to be served over an HTTP server.\n' + 31 | ' Opening index.html over file:// won\'t work.\n' 32 | )) 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 zack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | export function genKey() { 2 | // const t = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' 3 | const t = 'xxxxxxxx' 4 | return t.replace(/[xy]/g, function (c) { 5 | const r = Math.random() * 16 | 0 6 | const v = c === 'x' ? r : (r & 0x3 | 0x8) 7 | return v.toString(16) 8 | }) 9 | } 10 | 11 | export function getKey(route, keyName) { 12 | return `${route.name || route.path}?${route.query[keyName]}` 13 | } 14 | 15 | export function matches(pattern, name) { 16 | if (Array.isArray(pattern)) { 17 | return pattern.indexOf(name) > -1 18 | } else if (typeof pattern === 'string') { 19 | return pattern.split(',').indexOf(name) > -1 20 | } else if (isRegExp(pattern)) { 21 | return pattern.test(name) 22 | } 23 | return false 24 | } 25 | 26 | export function isObjEqual(obj1, obj2) { 27 | if (obj1 === obj2) { 28 | return true 29 | } 30 | else { 31 | const keys1 = Object.getOwnPropertyNames(obj1) 32 | const keys2 = Object.getOwnPropertyNames(obj2) 33 | if (keys1.length !== keys2.length) { 34 | return false 35 | } 36 | for (const key of keys1) { 37 | if (obj1[key] !== obj2[key]) { 38 | return false 39 | } 40 | } 41 | return true 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var webpack = require('webpack') 3 | var config = require('../config') 4 | var merge = require('webpack-merge') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 8 | 9 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // cheap-module-eval-source-map is faster for development 19 | devtool: '#cheap-module-eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env 23 | }), 24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoEmitOnErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }), 33 | new FriendlyErrorsPlugin() 34 | ] 35 | }) 36 | -------------------------------------------------------------------------------- /examples/src/pages/Detail.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 49 | -------------------------------------------------------------------------------- /examples/src/components/Page.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 35 | 36 | 74 | -------------------------------------------------------------------------------- /docs/examples/static/js/manifest.77ca56a9f5bab52a513c.js: -------------------------------------------------------------------------------- 1 | !function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var i,u,f,s=0,l=[];s 2 |
3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 43 | 44 | 74 | -------------------------------------------------------------------------------- /src/components/Navigation.js: -------------------------------------------------------------------------------- 1 | import Routes from '../routes' 2 | import { getKey, matches } from '../utils' 3 | 4 | export default (keyName) => { 5 | return { 6 | name: 'navigation', 7 | abstract: true, 8 | props: {}, 9 | data: () => ({ 10 | routes: Routes 11 | }), 12 | computed: {}, 13 | watch: { 14 | routes(val) { 15 | for (const key in this.cache) { 16 | if (!matches(val, key)) { 17 | const vnode = this.cache[key] 18 | vnode && vnode.componentInstance.$destroy() 19 | delete this.cache[key] 20 | } 21 | } 22 | }, 23 | }, 24 | created() { 25 | this.cache = {} 26 | }, 27 | destroyed() { 28 | for (const key in this.cache) { 29 | const vnode = this.cache[key] 30 | vnode && vnode.componentInstance.$destroy() 31 | } 32 | }, 33 | render() { 34 | const vnode = this.$slots.default ? this.$slots.default[0] : null 35 | if (vnode) { 36 | vnode.key = vnode.key || (vnode.isComment 37 | ? 'comment' 38 | : vnode.tag) 39 | // prevent vue-router reuse component 40 | const key = getKey(this.$route, keyName) 41 | if (vnode.key.indexOf(key) === -1) { 42 | vnode.key = `__navigation-${key}-${vnode.key}` 43 | } 44 | if (this.cache[key]) { 45 | if (vnode.key === this.cache[key].key) { 46 | // restore vnode from cache 47 | vnode.componentInstance = this.cache[key].componentInstance 48 | } else { 49 | // replace vnode to cache 50 | this.cache[key].componentInstance.$destroy() 51 | this.cache[key] = vnode 52 | } 53 | } else { 54 | // cache new vnode 55 | this.cache[key] = vnode 56 | } 57 | vnode.data.keepAlive = true 58 | } 59 | return vnode 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import Routes from './routes' 2 | import Navigator from './navigator' 3 | import NavComponent from './components/Navigation' 4 | import { genKey, isObjEqual } from './utils' 5 | 6 | export default { 7 | install: (Vue, { router, store, moduleName = 'navigation', keyName = 'VNK' } = {}) => { 8 | if (!router) { 9 | console.error('vue-navigation need options: router') 10 | return 11 | } 12 | 13 | const bus = new Vue() 14 | const navigator = Navigator(bus, store, moduleName, keyName) 15 | 16 | // hack vue-router replace for replaceFlag 17 | const routerReplace = router.replace.bind(router) 18 | let replaceFlag = false 19 | router.replace = (location, onComplete, onAbort) => { 20 | replaceFlag = true 21 | routerReplace(location, onComplete, onAbort) 22 | } 23 | 24 | // init router`s keyName 25 | router.beforeEach((to, from, next) => { 26 | if (!to.query[keyName]) { 27 | const query = { ...to.query } 28 | // go to the same route will be set the same key 29 | if (to.path === from.path && isObjEqual( 30 | { ...to.query, [keyName]: null }, 31 | { ...from.query, [keyName]: null }, 32 | ) && from.query[keyName]) { 33 | query[keyName] = from.query[keyName] 34 | } else { 35 | query[keyName] = genKey() 36 | } 37 | next({ name: to.name, params: to.params, query, replace: replaceFlag || !from.query[keyName] }) 38 | } else { 39 | next() 40 | } 41 | }) 42 | 43 | // record router change 44 | router.afterEach((to, from) => { 45 | navigator.record(to, from, replaceFlag) 46 | replaceFlag = false 47 | }) 48 | 49 | Vue.component('navigation', NavComponent(keyName)) 50 | 51 | Vue.navigation = Vue.prototype.$navigation = { 52 | on: (event, callback) => { 53 | bus.$on(event, callback) 54 | }, 55 | once: (event, callback) => { 56 | bus.$once(event, callback) 57 | }, 58 | off: (event, callback) => { 59 | bus.$off(event, callback) 60 | }, 61 | getRoutes: () => Routes.slice(), 62 | cleanRoutes: () => navigator.reset() 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /examples/build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | 15 | var cssLoader = { 16 | loader: 'css-loader', 17 | options: { 18 | minimize: process.env.NODE_ENV === 'production', 19 | sourceMap: options.sourceMap 20 | } 21 | } 22 | 23 | // generate loader string to be used with extract text Plugin 24 | function generateLoaders (loader, loaderOptions) { 25 | var loaders = [cssLoader] 26 | if (loader) { 27 | loaders.push({ 28 | loader: loader + '-loader', 29 | options: Object.assign({}, loaderOptions, { 30 | sourceMap: options.sourceMap 31 | }) 32 | }) 33 | } 34 | 35 | // Extract CSS when that option is specified 36 | // (which is the case during production build) 37 | if (options.extract) { 38 | return ExtractTextPlugin.extract({ 39 | use: loaders, 40 | fallback: 'vue-style-loader' 41 | }) 42 | } else { 43 | return ['vue-style-loader'].concat(loaders) 44 | } 45 | } 46 | 47 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html 48 | return { 49 | css: generateLoaders(), 50 | postcss: generateLoaders(), 51 | less: generateLoaders('less'), 52 | sass: generateLoaders('sass', { indentedSyntax: true }), 53 | scss: generateLoaders('sass'), 54 | stylus: generateLoaders('stylus'), 55 | styl: generateLoaders('stylus') 56 | } 57 | } 58 | 59 | // Generate loaders for standalone style files (outside of .vue) 60 | exports.styleLoaders = function (options) { 61 | var output = [] 62 | var loaders = exports.cssLoaders(options) 63 | for (var extension in loaders) { 64 | var loader = loaders[extension] 65 | output.push({ 66 | test: new RegExp('\\.' + extension + '$'), 67 | use: loader 68 | }) 69 | } 70 | return output 71 | } 72 | -------------------------------------------------------------------------------- /examples/build/dev-server.js: -------------------------------------------------------------------------------- 1 | 2 | var config = require('../config') 3 | if (!process.env.NODE_ENV) { 4 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 5 | } 6 | 7 | var opn = require('opn') 8 | var path = require('path') 9 | var express = require('express') 10 | var webpack = require('webpack') 11 | var proxyMiddleware = require('http-proxy-middleware') 12 | var webpackConfig = require('./webpack.dev.conf') 13 | 14 | // default port where dev server listens for incoming traffic 15 | var port = process.env.PORT || config.dev.port 16 | // automatically open browser, if not set will be false 17 | var autoOpenBrowser = !!config.dev.autoOpenBrowser 18 | // Define HTTP proxies to your custom API backend 19 | // https://github.com/chimurai/http-proxy-middleware 20 | var proxyTable = config.dev.proxyTable 21 | 22 | var app = express() 23 | var compiler = webpack(webpackConfig) 24 | 25 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 26 | publicPath: webpackConfig.output.publicPath, 27 | quiet: true 28 | }) 29 | 30 | var hotMiddleware = require('webpack-hot-middleware')(compiler, { 31 | log: () => { } 32 | }) 33 | // force page reload when html-webpack-Plugin template changes 34 | compiler.plugin('compilation', function (compilation) { 35 | compilation.plugin('html-webpack-Plugin-after-emit', function (data, cb) { 36 | hotMiddleware.publish({ action: 'reload' }) 37 | cb() 38 | }) 39 | }) 40 | 41 | // proxy api requests 42 | Object.keys(proxyTable).forEach(function (context) { 43 | var options = proxyTable[context] 44 | if (typeof options === 'string') { 45 | options = { target: options } 46 | } 47 | app.use(proxyMiddleware(options.filter || context, options)) 48 | }) 49 | 50 | // handle fallback for HTML5 history API 51 | app.use(require('connect-history-api-fallback')()) 52 | 53 | // serve webpack bundle output 54 | app.use(devMiddleware) 55 | 56 | // enable hot-reload and state-preserving 57 | // compilation error display 58 | app.use(hotMiddleware) 59 | 60 | // serve pure static assets 61 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 62 | app.use(staticPath, express.static('./static')) 63 | 64 | var uri = 'http://localhost:' + port 65 | 66 | devMiddleware.waitUntilValid(function () { 67 | console.log('> Listening at ' + uri + '\n') 68 | }) 69 | 70 | module.exports = app.listen(port, function (err) { 71 | if (err) { 72 | console.log(err) 73 | return 74 | } 75 | 76 | // when env is testing, don't need open it 77 | if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { 78 | opn(uri) 79 | } 80 | }) 81 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-navigation", 3 | "version": "1.1.4", 4 | "description": "A page navigation library, built with vue2 and vue-router2.", 5 | "keywords": [ 6 | "navigation", 7 | "vue", 8 | "vue-router" 9 | ], 10 | "main": "dist/vue-navigation.umd.js", 11 | "module": "dist/vue-navigation.esm.js", 12 | "files": [ 13 | "dist", 14 | "src", 15 | "examples" 16 | ], 17 | "scripts": { 18 | "dev:examples": "cd examples && node build/dev-server.js", 19 | "build": "node build/build.js", 20 | "build:examples": "cd examples && node build/build.js", 21 | "serve:examples:build": "cd docs/examples && anywhere", 22 | "version": "npm run build && npm run build:examples && git add -A", 23 | "release": "np --no-cleanup" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/zack24q/vue-navigation.git" 28 | }, 29 | "author": { 30 | "name": "zack", 31 | "email": "zack24q@gmail.com" 32 | }, 33 | "license": "MIT", 34 | "bugs": { 35 | "url": "https://github.com/zack24q/vue-navigation/issues" 36 | }, 37 | "homepage": "https://github.com/zack24q/vue-navigation#readme", 38 | "dependencies": {}, 39 | "devDependencies": { 40 | "anywhere": "^1.4.0", 41 | "autoprefixer": "^6.7.2", 42 | "babel-core": "^6.22.1", 43 | "babel-loader": "^6.2.10", 44 | "babel-plugin-transform-runtime": "^6.22.0", 45 | "babel-preset-env": "^1.2.1", 46 | "babel-preset-stage-2": "^6.22.0", 47 | "babel-register": "^6.22.0", 48 | "chalk": "^1.1.3", 49 | "connect-history-api-fallback": "^1.3.0", 50 | "copy-webpack-plugin": "^4.0.1", 51 | "css-loader": "^0.26.1", 52 | "eventsource-polyfill": "^0.9.6", 53 | "express": "^4.14.1", 54 | "extract-text-webpack-plugin": "^2.0.0", 55 | "file-loader": "^0.10.0", 56 | "filesize": "^3.5.10", 57 | "friendly-errors-webpack-plugin": "^1.1.3", 58 | "function-bind": "^1.1.0", 59 | "html-webpack-plugin": "^2.28.0", 60 | "http-proxy-middleware": "^0.17.3", 61 | "np": "^2.16.0", 62 | "opn": "^4.0.2", 63 | "optimize-css-assets-webpack-plugin": "^1.3.0", 64 | "ora": "^1.1.0", 65 | "rimraf": "^2.6.0", 66 | "rollup": "^0.41.6", 67 | "rollup-plugin-babel": "^2.7.1", 68 | "rollup-plugin-progress": "^0.2.1", 69 | "semver": "^5.3.0", 70 | "uglify-es": "^3.0.26", 71 | "uglify-js": "^3.0.26", 72 | "url-loader": "^0.5.7", 73 | "vue": "^2.4.2", 74 | "vue-loader": "^11.1.4", 75 | "vue-router": "^2.7.0", 76 | "vue-style-loader": "^2.0.0", 77 | "vue-template-compiler": "^2.2.4", 78 | "vuex": "^2.3.1", 79 | "webpack": "^2.2.1", 80 | "webpack-bundle-analyzer": "^2.2.1", 81 | "webpack-dev-middleware": "^1.10.0", 82 | "webpack-hot-middleware": "^2.16.1", 83 | "webpack-merge": "^2.6.1" 84 | }, 85 | "browserslist": [ 86 | "> 1%", 87 | "last 2 versions", 88 | "not ie <= 8" 89 | ] 90 | } 91 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | # vue-navigation 2 | 3 | [![npm](https://img.shields.io/npm/dm/vue-navigation.svg)](https://www.npmjs.com/package/vue-navigation) 4 | [![npm](https://img.shields.io/npm/v/vue-navigation.svg)](https://www.npmjs.com/package/vue-navigation) 5 | [![npm](https://img.shields.io/npm/l/vue-navigation.svg)](https://www.npmjs.com/package/vue-navigation) 6 | [![Github file size](https://img.shields.io/github/size/zack24q/vue-navigation/dist/vue-navigation.esm.min.js.svg)](https://github.com/zack24q/vue-navigation/blob/master/dist/vue-navigation.esm.min.js) 7 | 8 | > 需要 [vue](https://github.com/vuejs/vue) `2.x` 与 [vue-router](https://github.com/vuejs/vue-router) `2.x`。 9 | 10 | 11 | 导航默认行为类似手机APP的页面导航(A、B、C为页面): 12 | 13 | 1. A前进到B,再前进到C; 14 | 2. C返回到B时,B会**从缓存中恢复**; 15 | 3. B再次前进到C,C会**重新生成,不会从缓存中恢复**; 16 | 4. C前进到A,A会**生成,现在路由中包含2个A实例**。 17 | 18 | **!重要:vue-navigation在url中添加了一个key来区分路由。key的名称默认为VNK,可以修改。** 19 | 20 | ### 在线演示 21 | 22 | [演示地址](https://zack24q.github.io/vue-navigation/examples/) 23 | 24 | [代码地址](https://github.com/zack24q/vue-navigation/tree/master/examples) 25 | 26 | ## 安装 27 | 28 | ```bash 29 | npm i -S vue-navigation 30 | ``` 31 | 32 | 或 33 | 34 | ```bash 35 | yarn add vue-navigation 36 | ``` 37 | 38 | ## 使用 39 | 40 | ### 基础使用 41 | 42 | main.js 43 | 44 | ```javascript 45 | import Vue from 'vue' 46 | import router from './router' // vue-router 实例 47 | import Navigation from 'vue-navigation' 48 | 49 | Vue.use(Navigation, {router}) 50 | // 启动你的应用... 51 | ``` 52 | App.vue 53 | 54 | ```vue 55 | 60 | ``` 61 | 62 | ### 搭配vuex2使用 63 | 64 | main.js 65 | 66 | ```javascript 67 | import Vue from 'vue' 68 | import router from './router' // vue-router 实例 69 | import store from './store' // vuex store 实例 70 | import Navigation from 'vue-navigation' 71 | 72 | Vue.use(Navigation, {router, store}) 73 | // 启动你的应用... 74 | ``` 75 | 76 | 传入 `store` 后,`vue-navigation` 会向 `store` 注册一个Module(Module的默认名称为 `navigation`),同时在页面跳转时会提交 `navigation/FORWARD` 或 `navigation/BACK` 或 `navigation/REFRESH`。 77 | 78 | ## Options 79 | 80 | 只有`route`是必须的. 81 | 82 | ```javascript 83 | Vue.use(Navigation, {router, store, moduleName: 'navigation', keyName: 'VNK'}) 84 | ``` 85 | 86 | ### 事件 87 | 方法: [ `on` | `once` | `off` ] 88 | 89 | 事件类型: [ `forward` | `back` | `replace` | `refresh` | `reset` ] 90 | 91 | 参数( `to` | `from` ) 的属性: 92 | - `name` 93 | - 类型: string 94 | - 描述: 路由的名称(包含key) 95 | - `route` 96 | - 类型: object 97 | - 描述: vue-route的路由信息对象 98 | 99 | ```javascript 100 | this.$navigation.on('forward', (to, from) => {}) 101 | this.$navigation.once('back', (to, from) => {}) 102 | this.$navigation.on('replace', (to, from) => {}) 103 | this.$navigation.off('refresh', (to, from) => {}) 104 | this.$navigation.on('reset', () => {}) 105 | ``` 106 | 107 | ## 方法 108 | 109 | 在全局环境中使用 `Vue.navigation` 或在Vue实例中使用 `this.$navigation` 110 | 111 | - `getRoutes()` 获取路由记录 112 | - `cleanRoutes()` 清空路由记录 113 | -------------------------------------------------------------------------------- /docs/examples/static/js/0.b50a17303326a3e6c4a0.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([0],{18:function(t,e,n){var o=n(5)(n(26),n(27),null,null);t.exports=o.exports},19:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={name:"page",data:function(){return{scrollTop:0}},methods:{back:function(){window.history.back()},scroll:function(){this.scrollTop=this.$refs.content.scrollTop}},activated:function(){this.$refs.content.scrollTop=this.scrollTop}}},20:function(t,e,n){e=t.exports=n(14)(),e.push([t.i,".page{height:100%;position:relative}.header{background-color:#fff;position:absolute;width:100%;top:0;height:48px;line-height:48px;border-bottom:1px solid #e0e0e0;display:-webkit-box;display:-ms-flexbox;display:flex}.left,.right{width:40px;padding:0 10px;cursor:pointer}.center{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:center}.content{padding:0 10px;position:absolute;box-sizing:border-box;width:100%;top:49px;bottom:0;overflow:auto}","",{version:3,sources:["/Users/zack/Documents/projects/vue-navigation/examples/src/components/Page.vue"],names:[],mappings:"AACA,MACE,YAAa,AACb,iBAAmB,CACpB,AACD,QACE,sBAAuB,AACvB,kBAAmB,AACnB,WAAY,AACZ,MAAS,AACT,YAAa,AACb,iBAAkB,AAClB,gCAAiC,AACjC,oBAAqB,AACrB,oBAAqB,AACrB,YAAc,CACf,AACD,aACE,WAAY,AACZ,eAAgB,AAChB,cAAgB,CACjB,AACD,QACE,mBAAoB,AAChB,WAAY,AACR,OAAQ,AAChB,iBAAmB,CACpB,AACD,SACE,eAAgB,AAChB,kBAAmB,AACnB,sBAAuB,AACvB,WAAY,AACZ,SAAU,AACV,SAAY,AACZ,aAAe,CAChB",file:"Page.vue",sourcesContent:["\n.page {\n height: 100%;\n position: relative;\n}\n.header {\n background-color: #fff;\n position: absolute;\n width: 100%;\n top: 0px;\n height: 48px;\n line-height: 48px;\n border-bottom: 1px solid #e0e0e0;\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n}\n.left, .right {\n width: 40px;\n padding: 0 10px;\n cursor: pointer;\n}\n.center {\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n text-align: center;\n}\n.content {\n padding: 0 10px;\n position: absolute;\n box-sizing: border-box;\n width: 100%;\n top: 49px;\n bottom: 0px;\n overflow: auto;\n}\n"],sourceRoot:""}])},21:function(t,e,n){var o=n(20);"string"==typeof o&&(o=[[t.i,o,""]]),o.locals&&(t.exports=o.locals);n(15)("0f8cd410",o,!0)},22:function(t,e,n){n(21);var o=n(5)(n(19),n(23),null,null);t.exports=o.exports},23:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"page"},[n("div",{staticClass:"header"},[n("div",{staticClass:"left",on:{click:t.back}},[t._v("back")]),t._v(" "),n("div",{staticClass:"center"},[t._v("title")]),t._v(" "),n("div",{staticClass:"right"})]),t._v(" "),n("div",{ref:"content",staticClass:"content",on:{scroll:t.scroll}},[t._t("default")],2)])},staticRenderFns:[]}},26:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(22),i=n.n(o);e.default={components:{Page:i.a},data:function(){return{random:Math.random().toFixed(4)}},activated:function(){console.log("list activated")},deactivated:function(){console.log("list deactivated")},destroyed:function(){console.log("list destroyed")}}},27:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("page",[n("div",{staticClass:"list"},[n("p",[t._v("This is the "),n("b",[t._v("list")]),t._v(" page")]),t._v(" "),n("p",[t._v("random number: "+t._s(t.random))]),t._v(" "),t._l(30,function(e){return n("p",{key:e},[n("router-link",{attrs:{to:"list/"+e}},[t._v("go to detail page(id: "+t._s(e)+")")])],1)})],2)])},staticRenderFns:[]}}}); 2 | //# sourceMappingURL=0.b50a17303326a3e6c4a0.js.map -------------------------------------------------------------------------------- /docs/examples/static/js/1.a102ff9ff816ef7fcf2b.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([1],[,,,,,,,,,,,,,,,,,function(e,t,n){var o=n(5)(n(25),n(29),null,null);e.exports=o.exports},,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={name:"page",data:function(){return{scrollTop:0}},methods:{back:function(){window.history.back()},scroll:function(){this.scrollTop=this.$refs.content.scrollTop}},activated:function(){this.$refs.content.scrollTop=this.scrollTop}}},function(e,t,n){t=e.exports=n(14)(),t.push([e.i,".page{height:100%;position:relative}.header{background-color:#fff;position:absolute;width:100%;top:0;height:48px;line-height:48px;border-bottom:1px solid #e0e0e0;display:-webkit-box;display:-ms-flexbox;display:flex}.left,.right{width:40px;padding:0 10px;cursor:pointer}.center{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:center}.content{padding:0 10px;position:absolute;box-sizing:border-box;width:100%;top:49px;bottom:0;overflow:auto}","",{version:3,sources:["/Users/zack/Documents/projects/vue-navigation/examples/src/components/Page.vue"],names:[],mappings:"AACA,MACE,YAAa,AACb,iBAAmB,CACpB,AACD,QACE,sBAAuB,AACvB,kBAAmB,AACnB,WAAY,AACZ,MAAS,AACT,YAAa,AACb,iBAAkB,AAClB,gCAAiC,AACjC,oBAAqB,AACrB,oBAAqB,AACrB,YAAc,CACf,AACD,aACE,WAAY,AACZ,eAAgB,AAChB,cAAgB,CACjB,AACD,QACE,mBAAoB,AAChB,WAAY,AACR,OAAQ,AAChB,iBAAmB,CACpB,AACD,SACE,eAAgB,AAChB,kBAAmB,AACnB,sBAAuB,AACvB,WAAY,AACZ,SAAU,AACV,SAAY,AACZ,aAAe,CAChB",file:"Page.vue",sourcesContent:["\n.page {\n height: 100%;\n position: relative;\n}\n.header {\n background-color: #fff;\n position: absolute;\n width: 100%;\n top: 0px;\n height: 48px;\n line-height: 48px;\n border-bottom: 1px solid #e0e0e0;\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n}\n.left, .right {\n width: 40px;\n padding: 0 10px;\n cursor: pointer;\n}\n.center {\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n text-align: center;\n}\n.content {\n padding: 0 10px;\n position: absolute;\n box-sizing: border-box;\n width: 100%;\n top: 49px;\n bottom: 0px;\n overflow: auto;\n}\n"],sourceRoot:""}])},function(e,t,n){var o=n(20);"string"==typeof o&&(o=[[e.i,o,""]]),o.locals&&(e.exports=o.locals);n(15)("0f8cd410",o,!0)},function(e,t,n){n(21);var o=n(5)(n(19),n(23),null,null);e.exports=o.exports},function(e,t){e.exports={render:function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"page"},[n("div",{staticClass:"header"},[n("div",{staticClass:"left",on:{click:e.back}},[e._v("back")]),e._v(" "),n("div",{staticClass:"center"},[e._v("title")]),e._v(" "),n("div",{staticClass:"right"})]),e._v(" "),n("div",{ref:"content",staticClass:"content",on:{scroll:e.scroll}},[e._t("default")],2)])},staticRenderFns:[]}},,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=n(22),i=n.n(o);t.default={components:{Page:i.a},data:function(){return{random:Math.random().toFixed(4)}},activated:function(){console.log("index activated")},deactivated:function(){console.log("index deactivated")},destroyed:function(){console.log("index destroyed")}}},,,,function(e,t){e.exports={render:function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("page",[n("div",{staticClass:"index"},[n("p",[e._v("This is the "),n("b",[e._v("index")]),e._v(" page")]),e._v(" "),n("p",[e._v("random number: "+e._s(e.random))]),e._v(" "),n("p",[n("router-link",{attrs:{to:"/"}},[e._v("go to index page")])],1),e._v(" "),n("p",[n("router-link",{attrs:{to:"list"}},[e._v("go to list page")])],1)])])},staticRenderFns:[]}}]); 2 | //# sourceMappingURL=1.a102ff9ff816ef7fcf2b.js.map -------------------------------------------------------------------------------- /src/navigator.js: -------------------------------------------------------------------------------- 1 | import Routes from './routes' 2 | import { getKey } from './utils' 3 | 4 | export default (bus, store, moduleName, keyName) => { 5 | if (store) { 6 | store.registerModule(moduleName, { 7 | state: { 8 | routes: Routes 9 | }, 10 | mutations: { 11 | 'navigation/FORWARD': (state, { to, from, name }) => { 12 | state.routes.push(name) 13 | }, 14 | 'navigation/BACK': (state, { to, from, count }) => { 15 | state.routes.splice(state.routes.length - count, count) 16 | }, 17 | 'navigation/REPLACE': (state, { to, from, name }) => { 18 | state.routes.splice(Routes.length - 1, 1, name) 19 | }, 20 | 'navigation/REFRESH': (state, { to, from }) => { 21 | }, 22 | 'navigation/RESET': (state) => { 23 | state.routes.splice(0, state.routes.length) 24 | } 25 | } 26 | }) 27 | } 28 | 29 | const forward = (name, toRoute, fromRoute) => { 30 | const to = { route: toRoute } 31 | const from = { route: fromRoute } 32 | const routes = store ? store.state[moduleName].routes : Routes 33 | // if from does not exist, it will be set null 34 | from.name = routes[routes.length - 1] || null 35 | to.name = name 36 | store ? store.commit('navigation/FORWARD', { to, from, name }) : routes.push(name) 37 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify(routes) 38 | bus.$emit('forward', to, from) 39 | } 40 | const back = (count, toRoute, fromRoute) => { 41 | const to = { route: toRoute } 42 | const from = { route: fromRoute } 43 | const routes = store ? store.state[moduleName].routes : Routes 44 | from.name = routes[routes.length - 1] 45 | to.name = routes[routes.length - 1 - count] 46 | store ? store.commit('navigation/BACK', { to, from, count }) : routes.splice(Routes.length - count, count) 47 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify(routes) 48 | bus.$emit('back', to, from) 49 | } 50 | const replace = (name, toRoute, fromRoute) => { 51 | const to = { route: toRoute } 52 | const from = { route: fromRoute } 53 | const routes = store ? store.state[moduleName].routes : Routes 54 | // if from does not exist, it will be set null 55 | from.name = routes[routes.length - 1] || null 56 | to.name = name 57 | store ? store.commit('navigation/REPLACE', { to, from, name }) : routes.splice(Routes.length - 1, 1, name) 58 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify(routes) 59 | bus.$emit('replace', to, from) 60 | } 61 | const refresh = (toRoute, fromRoute) => { 62 | const to = { route: toRoute } 63 | const from = { route: fromRoute } 64 | const routes = store ? store.state[moduleName].routes : Routes 65 | to.name = from.name = routes[routes.length - 1] 66 | store ? store.commit('navigation/REFRESH', { to, from }) : null 67 | bus.$emit('refresh', to, from) 68 | } 69 | const reset = () => { 70 | store ? store.commit('navigation/RESET') : Routes.splice(0, Routes.length) 71 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify([]) 72 | bus.$emit('reset') 73 | } 74 | 75 | const record = (toRoute, fromRoute, replaceFlag) => { 76 | const name = getKey(toRoute, keyName) 77 | if (replaceFlag) { 78 | replace(name, toRoute, fromRoute) 79 | } else { 80 | const toIndex = Routes.lastIndexOf(name) 81 | if (toIndex === -1) { 82 | forward(name, toRoute, fromRoute) 83 | } else if (toIndex === Routes.length - 1) { 84 | refresh(toRoute, fromRoute) 85 | } else { 86 | back(Routes.length - 1 - toIndex, toRoute, fromRoute) 87 | } 88 | } 89 | } 90 | 91 | return { 92 | record, reset 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-navigation 2 | 3 | [![npm](https://img.shields.io/npm/dm/vue-navigation.svg)](https://www.npmjs.com/package/vue-navigation) 4 | [![npm](https://img.shields.io/npm/v/vue-navigation.svg)](https://www.npmjs.com/package/vue-navigation) 5 | [![npm](https://img.shields.io/npm/l/vue-navigation.svg)](https://www.npmjs.com/package/vue-navigation) 6 | [![Github file size](https://img.shields.io/github/size/zack24q/vue-navigation/dist/vue-navigation.esm.min.js.svg)](https://github.com/zack24q/vue-navigation/blob/master/dist/vue-navigation.esm.min.js) 7 | 8 | > require [vue](https://github.com/vuejs/vue) `2.x` and [vue-router](https://github.com/vuejs/vue-router) `2.x`. 9 | 10 | [中文文档](https://github.com/zack24q/vue-navigation/blob/master/README_CN.md) 11 | 12 | vue-navigation default behavior is similar to native mobile app (A、B、C are pages): 13 | 14 | 1. A forward to B, then forward to C; 15 | 2. C back to B, B will **recover from cache**; 16 | 3. B forward to C again, C will **rebuild, not recover from cache**; 17 | 4. C forward to A, A will **build, now the route contains two A instance**. 18 | 19 | **!important: vue-navigation adds a key to the url to distinguish the route. The default name of the key is VNK, which can be modified.** 20 | 21 | ### DEMO 22 | 23 | [DEMO](https://zack24q.github.io/vue-navigation/examples/) 24 | 25 | [CODE](https://github.com/zack24q/vue-navigation/tree/master/examples) 26 | 27 | ## Installing 28 | 29 | ```bash 30 | npm i -S vue-navigation 31 | ``` 32 | 33 | or 34 | 35 | ```bash 36 | yarn add vue-navigation 37 | ``` 38 | 39 | ## Usage 40 | 41 | ### Basic Usage 42 | 43 | main.js 44 | 45 | ```javascript 46 | import Vue from 'vue' 47 | import router from './router' // vue-router instance 48 | import Navigation from 'vue-navigation' 49 | 50 | Vue.use(Navigation, {router}) 51 | // bootstrap your app... 52 | ``` 53 | App.vue 54 | 55 | ```vue 56 | 61 | ``` 62 | 63 | ### Use with vuex2 64 | 65 | main.js 66 | 67 | ```javascript 68 | import Vue from 'vue' 69 | import router from './router' // vue-router instance 70 | import store from './store' // vuex store instance 71 | import Navigation from 'vue-navigation' 72 | 73 | Vue.use(Navigation, {router, store}) 74 | // bootstrap your app... 75 | ``` 76 | 77 | After passing in `store`, `vue-navigation` will register a module in `store` (default module name is `navigation`), and commit `navigation/FORWARD` or `navigation/BACK` or `navigation/REFRESH` when the page jumps. 78 | 79 | ## Options 80 | 81 | Only `router` is required. 82 | 83 | ```javascript 84 | Vue.use(Navigation, {router, store, moduleName: 'navigation', keyName: 'VNK'}) 85 | ``` 86 | 87 | ## Events 88 | functions: [ `on` | `once` | `off` ] 89 | 90 | event types: [ `forward` | `back` | `replace` | `refresh` | `reset` ] 91 | 92 | parameter( `to` | `from` ) properties: 93 | - `name` 94 | - type: string 95 | - desc: name of the route(contains the key) 96 | - `route` 97 | - type: object 98 | - desc: vue-route`s route object 99 | 100 | ```javascript 101 | this.$navigation.on('forward', (to, from) => {}) 102 | this.$navigation.once('back', (to, from) => {}) 103 | this.$navigation.on('replace', (to, from) => {}) 104 | this.$navigation.off('refresh', (to, from) => {}) 105 | this.$navigation.on('reset', () => {}) 106 | ``` 107 | 108 | ## Methods 109 | 110 | Use `Vue.navigation` in global environment or use `this.$navigation` in vue instance. 111 | 112 | - `getRoutes()` get the routing records 113 | - `cleanRoutes()` clean the routing records 114 | -------------------------------------------------------------------------------- /docs/examples/static/js/2.c662248ac7d4c3397a0f.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([2],[,,,,,,,,,,,,,,,,function(t,e,o){var n=o(5)(o(24),o(28),null,null);t.exports=n.exports},,,function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={name:"page",data:function(){return{scrollTop:0}},methods:{back:function(){window.history.back()},scroll:function(){this.scrollTop=this.$refs.content.scrollTop}},activated:function(){this.$refs.content.scrollTop=this.scrollTop}}},function(t,e,o){e=t.exports=o(14)(),e.push([t.i,".page{height:100%;position:relative}.header{background-color:#fff;position:absolute;width:100%;top:0;height:48px;line-height:48px;border-bottom:1px solid #e0e0e0;display:-webkit-box;display:-ms-flexbox;display:flex}.left,.right{width:40px;padding:0 10px;cursor:pointer}.center{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:center}.content{padding:0 10px;position:absolute;box-sizing:border-box;width:100%;top:49px;bottom:0;overflow:auto}","",{version:3,sources:["/Users/zack/Documents/projects/vue-navigation/examples/src/components/Page.vue"],names:[],mappings:"AACA,MACE,YAAa,AACb,iBAAmB,CACpB,AACD,QACE,sBAAuB,AACvB,kBAAmB,AACnB,WAAY,AACZ,MAAS,AACT,YAAa,AACb,iBAAkB,AAClB,gCAAiC,AACjC,oBAAqB,AACrB,oBAAqB,AACrB,YAAc,CACf,AACD,aACE,WAAY,AACZ,eAAgB,AAChB,cAAgB,CACjB,AACD,QACE,mBAAoB,AAChB,WAAY,AACR,OAAQ,AAChB,iBAAmB,CACpB,AACD,SACE,eAAgB,AAChB,kBAAmB,AACnB,sBAAuB,AACvB,WAAY,AACZ,SAAU,AACV,SAAY,AACZ,aAAe,CAChB",file:"Page.vue",sourcesContent:["\n.page {\n height: 100%;\n position: relative;\n}\n.header {\n background-color: #fff;\n position: absolute;\n width: 100%;\n top: 0px;\n height: 48px;\n line-height: 48px;\n border-bottom: 1px solid #e0e0e0;\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n}\n.left, .right {\n width: 40px;\n padding: 0 10px;\n cursor: pointer;\n}\n.center {\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n text-align: center;\n}\n.content {\n padding: 0 10px;\n position: absolute;\n box-sizing: border-box;\n width: 100%;\n top: 49px;\n bottom: 0px;\n overflow: auto;\n}\n"],sourceRoot:""}])},function(t,e,o){var n=o(20);"string"==typeof n&&(n=[[t.i,n,""]]),n.locals&&(t.exports=n.locals);o(15)("0f8cd410",n,!0)},function(t,e,o){o(21);var n=o(5)(o(19),o(23),null,null);t.exports=n.exports},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,o=t._self._c||e;return o("div",{staticClass:"page"},[o("div",{staticClass:"header"},[o("div",{staticClass:"left",on:{click:t.back}},[t._v("back")]),t._v(" "),o("div",{staticClass:"center"},[t._v("title")]),t._v(" "),o("div",{staticClass:"right"})]),t._v(" "),o("div",{ref:"content",staticClass:"content",on:{scroll:t.scroll}},[t._t("default")],2)])},staticRenderFns:[]}},function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=o(22),i=o.n(n);e.default={components:{Page:i.a},data:function(){return{id:Number(this.$route.params.id),random:Math.random().toFixed(4)}},activated:function(){console.log("detail activated")},deactivated:function(){console.log("detail deactivated")},destroyed:function(){console.log("detail destroyed")},methods:{replaceToNextDetail:function(){this.$router.replace("/list/"+(this.id>=30?30:this.id+1))},goToNextDetail:function(){this.$router.push("/list/"+(this.id>=30?30:this.id+1))},goToIndex:function(){this.$router.push("/")}}}},,,,function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,o=t._self._c||e;return o("page",[o("div",{staticClass:"detail"},[o("p",[t._v("This is the "),o("b",[t._v("detail")]),t._v(" page, detail id is "+t._s(t.id))]),t._v(" "),o("p",[t._v("random number: "+t._s(t.random))]),t._v(" "),o("a",{attrs:{href:"javascript:void(0)"},on:{click:t.replaceToNextDetail}},[t._v("replace to next detail")]),t._v(" "),o("br"),t._v(" "),o("a",{attrs:{href:"javascript:void(0)"},on:{click:t.goToNextDetail}},[t._v("go to next detail")]),t._v(" "),o("br"),t._v(" "),o("a",{attrs:{href:"javascript:void(0)"},on:{click:t.goToIndex}},[t._v("go to index")])])])},staticRenderFns:[]}}]); 2 | //# sourceMappingURL=2.c662248ac7d4c3397a0f.js.map -------------------------------------------------------------------------------- /examples/build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | var webpack = require('webpack') 4 | var config = require('../config') 5 | var merge = require('webpack-merge') 6 | var baseWebpackConfig = require('./webpack.base.conf') 7 | var CopyWebpackPlugin = require('copy-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 10 | var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 11 | 12 | var env = config.build.env 13 | 14 | var webpackConfig = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ 17 | sourceMap: config.build.productionSourceMap, 18 | extract: true 19 | }) 20 | }, 21 | devtool: config.build.productionSourceMap ? '#source-map' : false, 22 | output: { 23 | path: config.build.assetsRoot, 24 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 25 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 26 | }, 27 | plugins: [ 28 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 29 | new webpack.DefinePlugin({ 30 | 'process.env': env 31 | }), 32 | new webpack.optimize.UglifyJsPlugin({ 33 | compress: { 34 | warnings: false 35 | }, 36 | sourceMap: true 37 | }), 38 | // extract css into its own file 39 | new ExtractTextPlugin({ 40 | filename: utils.assetsPath('css/[name].[contenthash].css') 41 | }), 42 | // Compress extracted CSS. We are using this Plugin so that possible 43 | // duplicated CSS from different components can be deduped. 44 | new OptimizeCSSPlugin(), 45 | // generate dist index.html with correct asset hash for caching. 46 | // you can customize output by editing /index.html 47 | // see https://github.com/ampedandwired/html-webpack-plugin 48 | new HtmlWebpackPlugin({ 49 | filename: config.build.index, 50 | template: 'index.html', 51 | inject: true, 52 | minify: { 53 | removeComments: true, 54 | collapseWhitespace: true, 55 | removeAttributeQuotes: true 56 | // more options: 57 | // https://github.com/kangax/html-minifier#options-quick-reference 58 | }, 59 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 60 | chunksSortMode: 'dependency' 61 | }), 62 | // split vendor js into its own file 63 | new webpack.optimize.CommonsChunkPlugin({ 64 | name: 'vendor', 65 | minChunks: function (module, count) { 66 | // any required modules inside node_modules are extracted to vendor 67 | return ( 68 | module.resource && 69 | /\.js$/.test(module.resource) && 70 | module.resource.indexOf( 71 | path.join(__dirname, '../node_modules') 72 | ) === 0 73 | ) 74 | } 75 | }), 76 | // extract webpack runtime and module manifest to its own file in order to 77 | // prevent vendor hash from being updated whenever app bundle is updated 78 | new webpack.optimize.CommonsChunkPlugin({ 79 | name: 'manifest', 80 | chunks: ['vendor'] 81 | }), 82 | // copy custom static assets 83 | new CopyWebpackPlugin([ 84 | { 85 | from: path.resolve(__dirname, '../static'), 86 | to: config.build.assetsSubDirectory, 87 | ignore: ['.*'] 88 | } 89 | ]) 90 | ] 91 | }) 92 | 93 | if (config.build.productionGzip) { 94 | var CompressionWebpackPlugin = require('compression-webpack-Plugin') 95 | 96 | webpackConfig.plugins.push( 97 | new CompressionWebpackPlugin({ 98 | asset: '[path].gz[query]', 99 | algorithm: 'gzip', 100 | test: new RegExp( 101 | '\\.(' + 102 | config.build.productionGzipExtensions.join('|') + 103 | ')$' 104 | ), 105 | threshold: 10240, 106 | minRatio: 0.8 107 | }) 108 | ) 109 | } 110 | 111 | if (config.build.bundleAnalyzerReport) { 112 | var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 113 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 114 | } 115 | 116 | module.exports = webpackConfig 117 | -------------------------------------------------------------------------------- /dist/vue-navigation.umd.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * vue-navigation v1.1.4 3 | * https://github.com/zack24q/vue-navigation 4 | * Released under the MIT License. 5 | */ 6 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.VueNavigation=t()}(this,function(){"use strict";function e(){return"xxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}function t(e,t){return(e.name||e.path)+"?"+e.query[t]}function n(e,t){return Array.isArray(e)?e.indexOf(t)>-1:"string"==typeof e?e.split(",").indexOf(t)>-1:!!isRegExp(e)&&e.test(t)}function o(e,t){if(e===t)return!0;var n=Object.getOwnPropertyNames(e),o=Object.getOwnPropertyNames(t);if(n.length!==o.length)return!1;var r=!0,i=!1,a=void 0;try{for(var c,u=n[Symbol.iterator]();!(r=(c=u.next()).done);r=!0){var s=c.value;if(e[s]!==t[s])return!1}}catch(e){i=!0,a=e}finally{try{!r&&u.return&&u.return()}finally{if(i)throw a}}return!0}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var i=[];window.sessionStorage.VUE_NAVIGATION&&(i=JSON.parse(window.sessionStorage.VUE_NAVIGATION));var a=i,c=function(e,n,o,r){n&&n.registerModule(o,{state:{routes:a},mutations:{"navigation/FORWARD":function(e,t){t.to,t.from;var n=t.name;e.routes.push(n)},"navigation/BACK":function(e,t){t.to,t.from;var n=t.count;e.routes.splice(e.routes.length-n,n)},"navigation/REPLACE":function(e,t){t.to,t.from;var n=t.name;e.routes.splice(a.length-1,1,n)},"navigation/REFRESH":function(e,t){t.to,t.from},"navigation/RESET":function(e){e.routes.splice(0,e.routes.length)}}});var i=function(t,r,i){var c={route:r},u={route:i},s=n?n.state[o].routes:a;u.name=s[s.length-1]||null,c.name=t,n?n.commit("navigation/FORWARD",{to:c,from:u,name:t}):s.push(t),window.sessionStorage.VUE_NAVIGATION=JSON.stringify(s),e.$emit("forward",c,u)},c=function(t,r,i){var c={route:r},u={route:i},s=n?n.state[o].routes:a;u.name=s[s.length-1],c.name=s[s.length-1-t],n?n.commit("navigation/BACK",{to:c,from:u,count:t}):s.splice(a.length-t,t),window.sessionStorage.VUE_NAVIGATION=JSON.stringify(s),e.$emit("back",c,u)},u=function(t,r,i){var c={route:r},u={route:i},s=n?n.state[o].routes:a;u.name=s[s.length-1]||null,c.name=t,n?n.commit("navigation/REPLACE",{to:c,from:u,name:t}):s.splice(a.length-1,1,t),window.sessionStorage.VUE_NAVIGATION=JSON.stringify(s),e.$emit("replace",c,u)},s=function(t,r){var i={route:t},c={route:r},u=n?n.state[o].routes:a;i.name=c.name=u[u.length-1],n&&n.commit("navigation/REFRESH",{to:i,from:c}),e.$emit("refresh",i,c)};return{record:function(e,n,o){var f=t(e,r);if(o)u(f,e,n);else{var l=a.lastIndexOf(f);-1===l?i(f,e,n):l===a.length-1?s(e,n):c(a.length-1-l,e,n)}},reset:function(){n?n.commit("navigation/RESET"):a.splice(0,a.length),window.sessionStorage.VUE_NAVIGATION=JSON.stringify([]),e.$emit("reset")}}},u=function(e){return{name:"navigation",abstract:!0,props:{},data:function(){return{routes:a}},computed:{},watch:{routes:function(e){for(var t in this.cache)if(!n(e,t)){var o=this.cache[t];o&&o.componentInstance.$destroy(),delete this.cache[t]}}},created:function(){this.cache={}},destroyed:function(){for(var e in this.cache){var t=this.cache[e];t&&t.componentInstance.$destroy()}},render:function(){var n=this.$slots.default?this.$slots.default[0]:null;if(n){n.key=n.key||(n.isComment?"comment":n.tag);var o=t(this.$route,e);-1===n.key.indexOf(o)&&(n.key="__navigation-"+o+"-"+n.key),this.cache[o]?n.key===this.cache[o].key?n.componentInstance=this.cache[o].componentInstance:(this.cache[o].componentInstance.$destroy(),this.cache[o]=n):this.cache[o]=n,n.data.keepAlive=!0}return n}}},s=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{},i=n.router,f=n.store,l=n.moduleName,m=void 0===l?"navigation":l,h=n.keyName,g=void 0===h?"VNK":h;if(i){var v=new t,p=c(v,f,m,g),d=i.replace.bind(i),y=!1;i.replace=function(e,t,n){y=!0,d(e,t,n)},i.beforeEach(function(t,n,i){if(t.query[g])i();else{var a=s({},t.query);t.path===n.path&&o(s({},t.query,r({},g,null)),s({},n.query,r({},g,null)))&&n.query[g]?a[g]=n.query[g]:a[g]=e(),i({name:t.name,params:t.params,query:a,replace:y||!n.query[g]})}}),i.afterEach(function(e,t){p.record(e,t,y),y=!1}),t.component("navigation",u(g)),t.navigation=t.prototype.$navigation={on:function(e,t){v.$on(e,t)},once:function(e,t){v.$once(e,t)},off:function(e,t){v.$off(e,t)},getRoutes:function(){return a.slice()},cleanRoutes:function(){return p.reset()}}}else console.error("vue-navigation need options: router")}}}); -------------------------------------------------------------------------------- /dist/vue-navigation.esm.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * vue-navigation v1.1.4 3 | * https://github.com/zack24q/vue-navigation 4 | * Released under the MIT License. 5 | */ 6 | function genKey(){return"xxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}function getKey(e,t){return(e.name||e.path)+"?"+e.query[t]}function matches(e,t){return Array.isArray(e)?e.indexOf(t)>-1:"string"==typeof e?e.split(",").indexOf(t)>-1:!!isRegExp(e)&&e.test(t)}function isObjEqual(e,t){if(e===t)return!0;var n=Object.getOwnPropertyNames(e),o=Object.getOwnPropertyNames(t);if(n.length!==o.length)return!1;var r=!0,a=!1,i=void 0;try{for(var s,u=n[Symbol.iterator]();!(r=(s=u.next()).done);r=!0){var c=s.value;if(e[c]!==t[c])return!1}}catch(e){a=!0,i=e}finally{try{!r&&u.return&&u.return()}finally{if(a)throw i}}return!0}function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var routes=[];window.sessionStorage.VUE_NAVIGATION&&(routes=JSON.parse(window.sessionStorage.VUE_NAVIGATION));var Routes=routes,Navigator=function(e,t,n,o){t&&t.registerModule(n,{state:{routes:Routes},mutations:{"navigation/FORWARD":function(e,t){t.to,t.from;var n=t.name;e.routes.push(n)},"navigation/BACK":function(e,t){t.to,t.from;var n=t.count;e.routes.splice(e.routes.length-n,n)},"navigation/REPLACE":function(e,t){t.to,t.from;var n=t.name;e.routes.splice(Routes.length-1,1,n)},"navigation/REFRESH":function(e,t){t.to,t.from},"navigation/RESET":function(e){e.routes.splice(0,e.routes.length)}}});var r=function(o,r,a){var i={route:r},s={route:a},u=t?t.state[n].routes:Routes;s.name=u[u.length-1]||null,i.name=o,t?t.commit("navigation/FORWARD",{to:i,from:s,name:o}):u.push(o),window.sessionStorage.VUE_NAVIGATION=JSON.stringify(u),e.$emit("forward",i,s)},a=function(o,r,a){var i={route:r},s={route:a},u=t?t.state[n].routes:Routes;s.name=u[u.length-1],i.name=u[u.length-1-o],t?t.commit("navigation/BACK",{to:i,from:s,count:o}):u.splice(Routes.length-o,o),window.sessionStorage.VUE_NAVIGATION=JSON.stringify(u),e.$emit("back",i,s)},i=function(o,r,a){var i={route:r},s={route:a},u=t?t.state[n].routes:Routes;s.name=u[u.length-1]||null,i.name=o,t?t.commit("navigation/REPLACE",{to:i,from:s,name:o}):u.splice(Routes.length-1,1,o),window.sessionStorage.VUE_NAVIGATION=JSON.stringify(u),e.$emit("replace",i,s)},s=function(o,r){var a={route:o},i={route:r},s=t?t.state[n].routes:Routes;a.name=i.name=s[s.length-1],t&&t.commit("navigation/REFRESH",{to:a,from:i}),e.$emit("refresh",a,i)};return{record:function(e,t,n){var u=getKey(e,o);if(n)i(u,e,t);else{var c=Routes.lastIndexOf(u);-1===c?r(u,e,t):c===Routes.length-1?s(e,t):a(Routes.length-1-c,e,t)}},reset:function(){t?t.commit("navigation/RESET"):Routes.splice(0,Routes.length),window.sessionStorage.VUE_NAVIGATION=JSON.stringify([]),e.$emit("reset")}}},NavComponent=function(e){return{name:"navigation",abstract:!0,props:{},data:function(){return{routes:Routes}},computed:{},watch:{routes:function(e){for(var t in this.cache)if(!matches(e,t)){var n=this.cache[t];n&&n.componentInstance.$destroy(),delete this.cache[t]}}},created:function(){this.cache={}},destroyed:function(){for(var e in this.cache){var t=this.cache[e];t&&t.componentInstance.$destroy()}},render:function(){var t=this.$slots.default?this.$slots.default[0]:null;if(t){t.key=t.key||(t.isComment?"comment":t.tag);var n=getKey(this.$route,e);-1===t.key.indexOf(n)&&(t.key="__navigation-"+n+"-"+t.key),this.cache[n]?t.key===this.cache[n].key?t.componentInstance=this.cache[n].componentInstance:(this.cache[n].componentInstance.$destroy(),this.cache[n]=t):this.cache[n]=t,t.data.keepAlive=!0}return t}}},_extends=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{},n=t.router,o=t.store,r=t.moduleName,a=void 0===r?"navigation":r,i=t.keyName,s=void 0===i?"VNK":i;if(n){var u=new e,c=Navigator(u,o,a,s),f=n.replace.bind(n),l=!1;n.replace=function(e,t,n){l=!0,f(e,t,n)},n.beforeEach(function(e,t,n){if(e.query[s])n();else{var o=_extends({},e.query);e.path===t.path&&isObjEqual(_extends({},e.query,_defineProperty({},s,null)),_extends({},t.query,_defineProperty({},s,null)))&&t.query[s]?o[s]=t.query[s]:o[s]=genKey(),n({name:e.name,params:e.params,query:o,replace:l||!t.query[s]})}}),n.afterEach(function(e,t){c.record(e,t,l),l=!1}),e.component("navigation",NavComponent(s)),e.navigation=e.prototype.$navigation={on:function(e,t){u.$on(e,t)},once:function(e,t){u.$once(e,t)},off:function(e,t){u.$off(e,t)},getRoutes:function(){return Routes.slice()},cleanRoutes:function(){return c.reset()}}}else console.error("vue-navigation need options: router")}};export default index; -------------------------------------------------------------------------------- /dist/vue-navigation.esm.js: -------------------------------------------------------------------------------- 1 | /** 2 | * vue-navigation v1.1.4 3 | * https://github.com/zack24q/vue-navigation 4 | * Released under the MIT License. 5 | */ 6 | 7 | var routes = []; 8 | 9 | if (window.sessionStorage.VUE_NAVIGATION) { 10 | routes = JSON.parse(window.sessionStorage.VUE_NAVIGATION); 11 | } 12 | 13 | var Routes = routes; 14 | 15 | function genKey() { 16 | var t = 'xxxxxxxx'; 17 | return t.replace(/[xy]/g, function (c) { 18 | var r = Math.random() * 16 | 0; 19 | var v = c === 'x' ? r : r & 0x3 | 0x8; 20 | return v.toString(16); 21 | }); 22 | } 23 | 24 | function getKey(route, keyName) { 25 | return (route.name || route.path) + '?' + route.query[keyName]; 26 | } 27 | 28 | function matches(pattern, name) { 29 | if (Array.isArray(pattern)) { 30 | return pattern.indexOf(name) > -1; 31 | } else if (typeof pattern === 'string') { 32 | return pattern.split(',').indexOf(name) > -1; 33 | } else if (isRegExp(pattern)) { 34 | return pattern.test(name); 35 | } 36 | return false; 37 | } 38 | 39 | function isObjEqual(obj1, obj2) { 40 | if (obj1 === obj2) { 41 | return true; 42 | } else { 43 | var keys1 = Object.getOwnPropertyNames(obj1); 44 | var keys2 = Object.getOwnPropertyNames(obj2); 45 | if (keys1.length !== keys2.length) { 46 | return false; 47 | } 48 | var _iteratorNormalCompletion = true; 49 | var _didIteratorError = false; 50 | var _iteratorError = undefined; 51 | 52 | try { 53 | for (var _iterator = keys1[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 54 | var key = _step.value; 55 | 56 | if (obj1[key] !== obj2[key]) { 57 | return false; 58 | } 59 | } 60 | } catch (err) { 61 | _didIteratorError = true; 62 | _iteratorError = err; 63 | } finally { 64 | try { 65 | if (!_iteratorNormalCompletion && _iterator.return) { 66 | _iterator.return(); 67 | } 68 | } finally { 69 | if (_didIteratorError) { 70 | throw _iteratorError; 71 | } 72 | } 73 | } 74 | 75 | return true; 76 | } 77 | } 78 | 79 | var Navigator = (function (bus, store, moduleName, keyName) { 80 | if (store) { 81 | store.registerModule(moduleName, { 82 | state: { 83 | routes: Routes 84 | }, 85 | mutations: { 86 | 'navigation/FORWARD': function navigationFORWARD(state, _ref) { 87 | var to = _ref.to, 88 | from = _ref.from, 89 | name = _ref.name; 90 | 91 | state.routes.push(name); 92 | }, 93 | 'navigation/BACK': function navigationBACK(state, _ref2) { 94 | var to = _ref2.to, 95 | from = _ref2.from, 96 | count = _ref2.count; 97 | 98 | state.routes.splice(state.routes.length - count, count); 99 | }, 100 | 'navigation/REPLACE': function navigationREPLACE(state, _ref3) { 101 | var to = _ref3.to, 102 | from = _ref3.from, 103 | name = _ref3.name; 104 | 105 | state.routes.splice(Routes.length - 1, 1, name); 106 | }, 107 | 'navigation/REFRESH': function navigationREFRESH(state, _ref4) { 108 | var to = _ref4.to, 109 | from = _ref4.from; 110 | }, 111 | 'navigation/RESET': function navigationRESET(state) { 112 | state.routes.splice(0, state.routes.length); 113 | } 114 | } 115 | }); 116 | } 117 | 118 | var forward = function forward(name, toRoute, fromRoute) { 119 | var to = { route: toRoute }; 120 | var from = { route: fromRoute }; 121 | var routes = store ? store.state[moduleName].routes : Routes; 122 | 123 | from.name = routes[routes.length - 1] || null; 124 | to.name = name; 125 | store ? store.commit('navigation/FORWARD', { to: to, from: from, name: name }) : routes.push(name); 126 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify(routes); 127 | bus.$emit('forward', to, from); 128 | }; 129 | var back = function back(count, toRoute, fromRoute) { 130 | var to = { route: toRoute }; 131 | var from = { route: fromRoute }; 132 | var routes = store ? store.state[moduleName].routes : Routes; 133 | from.name = routes[routes.length - 1]; 134 | to.name = routes[routes.length - 1 - count]; 135 | store ? store.commit('navigation/BACK', { to: to, from: from, count: count }) : routes.splice(Routes.length - count, count); 136 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify(routes); 137 | bus.$emit('back', to, from); 138 | }; 139 | var replace = function replace(name, toRoute, fromRoute) { 140 | var to = { route: toRoute }; 141 | var from = { route: fromRoute }; 142 | var routes = store ? store.state[moduleName].routes : Routes; 143 | 144 | from.name = routes[routes.length - 1] || null; 145 | to.name = name; 146 | store ? store.commit('navigation/REPLACE', { to: to, from: from, name: name }) : routes.splice(Routes.length - 1, 1, name); 147 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify(routes); 148 | bus.$emit('replace', to, from); 149 | }; 150 | var refresh = function refresh(toRoute, fromRoute) { 151 | var to = { route: toRoute }; 152 | var from = { route: fromRoute }; 153 | var routes = store ? store.state[moduleName].routes : Routes; 154 | to.name = from.name = routes[routes.length - 1]; 155 | store ? store.commit('navigation/REFRESH', { to: to, from: from }) : null; 156 | bus.$emit('refresh', to, from); 157 | }; 158 | var reset = function reset() { 159 | store ? store.commit('navigation/RESET') : Routes.splice(0, Routes.length); 160 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify([]); 161 | bus.$emit('reset'); 162 | }; 163 | 164 | var record = function record(toRoute, fromRoute, replaceFlag) { 165 | var name = getKey(toRoute, keyName); 166 | if (replaceFlag) { 167 | replace(name, toRoute, fromRoute); 168 | } else { 169 | var toIndex = Routes.lastIndexOf(name); 170 | if (toIndex === -1) { 171 | forward(name, toRoute, fromRoute); 172 | } else if (toIndex === Routes.length - 1) { 173 | refresh(toRoute, fromRoute); 174 | } else { 175 | back(Routes.length - 1 - toIndex, toRoute, fromRoute); 176 | } 177 | } 178 | }; 179 | 180 | return { 181 | record: record, reset: reset 182 | }; 183 | }); 184 | 185 | var NavComponent = (function (keyName) { 186 | return { 187 | name: 'navigation', 188 | abstract: true, 189 | props: {}, 190 | data: function data() { 191 | return { 192 | routes: Routes 193 | }; 194 | }, 195 | computed: {}, 196 | watch: { 197 | routes: function routes(val) { 198 | for (var key in this.cache) { 199 | if (!matches(val, key)) { 200 | var vnode = this.cache[key]; 201 | vnode && vnode.componentInstance.$destroy(); 202 | delete this.cache[key]; 203 | } 204 | } 205 | } 206 | }, 207 | created: function created() { 208 | this.cache = {}; 209 | }, 210 | destroyed: function destroyed() { 211 | for (var key in this.cache) { 212 | var vnode = this.cache[key]; 213 | vnode && vnode.componentInstance.$destroy(); 214 | } 215 | }, 216 | render: function render() { 217 | var vnode = this.$slots.default ? this.$slots.default[0] : null; 218 | if (vnode) { 219 | vnode.key = vnode.key || (vnode.isComment ? 'comment' : vnode.tag); 220 | 221 | var key = getKey(this.$route, keyName); 222 | if (vnode.key.indexOf(key) === -1) { 223 | vnode.key = '__navigation-' + key + '-' + vnode.key; 224 | } 225 | if (this.cache[key]) { 226 | if (vnode.key === this.cache[key].key) { 227 | vnode.componentInstance = this.cache[key].componentInstance; 228 | } else { 229 | this.cache[key].componentInstance.$destroy(); 230 | this.cache[key] = vnode; 231 | } 232 | } else { 233 | this.cache[key] = vnode; 234 | } 235 | vnode.data.keepAlive = true; 236 | } 237 | return vnode; 238 | } 239 | }; 240 | }); 241 | 242 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 243 | 244 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 245 | 246 | var index = { 247 | install: function install(Vue) { 248 | var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, 249 | router = _ref.router, 250 | store = _ref.store, 251 | _ref$moduleName = _ref.moduleName, 252 | moduleName = _ref$moduleName === undefined ? 'navigation' : _ref$moduleName, 253 | _ref$keyName = _ref.keyName, 254 | keyName = _ref$keyName === undefined ? 'VNK' : _ref$keyName; 255 | 256 | if (!router) { 257 | console.error('vue-navigation need options: router'); 258 | return; 259 | } 260 | 261 | var bus = new Vue(); 262 | var navigator = Navigator(bus, store, moduleName, keyName); 263 | 264 | var routerReplace = router.replace.bind(router); 265 | var replaceFlag = false; 266 | router.replace = function (location, onComplete, onAbort) { 267 | replaceFlag = true; 268 | routerReplace(location, onComplete, onAbort); 269 | }; 270 | 271 | router.beforeEach(function (to, from, next) { 272 | if (!to.query[keyName]) { 273 | var query = _extends({}, to.query); 274 | 275 | if (to.path === from.path && isObjEqual(_extends({}, to.query, _defineProperty({}, keyName, null)), _extends({}, from.query, _defineProperty({}, keyName, null))) && from.query[keyName]) { 276 | query[keyName] = from.query[keyName]; 277 | } else { 278 | query[keyName] = genKey(); 279 | } 280 | next({ name: to.name, params: to.params, query: query, replace: replaceFlag || !from.query[keyName] }); 281 | } else { 282 | next(); 283 | } 284 | }); 285 | 286 | router.afterEach(function (to, from) { 287 | navigator.record(to, from, replaceFlag); 288 | replaceFlag = false; 289 | }); 290 | 291 | Vue.component('navigation', NavComponent(keyName)); 292 | 293 | Vue.navigation = Vue.prototype.$navigation = { 294 | on: function on(event, callback) { 295 | bus.$on(event, callback); 296 | }, 297 | once: function once(event, callback) { 298 | bus.$once(event, callback); 299 | }, 300 | off: function off(event, callback) { 301 | bus.$off(event, callback); 302 | }, 303 | getRoutes: function getRoutes() { 304 | return Routes.slice(); 305 | }, 306 | cleanRoutes: function cleanRoutes() { 307 | return navigator.reset(); 308 | } 309 | }; 310 | } 311 | }; 312 | 313 | export default index; 314 | -------------------------------------------------------------------------------- /dist/vue-navigation.umd.js: -------------------------------------------------------------------------------- 1 | /** 2 | * vue-navigation v1.1.4 3 | * https://github.com/zack24q/vue-navigation 4 | * Released under the MIT License. 5 | */ 6 | 7 | (function (global, factory) { 8 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 9 | typeof define === 'function' && define.amd ? define(factory) : 10 | (global.VueNavigation = factory()); 11 | }(this, (function () { 'use strict'; 12 | 13 | var routes = []; 14 | 15 | if (window.sessionStorage.VUE_NAVIGATION) { 16 | routes = JSON.parse(window.sessionStorage.VUE_NAVIGATION); 17 | } 18 | 19 | var Routes = routes; 20 | 21 | function genKey() { 22 | var t = 'xxxxxxxx'; 23 | return t.replace(/[xy]/g, function (c) { 24 | var r = Math.random() * 16 | 0; 25 | var v = c === 'x' ? r : r & 0x3 | 0x8; 26 | return v.toString(16); 27 | }); 28 | } 29 | 30 | function getKey(route, keyName) { 31 | return (route.name || route.path) + '?' + route.query[keyName]; 32 | } 33 | 34 | function matches(pattern, name) { 35 | if (Array.isArray(pattern)) { 36 | return pattern.indexOf(name) > -1; 37 | } else if (typeof pattern === 'string') { 38 | return pattern.split(',').indexOf(name) > -1; 39 | } else if (isRegExp(pattern)) { 40 | return pattern.test(name); 41 | } 42 | return false; 43 | } 44 | 45 | function isObjEqual(obj1, obj2) { 46 | if (obj1 === obj2) { 47 | return true; 48 | } else { 49 | var keys1 = Object.getOwnPropertyNames(obj1); 50 | var keys2 = Object.getOwnPropertyNames(obj2); 51 | if (keys1.length !== keys2.length) { 52 | return false; 53 | } 54 | var _iteratorNormalCompletion = true; 55 | var _didIteratorError = false; 56 | var _iteratorError = undefined; 57 | 58 | try { 59 | for (var _iterator = keys1[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 60 | var key = _step.value; 61 | 62 | if (obj1[key] !== obj2[key]) { 63 | return false; 64 | } 65 | } 66 | } catch (err) { 67 | _didIteratorError = true; 68 | _iteratorError = err; 69 | } finally { 70 | try { 71 | if (!_iteratorNormalCompletion && _iterator.return) { 72 | _iterator.return(); 73 | } 74 | } finally { 75 | if (_didIteratorError) { 76 | throw _iteratorError; 77 | } 78 | } 79 | } 80 | 81 | return true; 82 | } 83 | } 84 | 85 | var Navigator = (function (bus, store, moduleName, keyName) { 86 | if (store) { 87 | store.registerModule(moduleName, { 88 | state: { 89 | routes: Routes 90 | }, 91 | mutations: { 92 | 'navigation/FORWARD': function navigationFORWARD(state, _ref) { 93 | var to = _ref.to, 94 | from = _ref.from, 95 | name = _ref.name; 96 | 97 | state.routes.push(name); 98 | }, 99 | 'navigation/BACK': function navigationBACK(state, _ref2) { 100 | var to = _ref2.to, 101 | from = _ref2.from, 102 | count = _ref2.count; 103 | 104 | state.routes.splice(state.routes.length - count, count); 105 | }, 106 | 'navigation/REPLACE': function navigationREPLACE(state, _ref3) { 107 | var to = _ref3.to, 108 | from = _ref3.from, 109 | name = _ref3.name; 110 | 111 | state.routes.splice(Routes.length - 1, 1, name); 112 | }, 113 | 'navigation/REFRESH': function navigationREFRESH(state, _ref4) { 114 | var to = _ref4.to, 115 | from = _ref4.from; 116 | }, 117 | 'navigation/RESET': function navigationRESET(state) { 118 | state.routes.splice(0, state.routes.length); 119 | } 120 | } 121 | }); 122 | } 123 | 124 | var forward = function forward(name, toRoute, fromRoute) { 125 | var to = { route: toRoute }; 126 | var from = { route: fromRoute }; 127 | var routes = store ? store.state[moduleName].routes : Routes; 128 | 129 | from.name = routes[routes.length - 1] || null; 130 | to.name = name; 131 | store ? store.commit('navigation/FORWARD', { to: to, from: from, name: name }) : routes.push(name); 132 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify(routes); 133 | bus.$emit('forward', to, from); 134 | }; 135 | var back = function back(count, toRoute, fromRoute) { 136 | var to = { route: toRoute }; 137 | var from = { route: fromRoute }; 138 | var routes = store ? store.state[moduleName].routes : Routes; 139 | from.name = routes[routes.length - 1]; 140 | to.name = routes[routes.length - 1 - count]; 141 | store ? store.commit('navigation/BACK', { to: to, from: from, count: count }) : routes.splice(Routes.length - count, count); 142 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify(routes); 143 | bus.$emit('back', to, from); 144 | }; 145 | var replace = function replace(name, toRoute, fromRoute) { 146 | var to = { route: toRoute }; 147 | var from = { route: fromRoute }; 148 | var routes = store ? store.state[moduleName].routes : Routes; 149 | 150 | from.name = routes[routes.length - 1] || null; 151 | to.name = name; 152 | store ? store.commit('navigation/REPLACE', { to: to, from: from, name: name }) : routes.splice(Routes.length - 1, 1, name); 153 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify(routes); 154 | bus.$emit('replace', to, from); 155 | }; 156 | var refresh = function refresh(toRoute, fromRoute) { 157 | var to = { route: toRoute }; 158 | var from = { route: fromRoute }; 159 | var routes = store ? store.state[moduleName].routes : Routes; 160 | to.name = from.name = routes[routes.length - 1]; 161 | store ? store.commit('navigation/REFRESH', { to: to, from: from }) : null; 162 | bus.$emit('refresh', to, from); 163 | }; 164 | var reset = function reset() { 165 | store ? store.commit('navigation/RESET') : Routes.splice(0, Routes.length); 166 | window.sessionStorage.VUE_NAVIGATION = JSON.stringify([]); 167 | bus.$emit('reset'); 168 | }; 169 | 170 | var record = function record(toRoute, fromRoute, replaceFlag) { 171 | var name = getKey(toRoute, keyName); 172 | if (replaceFlag) { 173 | replace(name, toRoute, fromRoute); 174 | } else { 175 | var toIndex = Routes.lastIndexOf(name); 176 | if (toIndex === -1) { 177 | forward(name, toRoute, fromRoute); 178 | } else if (toIndex === Routes.length - 1) { 179 | refresh(toRoute, fromRoute); 180 | } else { 181 | back(Routes.length - 1 - toIndex, toRoute, fromRoute); 182 | } 183 | } 184 | }; 185 | 186 | return { 187 | record: record, reset: reset 188 | }; 189 | }); 190 | 191 | var NavComponent = (function (keyName) { 192 | return { 193 | name: 'navigation', 194 | abstract: true, 195 | props: {}, 196 | data: function data() { 197 | return { 198 | routes: Routes 199 | }; 200 | }, 201 | computed: {}, 202 | watch: { 203 | routes: function routes(val) { 204 | for (var key in this.cache) { 205 | if (!matches(val, key)) { 206 | var vnode = this.cache[key]; 207 | vnode && vnode.componentInstance.$destroy(); 208 | delete this.cache[key]; 209 | } 210 | } 211 | } 212 | }, 213 | created: function created() { 214 | this.cache = {}; 215 | }, 216 | destroyed: function destroyed() { 217 | for (var key in this.cache) { 218 | var vnode = this.cache[key]; 219 | vnode && vnode.componentInstance.$destroy(); 220 | } 221 | }, 222 | render: function render() { 223 | var vnode = this.$slots.default ? this.$slots.default[0] : null; 224 | if (vnode) { 225 | vnode.key = vnode.key || (vnode.isComment ? 'comment' : vnode.tag); 226 | 227 | var key = getKey(this.$route, keyName); 228 | if (vnode.key.indexOf(key) === -1) { 229 | vnode.key = '__navigation-' + key + '-' + vnode.key; 230 | } 231 | if (this.cache[key]) { 232 | if (vnode.key === this.cache[key].key) { 233 | vnode.componentInstance = this.cache[key].componentInstance; 234 | } else { 235 | this.cache[key].componentInstance.$destroy(); 236 | this.cache[key] = vnode; 237 | } 238 | } else { 239 | this.cache[key] = vnode; 240 | } 241 | vnode.data.keepAlive = true; 242 | } 243 | return vnode; 244 | } 245 | }; 246 | }); 247 | 248 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 249 | 250 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 251 | 252 | var index = { 253 | install: function install(Vue) { 254 | var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, 255 | router = _ref.router, 256 | store = _ref.store, 257 | _ref$moduleName = _ref.moduleName, 258 | moduleName = _ref$moduleName === undefined ? 'navigation' : _ref$moduleName, 259 | _ref$keyName = _ref.keyName, 260 | keyName = _ref$keyName === undefined ? 'VNK' : _ref$keyName; 261 | 262 | if (!router) { 263 | console.error('vue-navigation need options: router'); 264 | return; 265 | } 266 | 267 | var bus = new Vue(); 268 | var navigator = Navigator(bus, store, moduleName, keyName); 269 | 270 | var routerReplace = router.replace.bind(router); 271 | var replaceFlag = false; 272 | router.replace = function (location, onComplete, onAbort) { 273 | replaceFlag = true; 274 | routerReplace(location, onComplete, onAbort); 275 | }; 276 | 277 | router.beforeEach(function (to, from, next) { 278 | if (!to.query[keyName]) { 279 | var query = _extends({}, to.query); 280 | 281 | if (to.path === from.path && isObjEqual(_extends({}, to.query, _defineProperty({}, keyName, null)), _extends({}, from.query, _defineProperty({}, keyName, null))) && from.query[keyName]) { 282 | query[keyName] = from.query[keyName]; 283 | } else { 284 | query[keyName] = genKey(); 285 | } 286 | next({ name: to.name, params: to.params, query: query, replace: replaceFlag || !from.query[keyName] }); 287 | } else { 288 | next(); 289 | } 290 | }); 291 | 292 | router.afterEach(function (to, from) { 293 | navigator.record(to, from, replaceFlag); 294 | replaceFlag = false; 295 | }); 296 | 297 | Vue.component('navigation', NavComponent(keyName)); 298 | 299 | Vue.navigation = Vue.prototype.$navigation = { 300 | on: function on(event, callback) { 301 | bus.$on(event, callback); 302 | }, 303 | once: function once(event, callback) { 304 | bus.$once(event, callback); 305 | }, 306 | off: function off(event, callback) { 307 | bus.$off(event, callback); 308 | }, 309 | getRoutes: function getRoutes() { 310 | return Routes.slice(); 311 | }, 312 | cleanRoutes: function cleanRoutes() { 313 | return navigator.reset(); 314 | } 315 | }; 316 | } 317 | }; 318 | 319 | return index; 320 | 321 | }))); 322 | -------------------------------------------------------------------------------- /docs/examples/static/js/manifest.77ca56a9f5bab52a513c.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///static/js/manifest.77ca56a9f5bab52a513c.js","webpack:///webpack/bootstrap c78ede3379eba0122ebb"],"names":["modules","__webpack_require__","moduleId","installedModules","exports","module","i","l","call","parentJsonpFunction","window","chunkIds","moreModules","executeModules","chunkId","result","resolves","length","installedChunks","push","Object","prototype","hasOwnProperty","shift","s","4","e","onScriptComplete","script","onerror","onload","clearTimeout","timeout","chunk","Error","undefined","installedChunkData","Promise","resolve","promise","reject","head","document","getElementsByTagName","createElement","type","charset","async","nc","setAttribute","src","p","0","1","2","3","setTimeout","appendChild","m","c","value","d","name","getter","o","defineProperty","configurable","enumerable","get","n","__esModule","object","property","oe","err","console","error"],"mappings":"CAAS,SAAUA,GCuCnB,QAAAC,GAAAC,GAGA,GAAAC,EAAAD,GACA,MAAAC,GAAAD,GAAAE,OAGA,IAAAC,GAAAF,EAAAD,IACAI,EAAAJ,EACAK,GAAA,EACAH,WAUA,OANAJ,GAAAE,GAAAM,KAAAH,EAAAD,QAAAC,IAAAD,QAAAH,GAGAI,EAAAE,GAAA,EAGAF,EAAAD,QA1DA,GAAAK,GAAAC,OAAA,YACAA,QAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,GAAAX,GAAAY,EAAAC,EAAAT,EAAA,EAAAU,KACQV,EAAAK,EAAAM,OAAoBX,IAC5BQ,EAAAH,EAAAL,GACAY,EAAAJ,IACAE,EAAAG,KAAAD,EAAAJ,GAAA,IAEAI,EAAAJ,GAAA,CAEA,KAAAZ,IAAAU,GACAQ,OAAAC,UAAAC,eAAAd,KAAAI,EAAAV,KACAF,EAAAE,GAAAU,EAAAV,GAIA,KADAO,KAAAE,EAAAC,EAAAC,GACAG,EAAAC,QACAD,EAAAO,SAEA,IAAAV,EACA,IAAAP,EAAA,EAAYA,EAAAO,EAAAI,OAA2BX,IACvCS,EAAAd,IAAAuB,EAAAX,EAAAP,GAGA,OAAAS,GAIA,IAAAZ,MAGAe,GACAO,EAAA,EA6BAxB,GAAAyB,EAAA,SAAAZ,GA+BA,QAAAa,KAEAC,EAAAC,QAAAD,EAAAE,OAAA,KACAC,aAAAC,EACA,IAAAC,GAAAf,EAAAJ,EACA,KAAAmB,IACAA,GACAA,EAAA,MAAAC,OAAA,iBAAApB,EAAA,aAEAI,EAAAJ,OAAAqB,IAvCA,GAAAC,GAAAlB,EAAAJ,EACA,QAAAsB,EACA,UAAAC,SAAA,SAAAC,GAA0CA,KAI1C,IAAAF,EACA,MAAAA,GAAA,EAIA,IAAAG,GAAA,GAAAF,SAAA,SAAAC,EAAAE,GACAJ,EAAAlB,EAAAJ,IAAAwB,EAAAE,IAEAJ,GAAA,GAAAG,CAGA,IAAAE,GAAAC,SAAAC,qBAAA,WACAf,EAAAc,SAAAE,cAAA,SACAhB,GAAAiB,KAAA,kBACAjB,EAAAkB,QAAA,QACAlB,EAAAmB,OAAA,EACAnB,EAAAI,QAAA,KAEA/B,EAAA+C,IACApB,EAAAqB,aAAA,QAAAhD,EAAA+C,IAEApB,EAAAsB,IAAAjD,EAAAkD,EAAA,aAAArC,EAAA,KAAwEsC,EAAA,uBAAAC,EAAA,uBAAAC,EAAA,uBAAAC,EAAA,wBAA4GzC,GAAA,KACpL,IAAAkB,GAAAwB,WAAA7B,EAAA,KAgBA,OAfAC,GAAAC,QAAAD,EAAAE,OAAAH,EAaAc,EAAAgB,YAAA7B,GAEAW,GAIAtC,EAAAyD,EAAA1D,EAGAC,EAAA0D,EAAAxD,EAGAF,EAAAK,EAAA,SAAAsD,GAA2C,MAAAA,IAG3C3D,EAAA4D,EAAA,SAAAzD,EAAA0D,EAAAC,GACA9D,EAAA+D,EAAA5D,EAAA0D,IACA1C,OAAA6C,eAAA7D,EAAA0D,GACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMA9D,EAAAoE,EAAA,SAAAhE,GACA,GAAA0D,GAAA1D,KAAAiE,WACA,WAA2B,MAAAjE,GAAA,SAC3B,WAAiC,MAAAA,GAEjC,OADAJ,GAAA4D,EAAAE,EAAA,IAAAA,GACAA,GAIA9D,EAAA+D,EAAA,SAAAO,EAAAC,GAAsD,MAAApD,QAAAC,UAAAC,eAAAd,KAAA+D,EAAAC,IAGtDvE,EAAAkD,EAAA,KAGAlD,EAAAwE,GAAA,SAAAC,GAA8D,KAApBC,SAAAC,MAAAF,GAAoBA","file":"static/js/manifest.77ca56a9f5bab52a513c.js","sourcesContent":["/******/ (function(modules) { // webpackBootstrap\n/******/ \t// install a JSONP callback for chunk loading\n/******/ \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n/******/ \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n/******/ \t\t// add \"moreModules\" to the modules object,\n/******/ \t\t// then flag all \"chunkIds\" as loaded and fire callback\n/******/ \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n/******/ \t\tfor(;i < chunkIds.length; i++) {\n/******/ \t\t\tchunkId = chunkIds[i];\n/******/ \t\t\tif(installedChunks[chunkId]) {\n/******/ \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n/******/ \t\t\t}\n/******/ \t\t\tinstalledChunks[chunkId] = 0;\n/******/ \t\t}\n/******/ \t\tfor(moduleId in moreModules) {\n/******/ \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n/******/ \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n/******/ \t\t\t}\n/******/ \t\t}\n/******/ \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n/******/ \t\twhile(resolves.length) {\n/******/ \t\t\tresolves.shift()();\n/******/ \t\t}\n/******/ \t\tif(executeModules) {\n/******/ \t\t\tfor(i=0; i < executeModules.length; i++) {\n/******/ \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n/******/ \t\t\t}\n/******/ \t\t}\n/******/ \t\treturn result;\n/******/ \t};\n/******/\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// objects to store loaded and loading chunks\n/******/ \tvar installedChunks = {\n/******/ \t\t4: 0\n/******/ \t};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/ \t// This file contains only the entry chunk.\n/******/ \t// The chunk loading function for additional chunks\n/******/ \t__webpack_require__.e = function requireEnsure(chunkId) {\n/******/ \t\tvar installedChunkData = installedChunks[chunkId];\n/******/ \t\tif(installedChunkData === 0) {\n/******/ \t\t\treturn new Promise(function(resolve) { resolve(); });\n/******/ \t\t}\n/******/\n/******/ \t\t// a Promise means \"currently loading\".\n/******/ \t\tif(installedChunkData) {\n/******/ \t\t\treturn installedChunkData[2];\n/******/ \t\t}\n/******/\n/******/ \t\t// setup Promise in chunk cache\n/******/ \t\tvar promise = new Promise(function(resolve, reject) {\n/******/ \t\t\tinstalledChunkData = installedChunks[chunkId] = [resolve, reject];\n/******/ \t\t});\n/******/ \t\tinstalledChunkData[2] = promise;\n/******/\n/******/ \t\t// start chunk loading\n/******/ \t\tvar head = document.getElementsByTagName('head')[0];\n/******/ \t\tvar script = document.createElement('script');\n/******/ \t\tscript.type = 'text/javascript';\n/******/ \t\tscript.charset = 'utf-8';\n/******/ \t\tscript.async = true;\n/******/ \t\tscript.timeout = 120000;\n/******/\n/******/ \t\tif (__webpack_require__.nc) {\n/******/ \t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n/******/ \t\t}\n/******/ \t\tscript.src = __webpack_require__.p + \"static/js/\" + chunkId + \".\" + {\"0\":\"b50a17303326a3e6c4a0\",\"1\":\"a102ff9ff816ef7fcf2b\",\"2\":\"c662248ac7d4c3397a0f\",\"3\":\"117caf5e040c3792f2e6\"}[chunkId] + \".js\";\n/******/ \t\tvar timeout = setTimeout(onScriptComplete, 120000);\n/******/ \t\tscript.onerror = script.onload = onScriptComplete;\n/******/ \t\tfunction onScriptComplete() {\n/******/ \t\t\t// avoid mem leaks in IE.\n/******/ \t\t\tscript.onerror = script.onload = null;\n/******/ \t\t\tclearTimeout(timeout);\n/******/ \t\t\tvar chunk = installedChunks[chunkId];\n/******/ \t\t\tif(chunk !== 0) {\n/******/ \t\t\t\tif(chunk) {\n/******/ \t\t\t\t\tchunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));\n/******/ \t\t\t\t}\n/******/ \t\t\t\tinstalledChunks[chunkId] = undefined;\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t\thead.appendChild(script);\n/******/\n/******/ \t\treturn promise;\n/******/ \t};\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// identity function for calling harmony imports with the correct context\n/******/ \t__webpack_require__.i = function(value) { return value; };\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"./\";\n/******/\n/******/ \t// on error function for async loading\n/******/ \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n/******/ })\n/************************************************************************/\n/******/ ([]);\n\n\n// WEBPACK FOOTER //\n// static/js/manifest.77ca56a9f5bab52a513c.js"," \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t4: 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId) {\n \t\tvar installedChunkData = installedChunks[chunkId];\n \t\tif(installedChunkData === 0) {\n \t\t\treturn new Promise(function(resolve) { resolve(); });\n \t\t}\n\n \t\t// a Promise means \"currently loading\".\n \t\tif(installedChunkData) {\n \t\t\treturn installedChunkData[2];\n \t\t}\n\n \t\t// setup Promise in chunk cache\n \t\tvar promise = new Promise(function(resolve, reject) {\n \t\t\tinstalledChunkData = installedChunks[chunkId] = [resolve, reject];\n \t\t});\n \t\tinstalledChunkData[2] = promise;\n\n \t\t// start chunk loading\n \t\tvar head = document.getElementsByTagName('head')[0];\n \t\tvar script = document.createElement('script');\n \t\tscript.type = 'text/javascript';\n \t\tscript.charset = 'utf-8';\n \t\tscript.async = true;\n \t\tscript.timeout = 120000;\n\n \t\tif (__webpack_require__.nc) {\n \t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n \t\t}\n \t\tscript.src = __webpack_require__.p + \"static/js/\" + chunkId + \".\" + {\"0\":\"b50a17303326a3e6c4a0\",\"1\":\"a102ff9ff816ef7fcf2b\",\"2\":\"c662248ac7d4c3397a0f\",\"3\":\"117caf5e040c3792f2e6\"}[chunkId] + \".js\";\n \t\tvar timeout = setTimeout(onScriptComplete, 120000);\n \t\tscript.onerror = script.onload = onScriptComplete;\n \t\tfunction onScriptComplete() {\n \t\t\t// avoid mem leaks in IE.\n \t\t\tscript.onerror = script.onload = null;\n \t\t\tclearTimeout(timeout);\n \t\t\tvar chunk = installedChunks[chunkId];\n \t\t\tif(chunk !== 0) {\n \t\t\t\tif(chunk) {\n \t\t\t\t\tchunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));\n \t\t\t\t}\n \t\t\t\tinstalledChunks[chunkId] = undefined;\n \t\t\t}\n \t\t};\n \t\thead.appendChild(script);\n\n \t\treturn promise;\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"./\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap c78ede3379eba0122ebb"],"sourceRoot":""} -------------------------------------------------------------------------------- /docs/examples/static/js/0.b50a17303326a3e6c4a0.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///static/js/0.b50a17303326a3e6c4a0.js","webpack:///./src/pages/List.vue","webpack:///Page.vue","webpack:///./src/components/Page.vue?676e","webpack:///./src/components/Page.vue?b847","webpack:///./src/components/Page.vue?94e6","webpack:///./src/components/Page.vue?2230","webpack:///List.vue","webpack:///./src/pages/List.vue?5cdc"],"names":["webpackJsonp","18","module","exports","__webpack_require__","Component","19","__webpack_exports__","Object","defineProperty","value","name","data","scrollTop","methods","back","window","history","scroll","this","$refs","content","activated","20","push","i","version","sources","names","mappings","file","sourcesContent","sourceRoot","21","locals","22","23","render","_vm","_h","$createElement","_c","_self","staticClass","on","click","_v","ref","_t","staticRenderFns","26","__WEBPACK_IMPORTED_MODULE_0__components_Page_vue__","__WEBPACK_IMPORTED_MODULE_0__components_Page_vue___default","n","components","Page","a","random","Math","toFixed","console","log","deactivated","destroyed","27","_s","_l","key","attrs","to"],"mappings":"AAAAA,cAAc,IAERC,GACA,SAAUC,EAAQC,EAASC,GCHjC,GAAAC,GAAAD,EAAA,GAEAA,EAAA,IAEAA,EAAA,IAEA,KAEA,KAGAF,GAAAC,QAAAE,EAAAF,SDUMG,GACA,SAAUJ,EAAQK,EAAqBH,GAE7C,YACAI,QAAOC,eAAeF,EAAqB,cAAgBG,OAAO,IEXlEH,EAAA,SFeEI,KEbF,OFcEC,KAAM,WACJ,OACEC,UEZN,IFgBEC,SACEC,KAAM,WACJC,OAAOC,QEdbF,QFgBIG,OAAQ,WACNC,KAAKN,UAAYM,KAAKC,MAAMC,QEdlCR,YFiBES,UAAW,WACTH,KAAKC,MAAMC,QAAQR,UAAYM,KEdnCN,aFoBMU,GACA,SAAUrB,EAAQC,EAASC,GGpDjCD,EAAAD,EAAAC,QAAAC,EAAA,MAKAD,EAAAqB,MAAAtB,EAAAuB,EAAA,0bAAid,IAAQC,QAAA,EAAAC,SAAA,kFAAAC,SAAAC,SAAA,iWAAAC,KAAA,WAAAC,gBAAA,8mBAA6mCC,WAAA,OH6DhkDC,GACA,SAAU/B,EAAQC,EAASC,GIhEjC,GAAAiB,GAAAjB,EAAA,GACA,iBAAAiB,SAAAnB,EAAAuB,EAAAJ,EAAA,MACAA,EAAAa,SAAAhC,EAAAC,QAAAkB,EAAAa,OAEA9B,GAAA,eAAAiB,GAAA,IJyEMc,GACA,SAAUjC,EAAQC,EAASC,GK/EjCA,EAAA,GAEA,IAAAC,GAAAD,EAAA,GAEAA,EAAA,IAEAA,EAAA,IAEA,KAEA,KAGAF,GAAAC,QAAAE,EAAAF,SLwFMiC,GACA,SAAUlC,EAAQC,GMxGxBD,EAAAC,SAAgBkC,OAAA,WAAmB,GAAAC,GAAAnB,KAAaoB,EAAAD,EAAAE,eAA0BC,EAAAH,EAAAI,MAAAD,IAAAF,CAC1E,OAAAE,GAAA,OACAE,YAAA,SACGF,EAAA,OACHE,YAAA,WACGF,EAAA,OACHE,YAAA,OACAC,IACAC,MAAAP,EAAAvB,QAEGuB,EAAAQ,GAAA,UAAAR,EAAAQ,GAAA,KAAAL,EAAA,OACHE,YAAA,WACGL,EAAAQ,GAAA,WAAAR,EAAAQ,GAAA,KAAAL,EAAA,OACHE,YAAA,YACGL,EAAAQ,GAAA,KAAAL,EAAA,OACHM,IAAA,UACAJ,YAAA,UACAC,IACA1B,OAAAoB,EAAApB,UAEGoB,EAAAU,GAAA,kBACFC,qBN8GKC,GACA,SAAUhD,EAAQK,EAAqBH,GAE7C,YACAI,QAAOC,eAAeF,EAAqB,cAAgBG,OAAO,GAC7C,IAAIyC,GAAqD/C,EAAoB,IACzEgD,EAA6DhD,EAAoBiD,EAAEF,EO1H5G5C,GAAA,SPgIE+C,YO9HFC,KAAAH,EAAAI,GP+HE5C,KAAM,WACJ,OACE6C,OAAQC,KAAKD,SAASE,QO7H5B,KPgIErC,UAAW,WACTsC,QAAQC,IO9HZ,mBPgIEC,YAAa,WACXF,QAAQC,IO9HZ,qBPgIEE,UAAW,WACTH,QAAQC,IO9HZ,qBPoIMG,GACA,SAAU9D,EAAQC,GQnKxBD,EAAAC,SAAgBkC,OAAA,WAAmB,GAAAC,GAAAnB,KAAaoB,EAAAD,EAAAE,eAA0BC,EAAAH,EAAAI,MAAAD,IAAAF,CAC1E,OAAAE,GAAA,QAAAA,EAAA,OACAE,YAAA,SACGF,EAAA,KAAAH,EAAAQ,GAAA,gBAAAL,EAAA,KAAAH,EAAAQ,GAAA,UAAAR,EAAAQ,GAAA,WAAAR,EAAAQ,GAAA,KAAAL,EAAA,KAAAH,EAAAQ,GAAA,kBAAAR,EAAA2B,GAAA3B,EAAAmB,WAAAnB,EAAAQ,GAAA,KAAAR,EAAA4B,GAAA,YAAAb,GACH,MAAAZ,GAAA,KACA0B,IAAAd,IACKZ,EAAA,eACL2B,OACAC,GAAA,QAAAhB,KAEKf,EAAAQ,GAAA,yBAAAR,EAAA2B,GAAAZ,GAAA,cACF,MACFJ","file":"static/js/0.b50a17303326a3e6c4a0.js","sourcesContent":["webpackJsonp([0],{\n\n/***/ 18:\n/***/ (function(module, exports, __webpack_require__) {\n\nvar Component = __webpack_require__(5)(\n /* script */\n __webpack_require__(26),\n /* template */\n __webpack_require__(27),\n /* scopeId */\n null,\n /* cssModules */\n null\n)\n\nmodule.exports = Component.exports\n\n\n/***/ }),\n\n/***/ 19:\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n name: 'page',\n data: function data() {\n return {\n scrollTop: 0\n };\n },\n\n methods: {\n back: function back() {\n window.history.back();\n },\n scroll: function scroll() {\n this.scrollTop = this.$refs.content.scrollTop;\n }\n },\n activated: function activated() {\n this.$refs.content.scrollTop = this.scrollTop;\n }\n});\n\n/***/ }),\n\n/***/ 20:\n/***/ (function(module, exports, __webpack_require__) {\n\nexports = module.exports = __webpack_require__(14)();\n// imports\n\n\n// module\nexports.push([module.i, \".page{height:100%;position:relative}.header{background-color:#fff;position:absolute;width:100%;top:0;height:48px;line-height:48px;border-bottom:1px solid #e0e0e0;display:-webkit-box;display:-ms-flexbox;display:flex}.left,.right{width:40px;padding:0 10px;cursor:pointer}.center{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:center}.content{padding:0 10px;position:absolute;box-sizing:border-box;width:100%;top:49px;bottom:0;overflow:auto}\", \"\", {\"version\":3,\"sources\":[\"/Users/zack/Documents/projects/vue-navigation/examples/src/components/Page.vue\"],\"names\":[],\"mappings\":\"AACA,MACE,YAAa,AACb,iBAAmB,CACpB,AACD,QACE,sBAAuB,AACvB,kBAAmB,AACnB,WAAY,AACZ,MAAS,AACT,YAAa,AACb,iBAAkB,AAClB,gCAAiC,AACjC,oBAAqB,AACrB,oBAAqB,AACrB,YAAc,CACf,AACD,aACE,WAAY,AACZ,eAAgB,AAChB,cAAgB,CACjB,AACD,QACE,mBAAoB,AAChB,WAAY,AACR,OAAQ,AAChB,iBAAmB,CACpB,AACD,SACE,eAAgB,AAChB,kBAAmB,AACnB,sBAAuB,AACvB,WAAY,AACZ,SAAU,AACV,SAAY,AACZ,aAAe,CAChB\",\"file\":\"Page.vue\",\"sourcesContent\":[\"\\n.page {\\n height: 100%;\\n position: relative;\\n}\\n.header {\\n background-color: #fff;\\n position: absolute;\\n width: 100%;\\n top: 0px;\\n height: 48px;\\n line-height: 48px;\\n border-bottom: 1px solid #e0e0e0;\\n display: -webkit-box;\\n display: -ms-flexbox;\\n display: flex;\\n}\\n.left, .right {\\n width: 40px;\\n padding: 0 10px;\\n cursor: pointer;\\n}\\n.center {\\n -webkit-box-flex: 1;\\n -ms-flex: 1;\\n flex: 1;\\n text-align: center;\\n}\\n.content {\\n padding: 0 10px;\\n position: absolute;\\n box-sizing: border-box;\\n width: 100%;\\n top: 49px;\\n bottom: 0px;\\n overflow: auto;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n\n// exports\n\n\n/***/ }),\n\n/***/ 21:\n/***/ (function(module, exports, __webpack_require__) {\n\n// style-loader: Adds some css to the DOM by adding a \n\n\n\n// WEBPACK FOOTER //\n// Page.vue?04a97522","exports = module.exports = require(\"../../../node_modules/css-loader/lib/css-base.js\")();\n// imports\n\n\n// module\nexports.push([module.id, \".page{height:100%;position:relative}.header{background-color:#fff;position:absolute;width:100%;top:0;height:48px;line-height:48px;border-bottom:1px solid #e0e0e0;display:-webkit-box;display:-ms-flexbox;display:flex}.left,.right{width:40px;padding:0 10px;cursor:pointer}.center{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:center}.content{padding:0 10px;position:absolute;box-sizing:border-box;width:100%;top:49px;bottom:0;overflow:auto}\", \"\", {\"version\":3,\"sources\":[\"/Users/zack/Documents/projects/vue-navigation/examples/src/components/Page.vue\"],\"names\":[],\"mappings\":\"AACA,MACE,YAAa,AACb,iBAAmB,CACpB,AACD,QACE,sBAAuB,AACvB,kBAAmB,AACnB,WAAY,AACZ,MAAS,AACT,YAAa,AACb,iBAAkB,AAClB,gCAAiC,AACjC,oBAAqB,AACrB,oBAAqB,AACrB,YAAc,CACf,AACD,aACE,WAAY,AACZ,eAAgB,AAChB,cAAgB,CACjB,AACD,QACE,mBAAoB,AAChB,WAAY,AACR,OAAQ,AAChB,iBAAmB,CACpB,AACD,SACE,eAAgB,AAChB,kBAAmB,AACnB,sBAAuB,AACvB,WAAY,AACZ,SAAU,AACV,SAAY,AACZ,aAAe,CAChB\",\"file\":\"Page.vue\",\"sourcesContent\":[\"\\n.page {\\n height: 100%;\\n position: relative;\\n}\\n.header {\\n background-color: #fff;\\n position: absolute;\\n width: 100%;\\n top: 0px;\\n height: 48px;\\n line-height: 48px;\\n border-bottom: 1px solid #e0e0e0;\\n display: -webkit-box;\\n display: -ms-flexbox;\\n display: flex;\\n}\\n.left, .right {\\n width: 40px;\\n padding: 0 10px;\\n cursor: pointer;\\n}\\n.center {\\n -webkit-box-flex: 1;\\n -ms-flex: 1;\\n flex: 1;\\n text-align: center;\\n}\\n.content {\\n padding: 0 10px;\\n position: absolute;\\n box-sizing: border-box;\\n width: 100%;\\n top: 49px;\\n bottom: 0px;\\n overflow: auto;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/css-loader?{\"minimize\":true,\"sourceMap\":true}!../~/vue-loader/lib/style-compiler?{\"id\":\"data-v-7ca65025\",\"scoped\":false,\"hasInlineConfig\":false}!../~/vue-loader/lib/selector.js?type=styles&index=0!./src/components/Page.vue\n// module id = 20\n// module chunks = 0 1 2","// style-loader: Adds some css to the DOM by adding a \n\n\n\n// WEBPACK FOOTER //\n// Page.vue?04a97522","exports = module.exports = require(\"../../../node_modules/css-loader/lib/css-base.js\")();\n// imports\n\n\n// module\nexports.push([module.id, \".page{height:100%;position:relative}.header{background-color:#fff;position:absolute;width:100%;top:0;height:48px;line-height:48px;border-bottom:1px solid #e0e0e0;display:-webkit-box;display:-ms-flexbox;display:flex}.left,.right{width:40px;padding:0 10px;cursor:pointer}.center{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:center}.content{padding:0 10px;position:absolute;box-sizing:border-box;width:100%;top:49px;bottom:0;overflow:auto}\", \"\", {\"version\":3,\"sources\":[\"/Users/zack/Documents/projects/vue-navigation/examples/src/components/Page.vue\"],\"names\":[],\"mappings\":\"AACA,MACE,YAAa,AACb,iBAAmB,CACpB,AACD,QACE,sBAAuB,AACvB,kBAAmB,AACnB,WAAY,AACZ,MAAS,AACT,YAAa,AACb,iBAAkB,AAClB,gCAAiC,AACjC,oBAAqB,AACrB,oBAAqB,AACrB,YAAc,CACf,AACD,aACE,WAAY,AACZ,eAAgB,AAChB,cAAgB,CACjB,AACD,QACE,mBAAoB,AAChB,WAAY,AACR,OAAQ,AAChB,iBAAmB,CACpB,AACD,SACE,eAAgB,AAChB,kBAAmB,AACnB,sBAAuB,AACvB,WAAY,AACZ,SAAU,AACV,SAAY,AACZ,aAAe,CAChB\",\"file\":\"Page.vue\",\"sourcesContent\":[\"\\n.page {\\n height: 100%;\\n position: relative;\\n}\\n.header {\\n background-color: #fff;\\n position: absolute;\\n width: 100%;\\n top: 0px;\\n height: 48px;\\n line-height: 48px;\\n border-bottom: 1px solid #e0e0e0;\\n display: -webkit-box;\\n display: -ms-flexbox;\\n display: flex;\\n}\\n.left, .right {\\n width: 40px;\\n padding: 0 10px;\\n cursor: pointer;\\n}\\n.center {\\n -webkit-box-flex: 1;\\n -ms-flex: 1;\\n flex: 1;\\n text-align: center;\\n}\\n.content {\\n padding: 0 10px;\\n position: absolute;\\n box-sizing: border-box;\\n width: 100%;\\n top: 49px;\\n bottom: 0px;\\n overflow: auto;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/css-loader?{\"minimize\":true,\"sourceMap\":true}!../~/vue-loader/lib/style-compiler?{\"id\":\"data-v-7ca65025\",\"scoped\":false,\"hasInlineConfig\":false}!../~/vue-loader/lib/selector.js?type=styles&index=0!./src/components/Page.vue\n// module id = 20\n// module chunks = 0 1 2","// style-loader: Adds some css to the DOM by adding a \n\n\n\n// WEBPACK FOOTER //\n// Page.vue?04a97522","exports = module.exports = require(\"../../../node_modules/css-loader/lib/css-base.js\")();\n// imports\n\n\n// module\nexports.push([module.id, \".page{height:100%;position:relative}.header{background-color:#fff;position:absolute;width:100%;top:0;height:48px;line-height:48px;border-bottom:1px solid #e0e0e0;display:-webkit-box;display:-ms-flexbox;display:flex}.left,.right{width:40px;padding:0 10px;cursor:pointer}.center{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:center}.content{padding:0 10px;position:absolute;box-sizing:border-box;width:100%;top:49px;bottom:0;overflow:auto}\", \"\", {\"version\":3,\"sources\":[\"/Users/zack/Documents/projects/vue-navigation/examples/src/components/Page.vue\"],\"names\":[],\"mappings\":\"AACA,MACE,YAAa,AACb,iBAAmB,CACpB,AACD,QACE,sBAAuB,AACvB,kBAAmB,AACnB,WAAY,AACZ,MAAS,AACT,YAAa,AACb,iBAAkB,AAClB,gCAAiC,AACjC,oBAAqB,AACrB,oBAAqB,AACrB,YAAc,CACf,AACD,aACE,WAAY,AACZ,eAAgB,AAChB,cAAgB,CACjB,AACD,QACE,mBAAoB,AAChB,WAAY,AACR,OAAQ,AAChB,iBAAmB,CACpB,AACD,SACE,eAAgB,AAChB,kBAAmB,AACnB,sBAAuB,AACvB,WAAY,AACZ,SAAU,AACV,SAAY,AACZ,aAAe,CAChB\",\"file\":\"Page.vue\",\"sourcesContent\":[\"\\n.page {\\n height: 100%;\\n position: relative;\\n}\\n.header {\\n background-color: #fff;\\n position: absolute;\\n width: 100%;\\n top: 0px;\\n height: 48px;\\n line-height: 48px;\\n border-bottom: 1px solid #e0e0e0;\\n display: -webkit-box;\\n display: -ms-flexbox;\\n display: flex;\\n}\\n.left, .right {\\n width: 40px;\\n padding: 0 10px;\\n cursor: pointer;\\n}\\n.center {\\n -webkit-box-flex: 1;\\n -ms-flex: 1;\\n flex: 1;\\n text-align: center;\\n}\\n.content {\\n padding: 0 10px;\\n position: absolute;\\n box-sizing: border-box;\\n width: 100%;\\n top: 49px;\\n bottom: 0px;\\n overflow: auto;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/css-loader?{\"minimize\":true,\"sourceMap\":true}!../~/vue-loader/lib/style-compiler?{\"id\":\"data-v-7ca65025\",\"scoped\":false,\"hasInlineConfig\":false}!../~/vue-loader/lib/selector.js?type=styles&index=0!./src/components/Page.vue\n// module id = 20\n// module chunks = 0 1 2","// style-loader: Adds some css to the DOM by adding a