{"_id":"@bobfintech-opensource/vue-router-dynamic-cache","name":"@bobfintech-opensource/vue-router-dynamic-cache","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@bobfintech-opensource/vue-router-dynamic-cache","version":"1.0.0","description":"基于 vue-router 及 vuex 的一种应用于 H5 单页应用（SPA）的路由组件动态缓存。","main":"index.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"repository":{"type":"git","url":"git+https://github.com/bobfintech-opensource/vue-router-dynamic-cache.git"},"author":{"name":"bobfintech-opensource"},"license":"MIT","bugs":{"url":"https://github.com/bobfintech-opensource/vue-router-dynamic-cache/issues"},"homepage":"https://github.com/bobfintech-opensource/vue-router-dynamic-cache#readme","_id":"@bobfintech-opensource/vue-router-dynamic-cache@1.0.0","_nodeVersion":"16.17.0","_npmVersion":"8.15.0","dist":{"integrity":"sha512-/C6E0YHGmjfIZam5o2AJE0J/jIdl8EbB9/4h2QoLAV8pI/bs10bDnu3j3Og2RJeEFgdzuuEs8zrCAkZZtCDh9A==","shasum":"37e9a66288d9ad30d7e7ece71700b90773898d4b","tarball":"https://registry.npmjs.org/@bobfintech-opensource/vue-router-dynamic-cache/-/vue-router-dynamic-cache-1.0.0.tgz","fileCount":7,"unpackedSize":28235,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG5dskPMmS+qjR83qzaskgSFRHW2Cx1pIuAIhRcD+GUHAiADzhngBrbM0/PZF+nI8NfLwU3kbGwdbbXKeDQdFWVloQ=="}]},"_npmUser":{"name":"jeremykkk","email":"wang-junjie@outlook.com"},"directories":{},"maintainers":[{"name":"jeremykkk","email":"wang-junjie@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vue-router-dynamic-cache_1.0.0_1700549423363_0.8851120451392807"},"_hasShrinkwrap":false}},"time":{"created":"2023-11-21T06:50:23.299Z","1.0.0":"2023-11-21T06:50:23.516Z","modified":"2023-11-21T06:50:23.761Z"},"maintainers":[{"name":"jeremykkk","email":"wang-junjie@outlook.com"}],"description":"基于 vue-router 及 vuex 的一种应用于 H5 单页应用（SPA）的路由组件动态缓存。","homepage":"https://github.com/bobfintech-opensource/vue-router-dynamic-cache#readme","repository":{"type":"git","url":"git+https://github.com/bobfintech-opensource/vue-router-dynamic-cache.git"},"author":{"name":"bobfintech-opensource"},"bugs":{"url":"https://github.com/bobfintech-opensource/vue-router-dynamic-cache/issues"},"license":"MIT","readme":"### 使用文档及使用案例还在持续迭代更新中\r\n\r\n# vue-router-dynamic-cache\r\n\r\n### 介绍\r\n本软件是基于vue-router及vuex的一种H5单页应用（SPA）的路由组件动态缓存策略实现软件。\r\n本软件能够在不修改vue-router框架源代码，不侵入业务组件代码，不增加业务组件逻辑功能的情况下，实现了H5单页应用中路由组件动态缓存功能，解决了H5单页应用难以实现路由组件前进重新加载，后退不刷新和在应用单次访问会话期间无法保留历史路由组件数据及状态的问题。使应用的用户操作体验更接近于原生应用，是H5单页应用路由组件动态缓存的更优化实现。\r\n\r\n##### 本软件包含了以下几个特征：\r\n1. 基于vue-router及vuex的一种H5单页应用（SPA）的路由组件动态缓存策略\r\n1. 不修改vue-router框架源代码，可以兼容vue-router3及vue-router4版本\r\n1. 能够在不侵入业务组件代码，不增加业务组件逻辑功能的情况下，实现H5单页应用路由组件动态缓存，解决H5单页应用难以实现路由组件前进重新加载，后退不刷新功能的问题\r\n1. 保留了应用在单次访问会话期间历史路由组件的数据及状态\r\n1. 为开发者提供了可动态设置不缓存当前页面的功能\r\n\r\n#### 使用\r\n\r\n##### 使用前注意事项\r\n1. 目前该软件只支持vue-router3及vue-router4版本\r\n1. 该软件需要使用vuex状态管理\r\n\r\n##### 开始步骤\r\n（1）安装依赖包，  \r\n（2）配置路由之间的关系，  \r\n（3）引入依赖包，  \r\n（4）调用依赖包`dynamicCacheRouter`对router实例进行增强，  \r\n（5）调用app.use()注册`cecheRouter`实例，  \r\n（6）在业务组件路由跳转中使用，    \r\n\r\n使用示例项目请参考[vue-router-dynamic-cache使用示例](https://github.com/githubzhuangye/vue-router-dynamic-cache) \r\n\r\n具体请看下面示例步骤：\r\n\r\n1. install 安装\r\n```js\r\n    // `使用组件缓存需要做的第一步`：安装依赖包\r\n    npm install --save vue-router-dynamic-cache\r\n```\r\n\r\n2. 引入及调用\r\n\r\n在以下这样的示例项目中：\r\n![示例新闻项目](https://github.com/githubzhuangye/vue-router-dynamic-cache/blob/master/images/demo-project.png)\r\n\r\n\r\n```js\r\n// `使用组件缓存需要做的第二步`：配置路由之间的关系。按照示例项目的要求，配置示例如下(开发者根据需求动态调整)\r\n\r\nconst routes = [\r\n    {\r\n        path: '/',\r\n        name: 'Root',\r\n        component: () => import('@/pages/layout.vue'),\r\n        redirect: '/home',\r\n        children: [\r\n            {\r\n                path: '/home',\r\n                name: 'Home',\r\n                meta: {\r\n                    name: '首页',\r\n                    title: '新闻首页',\r\n                    keepAlive: true, // 为true的话，该组件将永远不销毁（请慎用）\r\n                    cacheRouterNext: ['NewsList'], // 从首页进入新闻列表，列表页不缓存，每次重新初始化\r\n                },\r\n                component: () => import('@/pages/home/index.vue'),\r\n            }\r\n        ],\r\n    },\r\n    {\r\n        path: '/news/list',\r\n        name: 'NewsList',\r\n        meta: {\r\n            title: '新闻列表',\r\n            keepAlive: false,\r\n            cacheRouterPrev: ['Home'], // 新闻列表页返回首页时，销毁列表页\r\n            cacheRouterNext: ['NewsDetail'], // 列表页进入新闻详情页时，详情页不缓存，每次重新初始化\r\n        },\r\n        component: () => import('@/pages/news/list.vue'),\r\n    },\r\n    {\r\n        path: '/news/detail',\r\n        name: 'NewsDetail',\r\n        meta: {\r\n            title: '新闻详情',\r\n            keepAlive: false,\r\n            cacheRouterPrev: ['NewsList'], // 新闻详情页返回列表页，直接显示缓存的列表页，需要配置\r\n        },\r\n        component: () => import('@/pages/news/detail.vue'),\r\n    }\r\n]\r\n\r\n// 在`router/index.js`文件中（如果你使用了vue路由，自然就应该有这个文件），开发者自己创建的router实例\r\n\r\nconst router = createRouter({\r\n    history: createWebHistory(xxxxxxxx), // 采用history模式\r\n    routes, // 上面配置的路由\r\n    linkActiveClass: 'is-active',\r\n});\r\n```\r\n\r\n```js\r\n// 在`src/main.js`主入口文件中, \r\nimport router from 'path to router(路由入口路径)';\r\n\r\n//  `使用组件缓存需要做的第三步`：引入依赖包\r\nimport dynamicCacheRouter from 'vue-router-dynamic-cache';\r\n\r\n// `使用组件缓存需要做的第四步`：调用依赖包`dynamicCacheRouter`对router实例进行增强，并将返回的新的cecheRouter实例\r\nconst { cecheRouter, store } = dynamicCacheRouter(router, store);\r\n\r\n// `使用组件缓存需要做的第五步`：调用app.use()注册`cecheRouter`实例\r\nconst app = createApp(App);\r\napp.use(cecheRouter)；\r\n// app.use(store); // 如果开发者需要使用store，可以加上\r\napp.mount('#app');\r\n\r\n```\r\n\r\n3. 具体使用\r\n```js\r\n//  `使用组件缓存需要做的第六步`：在业务组件中使用\r\n\r\n// 以上面的例子，从首页跳转到新闻详情\r\nimport { ROUTER_CACHE_CONSTANTS } from 'vue-router-dynamic-cache'; // 引入常量\r\n\r\nconst handleNavNewsList = () => {\r\n    router.push({\r\n        path: '/news/list',\r\n        // hash值可自定义，开发者可以根据需求，继续拼接自定义参数\r\n        hash: ROUTER_CACHE_CONSTANTS.KEY.ROUTER_ALIVE_HASH_PUSH, \r\n    });\r\n};\r\n\r\n// 从新闻列表页返回首页\r\nconst handleBack = () => {\r\n    router.back();\r\n}\r\n\r\n// 从新闻列表页跳转到新闻详情\r\nconst handleNavDetail = (index) => {\r\n    router.push({\r\n        path: '/news/detail',\r\n        query: newsList.value[index].id,\r\n        // hash值是动态缓存的标识,开发者可以根据需求，继续拼接自定义参数\r\n        hash: ROUTER_CACHE_CONSTANTS.KEY.ROUTER_ALIVE_HASH_PUSH,\r\n    });\r\n};\r\n\r\n// 从新闻详情页返回新闻列表，当然了，使用系统自带的返回按钮也可以达到动态缓存的效果。\r\nconst handleNavBack = () => {\r\n    router.back();\r\n}\r\n\r\n```\r\n\r\n### 方法及参数说明\r\n\r\n#### dynamicCacheRouter方法说明\r\n```js\r\n/**\r\n * 处理路由缓存内容，在全局前置守卫`beforeEach`中添加处理函数\r\n * @param router createRouter创建的路由实例，必传\r\n * @param store createStore 创建的实例，非必传，请注意，当不传store时，方法会自行创建一个store实例并返回。\r\n * @returns Object { cacheRouter，store } 增强后的router及store。\r\n *  */ \r\nfunction dynamicCacheRouter(router, store) {\r\n    // 增强处理 XXXX\r\n    return {\r\n        cacheRouter: router,\r\n        store\r\n    };\r\n}\r\n\r\n```\r\n\r\n#### hash常量说明\r\n```js\r\nconst KEY = {\r\n    ROUTER_ALIVE_HASH_PUSH, // 动态缓存功能标识，使用`router.push`时都需要加上该值\r\n    ROUTER_ALIVE_HASH_BACK, // 使用`router.push`返回上一级时，础上拼接上该hash值，以便和router.back做区分\r\n    ROUTER_ALIVE_HASH_RELOAD_BACK, // 通过router.push跳级返回，且需要重新加载返回页，则拼接上该值\r\n    ROUTER_ALIVE_HASH_NO_CACHE_FROM, // 动态设置不缓存,如果router.push，hash上拼接上该值，则不缓存\r\n    ROUTER_ALIVE_HASH_PUSH_REPLACE, // 当使用router.push({ replace: true})或者router.replace进行路由导航，在hash加拼接上该值。\r\n}\r\n```\r\n\r\n|  router.push时的hash常量   | 使用说明  |\r\n|  ----  | ----  |\r\n| ROUTER_ALIVE_HASH_PUSH  | 当需要动态缓存功能时，使用`router.push`时都需要加上该值 |\r\n| ROUTER_ALIVE_HASH_BACK  | 如果需要使用`router.push`返回上一级时则在`ROUTER_ALIVE_HASH_PUSH`基础上拼接上该hash值，以便和router.back做区分，（以例子说明，在新闻详情返回新闻新闻列表，开发者可以使用`router.back`或者`router.push`，虽然一般情况下应该使用`router.back`） |\r\n| ROUTER_ALIVE_HASH_RELOAD_BACK  | 通过router.push跳级返回，且需要重新加载返回页，则拼接上该值 |\r\n| ROUTER_ALIVE_HASH_NO_CACHE_FROM  | 动态设置不缓存,如果`router.push`时，如果不想要缓存这次跳转的当前路由组件，在hash上拼接上该值，则不缓存 |\r\n| ROUTER_ALIVE_HASH_PUSH_REPLACE  | 当使用router.push({ replace: true})或者router.replace进行路由导航时，在hash加拼接上该值。因为使用这种跳转方式时，当前页面栈不会在history保留 |\r\n\r\n\r\n\r\n\r\n\r\n#### 技术背景\r\n\r\n由于H5单页应用（SPA）渲染原理（以vue项目为例）：进入路由导航时，统一资源定位符（url）的更改触发路由对应的onHashChange/pushState/popState/replaceState方法，通过统一资源定位符（url）中的path路径去匹配路由配置文件中对应的路由组件，加载并实例化渲染在项目出口路由视图（router-view）中。一般而言，一个应用中路由视图的渲染出口只有一个，这就意味着一个路由组件实例的解析渲染则意味着另外一个路由组件实例的销毁，导致在应用访问期间，即便是我们已经访问过的渲染过的路由组件，在路由导航返回时，其对应路由组件也会重新加载，重新初始化，致使组件状态丢失，用户体验不佳，有时还会重复请求网络数据造成不必要的资源浪费。\r\n\r\n而如果使用vue-router插件的keep-alive组件提供的路由组件缓存功能，由于vue-router本身没有提供对缓存组件的动态增加删除接口。一旦路由组件被缓存，那么在应用访问会话期间将一直留存在缓存栈中，当路由导航再次进入时，哪怕参数已经更改，vue-router插件也只会从已缓存的组件列表中获取组件并重新渲染，这种情况下路由组件就无法重新加载，状态无法更新，严重时将导致业务逻辑错误。另外，vue-router插件无法获取当前应用的路由导航访问历史栈，开发者也不能对当前应用路由访问缓存历史栈进行操作，然而在某些特殊的场景下，开发者需要动态更新已被缓存的组件。\r\n\r\n基于vue框架的H5单页应用的视图渲染特性及vue-router的接口设计，想要应用能在不修改vue-router框架源代码，不侵入业务代码，不增加业务组件逻辑功能的情况下，实现H5单页应用中路由组件动态缓存功能，解决H5单页应用难以实现路由组件前进重新加载，后退不刷新且在应用单次访问会话期间保留历史路由组件数据及状态的问题，使应用的用户体验更加接近于App原生应用，并非一件易事。\r\n\r\n\r\n### 发布主体\r\n\r\n[北银金融科技有限责任公司](https://www.bobfintech.com.cn/)\r\n\r\n### 许可证\r\n\r\n[MIT](https://github.com/bobfintech/vue-router-dynamic-cache/blob/master/LICENSE)\r\n\r\n### 维护者\r\n[z-yates](zhuangshujie@bobfintech.com.cn)","readmeFilename":"README.md"}