Vue路由器-路由加载后的呼叫功能

时间:2018-09-23 16:31:41

标签: javascript vue.js vue-router

我正在一个项目中,在路线加载完成后,我需要调用一个函数。但是,当使用“监视”功能时,它仅在路线更改时加载,而是在路线完成加载之前加载。因此,当我尝试运行针对页面上DOM元素的脚本时,这些元素尚不存在。 Vue Router中是否有任何功能可以让我等到所有内容渲染完毕后再运行脚本?

const app = new Vue({
    el: '#app',
    router,
    watch: {
        '$route': function (from, to) {
            function SOMEFUNCTION()
         }   
    },
    data: {
        some data
    },
    template: `
      <router-view/>
  `
})

5 个答案:

答案 0 :(得分:2)

在这种情况下,我认为应该使用已加载组件的组件生命周期方法,或者使用装入方法,也可以使用创建方法。

或者如果您的脚本不依赖任何vue组件(存储),则可以使用router.afterEach钩子

Type_id

答案 1 :(得分:0)

您可以通过插入VueJS lifecycle hooks来完成此操作:

  1. 使用VueJS生命周期挂钩: 这是主要的VueJS生命周期挂钩的摘要。请查阅文档以获取完整描述。

i。 beforeCreate:将在创建组件之前调用此函数

ii。 created:创建组件后将调用此函数,但请注意,尽管已创建组件,但尚未挂载。因此,您将无法访问组件的this。但是,这是制作Network Requests的好地方,它将更新数据属性。

iii。 mounted:一旦渲染了组件并且可以在此处访问元素,则调用此函数。这就是您要寻找的。

iv。 beforeDestroy:在销毁组件之前调用此函数。这对于停止您创建的所有侦听器(setTimeout,setInterval ..)很有用。

See the diagram below for the details.

const app = new Vue({
    el: '#app',
    router,
    mounted(){
      this.someFunction()
    },
    data: {
        some data
    },
    template: `
      <router-view/>
  `
})
  1. 使用Vue Router导航防护:Vue Router还公开了一些可以挂钩的生命周期挂钩。但是,正如您将在下面看到的,它们不符合您的要求:

i。 beforeRouteEnter:在确认呈现此组件的路由之前调用。 oes无法访问this组件实例,因为在调用此防护时尚未创建它!

ii。 beforeRouteUpdate:当呈现此组件的路线已更改,但该组件在新路线中被重用时调用。

iii。 beforeRouteLeave:在将要渲染远离该组件的路线时调用。

enter image description here

参考文献:

VueJS文档(LifeCycle):VueJS Instance

Vue路由器文档(导航卫士):Navigation Guards

答案 2 :(得分:0)

对我来说,解决方案是在每个页面的mounted()挂钩中使用mixin设置自定义事件,然后在body上监听该事件。如果您想严格将其与路由器的afterEach或路由观察器绑定在一起,以确保在触发事件之前确实更改了路由,则可以在Promise中设置afterEach并通过事件或通过mounted()共享resolve函数在页面的window中解决它。

一个例子:

// Component.vue

    watch: {
      '$route': function (from, to) {
        new Promise((resolve) => {
          window.resolveRouteChange = resolve;
        }).then(() => {
          // route changed and page DOM mounted!
        });
      }
    }

// PageComponent.vue

    mounted() {
      if(window.resolveRouteChange) {
        window.resolveRouteChange();
        window.resolveRouteChange = null;
      }
    }

答案 3 :(得分:0)

您应该使用Vue.nextTick

在您的情况下,这将转换为:

const app = new Vue({
    el: '#app',
    router,
    watch: {
        $route() {
            this.$nextTick(this.routeLoaded);
         }   
    },
    data() {
        return {};
    },
    methods: {
        routeLoaded() {
           //Dom for the current route is loaded
        }
    },
    mounted() {
       this.routeLoaded();
    },
    template: `<router-view/>`
})

这将在每次路线更改时调用routeLoaded方法(由于您正在使用<router-view>元素,因此我推断这是您需要的),如果您也想一开始调用它,我建议mounted hook或观察者上的immediate flag

答案 4 :(得分:0)

如果是路由器视图,我们可以手动检测路由器视图。更改$ route后,$ el会更改

watch: {
        '$route'(to, from) {
            // Get $el that is our starting point
            let start_el = this.$refs.routerview.$el
            this.$nextTick(async function() { await this.wait_component_change(start_el)})
        }
    },
    methods: {
        on_router_view_component_changed: function() { }
        wait_component_change: async function(start_el) {
            // Just need to wait when $el is changed in async manner
            for (let i = 0; i < 9; i++) {
                console.log('calc_has_dragscroll ' + i)
                if(start_el) {
                    if (!start_el.isSameNode(this.$refs.routerview.$el)) {
                        // $el changed - out goal completed
                        this.on_router_view_component_changed()
                        return
                    }
                }
                else {
                    // No start_el, just wait any other
                    if(this.$refs.routerview.$el) {
                        // $el changed - out goal completed too
                        this.on_router_view_component_changed()
                        return
                    }
                }
                await this.$nextTick()
            }
        },
    }