Vue中对iframe实现keep alive(无刷新)

参考:

Vue中对iframe实现keep alive(无刷新) - 掘金

首先,将addRoutes.js中的ifame页面的路由component改成iframeComponent。

然后,再改Home.vue,在此文件中之前就是使用keep-alive写的,在下面加个ifame的。

 

以下是Home.vue原来的样子(根据打开的标签页缓存)(省略了很多内容)

<template>
    <div>
        <keep-alive :include="tagsList">
            <router-view></router-view>
        </keep-alive>
    </div>
</template>
​
<script>
    export default {
        data() {
            return {
                tagsList: [],
            }
        },
        created() {
        // 只有在标签页列表里的页面才使用keep-alive,即关闭标签之后就不保存到内存中了。
            bus.$on('tags', msg => {
                let arr = [];
                for (let i = 0, len = msg.length; i < len; i++) {
                    if (msg[i].name != 'projectFlow') {
                        msg[i].name && arr.push(msg[i].name);
                    }
                }
                this.tagsList = arr;
            })
            bus.$on('removeKeep', msg => {
                for (let i = 0, len = this.tagsList.length; i < len; i++) {
                    if (this.tagsList[i] == msg) {
                        this.tagsList.splice(i, 1)
                        break;
                    }
                }
            })
        },
        mounted() {
        },
        methods: {}
    }
</script>
​
​

加入ifame页面缓存(实现打开的tag标签页,再次通过点击上面的tag打开不刷新页面)代码之后:

<template>
    <div>
        <keep-alive :include="tagsList">
            <router-view></router-view>
        </keep-alive>
        //-----iframe页面-------
        <component
            v-for="item in hasOpenComponentsArr"
            :key="item.name"
            :is="item.name"
            v-show="$route.path === item.path"
        ></component>
    </div>
</template>
<script>
export default {
    created() {
    // 只有在标签页列表里的页面才使用keep-alive,即关闭标签之后就不保存到内存中了。
            bus.$on('tags', msg => {
                let arr = [];
                for (let i = 0, len = msg.length; i < len; i++) {
                    if (msg[i].name != 'projectFlow') {
                        msg[i].name && arr.push(msg[i].name);
                    }
                }
                this.tagsList = arr;
            })
            bus.$on('removeKeep', msg => {
                for (let i = 0, len = this.tagsList.length; i < len; i++) {
                    if (this.tagsList[i] == msg) {
                        this.tagsList.splice(i, 1)
                        break;
                    }
                }
            })
            
            
            
        // 设置iframe页的数组对象
        const componentsArr = this.getComponentsArr();
        componentsArr.forEach((item) => {
            Vue.component(item.name, item.component);
        });
        this.componentsArr = componentsArr;
        // 判断当前路由是否iframe页
        this.isOpenIframePage();
    },
    data() {
        return {
            componentsArr: [] // 含有iframe的页面
        }
    },
    watch: {
        $route() {
            // 判断当前路由是否iframe页
            this.isOpenIframePage();
        }
    },
    computed: {
        // 实现懒加载,只渲染已经打开过(hasOpen:true)的iframe页
        hasOpenComponentsArr() {
            return this.componentsArr.filter(item => item.hasOpen);
        }
    },
    methods: {
        // 根据当前路由设置hasOpen
        isOpenIframePage() {
            const target = this.componentsArr.find(item => {
                return item.path === this.$route.path
            });
            if (target && !target.hasOpen) {
                target.hasOpen = true;
            }
        },
        // 遍历路由的所有页面,把含有iframeComponent标识的收集起来
        getComponentsArr() {
            const router = this.$router;
            const routes = router.options.routes;
            const homeroutes = routes[routes.length-1];
            const addroutes = homeroutes[0].children;
            const iframeArr = routes.filter(item => item.iframeComponent);
            
            return iframeArr.map((item) => {
                const name = item.name || item.path.replace('/', '');
                return {
                    name: name,
                    path: item.path,
                    hasOpen: false, // 是否打开过,默认false
                    component: item.iframeComponent // 组件文件的引用
                };
            });
        }
    }
}
</script>

如上代码this.$router获取不到addroutes中的路由需要手动添加,参考文章如下:

关于vue-router动态添加路由$router.options不更新的解决办法_快乐远航1的博客-CSDN博客_router.options

在addroutes.js中添加router.options.routes.push(rootRoute)手动更新$router

源代码如下:

var rootRoute = [{
                path: '/',
                component: resolve => require(['@/components/common/Home.vue'], resolve),
                meta: {
                    title: '自述文件'
                },
                children: routeList
                //routeList是addroutes中所有的路由
            }];
            //添加新窗口打开的页面
            if (routeHideList && routeHideList.length > 0) {
                rootRoute = rootRoute.concat(routeHideList);
            }
            //保存路由参数到store中
            state.routeParam = routeParam;
            state.rootRoute = rootRoute;
            //手动更新$router
            router.options.routes.push(rootRoute)
            //动态添加路由
            router.addRoutes(rootRoute)

补充:

缓存所有页面(keep-alive用法):

    在 Home.vue 里面

<template>
  <div id="app">
      <keep-alive>
      <router-view/>
    </keep-alive>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

猜你喜欢

转载自blog.csdn.net/wulikunbing/article/details/128973779