vue router动态路由下让每个子路由都是独立组件的解决方案
程序员文章站
2022-06-24 22:06:09
vue-router 之动态路由
vue-router官网上面是这样说的
// 带查询参数,变成 /register?plan=private
rou...
vue-router 之动态路由
vue-router官网上面是这样说的 // 带查询参数,变成 /register?plan=private router.push({ path: 'register', query: { plan: 'private' }}) 然后,我就这样写了: this.$router.push({path:'manage', query: {id: 'tasklist'}})1 结果很明显,失败了。然后我就默默的再次看了一下官网,结果发现了这句话 // 命名的路由 router.push({ name: 'user', params: { userid: 123 }}) // 带查询参数,变成 /register?plan=private router.push({ path: 'register', params: { plan: 'private' }}) 注意:如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path: const userid = 123 router.push({ name: 'user', params: { userid }}) // -> /user/123 router.push({ path: `/user/${userid}` }) // -> /user/123 // 这里的 params 不生效 router.push({ path: '/user', params: { userid }}) // -> /user 谨记啊,动态实现二级路由,需要先用变量保存二级路由名称(let router = 'tasklist'),然后调用this.$router.push({path: `/user/${router}`}).
下面看下vue router动态路由下让每个子路由都是独立组件的解决方案
因为 vue-router 对嵌套路由采用的是组件复用策略,这在大部分场景的确是高效的做法,但是如果遇到这种情况:
就是要求多个子路由共活,并且有频繁来回切换需求的话,就很希望能让每个子路由都是独立组件了,虽然可以通过监听路由切换
watch: { '$route'(to) { if (to.meta.path === '/page/buy-details') { this.id = to.params.id; this.state() } } },
去实时处理更新的数据,我之前一直都是这么做的,包括上面那副动图的页面,但是这真的很麻烦,要让用户切换中准确的回到切换前页面的显示状态,要考虑的东西太多,于是想出了一个解决方案:
子路由组件不涉及实际业务代码,只维护一个打开过的id列表,路由切换到这边时,判断id,没打开过的添加,通过这个列表循环出实际的子路由组件,v-show当前id的,这样就能实现每个实例都是独立的了
我按这个思路写出一个 mixins
details-page.js
export default { watch: { '$route'(to, from) { this.detailsleave(from); this.detailsopen(to); } }, data() { return { pagepath: '', pageid: 0, pages: {} } }, methods: { /** * 子页面打开触发 * @param route */ detailsopen(route) { if (this.detailspathget(route.path) === this.pagepath) { if (!this.pages[route.params.id]) { this.$set(this.pages, route.params.id, { id: route.params.id, scrolltop: 0 }) } //路由打开 跳转滚动条 this.pageid = route.params.id; this.$nexttick(()=>{ this.$parent.$el.firstchild.scrolltop = this.pages[route.params.id].scrolltop; }); } }, /** * 路由切换触发 * 判断离开的路由是否是当前页面,如果是则记录滚动条高度 * @param route */ detailsleave(route) { if (this.detailspathget(route.path) === this.pagepath) { if (this.pages[route.params.id]) { //记录滚动条高度 此处针对ea-admin后台 不同的框架要记录的滚动条el不同 this.pages[route.params.id].scrolltop = this.$parent.$el.firstchild.scrolltop ; } } }, /** * 子页面关闭函数 * @param id */ detailsclose(id) { delete this.pages[id] }, /** * 取路由不含最后一项参数的地址 * @param path * @returns {string} */ detailspathget(path) { const i = path.lastindexof('/'); return path.substr(0, i); } }, mounted() { //通过当前路由地址创建页面识别地址 注:只对path: '/user/:id' 有效 当 path: /user/:id/profile 失效 this.pagepath = this.detailspathget(this.$route.path); //执行第一次子页面打开 this.detailsopen(this.$route); //监听标签关闭消息 此处针对ea-admin后台 不同框架监听关闭方式不同 this.$tabs.onremove((page, next) => { //收到标签关闭回调,判断关闭的是否是当前页面 if (page._path === this.pagepath) { //触发子页面删除 this.detailsclose(page.id) } next() }) } }
details.vue
<template> <div> <your-component v-for="item in pages" :id="item.id" :key="item.id" v-show="item.id === pageid"> </your-component> </div> </template> <script> import yourcomponent from ''; import detailspage from '../mixins/details-page' export default { name: 'detailspage', components: {yourcomponent}, mixins: [detailspage], } </script>
这样子组件可以只专注处理自己的固定数据,因为组件唯一,不用再去烦恼为每个id存储视图状态了。
总结
以上所述是小编给大家介绍的vue router动态路由下让每个子路由都是独立组件的解决方案,希望对大家有所帮助