V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jiushengyuan
V2EX  ›  Vue.js

路由 A 中的自定义 component 里,有个定时器,跳转到另个路由里,如何关闭定时器?

  •  
  •   jiushengyuan · 2019-10-10 18:10:49 +08:00 · 2949 次点击
    这是一个创建于 1906 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题如标题。

    我搜索,大部分资料是 路由 A 中有个定时器,不是在 component 里。我现在的问题是 如何获取到 component 中 timer = setTimeout() 的这个 timer。

    只找到 点击这里,是把 timer 写成全局的了,所以方便访问。不知道这样好不好,有其他方法吗?

    示例代码:

    Vue.component('v-osd', {
        template: 'xxx',
        data: function() {
            var myData = {};
            function refresh() {
                get(
                    'get_client_osd_list', {
                        id: 1,
                    },
                    response => {
                        refreshTimer = setTimeout(function() {
                            refresh();
                        }, 500);
                    }
                );
    
            }
            refresh();
            return myData;
        },
    });
    
    var routeA = {
        template: 'yyy',
        data: function() {
            return {};
        },
        
        beforeRouteLeave(to, from, next) {
            // 如何获取到 组件里面的 timer??
            clearInterval(refreshTimer);
            next();
        },
    };
    
    第 1 条附言  ·  2019-10-11 10:17:36 +08:00

    发现在 ajax 的 response 里 setTimeout,在 clearTimeout 时,会有其他问题。为了避免问题偏移,去掉ajax,新的示例如下: 参考 wiluxy,在组件的 beforeDestroy 中清除

    <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
    <script src="https://unpkg.com/[email protected]/dist/vue-router.js"></script>
    
    <div id="app">
        <router-link to='/routea'>go to a</router-link>
        <router-link to='/routeb'>go to b</router-link>
        <router-view></router-view>
    </div>
    
    <!-- component -->
    <template id='templateOsd'>
        <div>component osd</div>
    </template>
    
    <template id="templatea">
        <div>route a</div>
    </template>
    
    <template id="templateb">
        <div>
            <div>route b</div>
            <v-osd></v-osd>
        </div>
    </template>
    
    <script src="index.js"></script>
    
    Vue.component('v-osd', {
        template: '#templateOsd',
        data: function () {
            var myData = {
                refreshTimer: -1,
            };
            var self = this;
    
            function refreshOsd() {
                console.log('refreshOsd in');
                self.refreshTimer = setTimeout(refreshOsd, 2000);
            }
            refreshOsd();
            return myData;
        },
        beforeDestroy: function () {
            console.log('v-osd beforeDestory');
            clearTimeout(this.refreshTimer)
        },
        destroyed: function () {
            console.log('v-osd destroyed');
        }
    });
    
    // 路由a
    var componenta = {
        template: '#templatea',
        data: function () {
            var data = {};
            return data;
        },
    };
    
    // 路由b
    var componentb = {
        template: '#templateb',
        data: function () {
            var data = {};
            return data;
        },
    };
    
    var router = new VueRouter({
        routes: [{
                name: "a",
                path: "/routea",
                component: componenta
            },
            {
                name: "b",
                path: "/routeb",
                component: componentb
            }
        ]
    
    })
    
    var app = new Vue({
        router,
        data: {},
    })
    app.$mount('#app');
    
    4 条回复    2019-10-12 17:42:00 +08:00
    wiluxy
        1
    wiluxy  
       2019-10-10 19:44:43 +08:00
    跳转到另外一个路由的话,如果当前路由没有倍<keep-active>保留的话,component 应该就跟着销毁了,调用组件销毁前生命周期清除定时器,或者用 vue-router 的路由跳转钩子函数。。。跳转前判断当前路由是不是路由 A,是的话就清除定时器
    15651980765
        2
    15651980765  
       2019-10-11 09:52:16 +08:00
    这个组件没有 keepalive 缓存的话,beforeDestroy 的时候清除这个定时器;
    这个组件有 keepalive 缓存的话,deactivated 的时候清除这个定时器。
    个人观点,如有错误请指正。
    楼上通过路由跳转钩子函数判断当前路由的方法好像也可以,但是定时器应该得放在全局变量里。
    jiushengyuan
        3
    jiushengyuan  
    OP
       2019-10-11 10:23:49 +08:00
    感谢 @wiluxy @15651980765 提供的,
    现在在 component beforeDestroy 中,引用 refreshTimer,就不用设成全局变量了。

    有个新问题,路由是没有 keepalive 的,如果我不清除定时器,在跳转到新路由时,refreshOsd 还是会不断执行,也可以访问到其中的 self 是个 compoenent。
    可是 component 不是已经被销毁了吗?
    jiushengyuan
        4
    jiushengyuan  
    OP
       2019-10-12 17:42:00 +08:00
    是给的代码示例太长,大家都没耐心看了么。其实那个只是方便模拟贴出来,问题不复杂的。

    新问题:路由是没有 keepalive 的,如果我不清除定时器,在跳转到新路由时,refreshOsd 还是会不断执行,也可以访问到其中的 self 是个 compoenent。
    可是 component 不是已经被销毁了吗?

    有没有大佬帮忙看看呀
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1416 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 17:22 · PVG 01:22 · LAX 09:22 · JFK 12:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.