[英]Vue Router - call function after route has loaded
I'm working on a project where I need to call a function AFTER the route has finished loading.我正在开发一个项目,我需要在路由完成加载后调用一个函数。 However, when using the 'watch' functionality, it only loads on route change, but does so before route has finished loading.
但是,当使用“监视”功能时,它只会在路线更改时加载,但会在路线完成加载之前加载。 So when I attempt to run a script that targets DOM elements on the page, those elements don't exist yet.
因此,当我尝试运行以页面上的 DOM 元素为目标的脚本时,这些元素还不存在。 Is there any functionality in Vue Router that would allow me to wait until everything is rendered before running the script?
Vue Router 中是否有任何功能可以让我等到所有内容都呈现后再运行脚本?
const app = new Vue({
el: '#app',
router,
watch: {
'$route': function (from, to) {
function SOMEFUNCTION()
}
},
data: {
some data
},
template: `
<router-view/>
`
})
You should use Vue.nextTick
你应该使用
Vue.nextTick
In your case this would translate to:在您的情况下,这将转化为:
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() {
/* The route will not be ready in the mounted hook if it's component is async
so we use $router.onReady to make sure it is.
it will fire right away if the router was already loaded, so catches all the cases.
Just understand that the watcher will also trigger in the case of an async component on mount
because the $route will change and the function will be called twice in this case,
it can easily be worked around with a local variable if necessary
*/
this.$router.onReady(() => this.routeLoaded());
},
template: `<router-view/>`
})
This will call the routeLoaded method every time the route changes (which I'm deducing is what you need since you are using the <router-view>
element), if you also want to call it initially, I would recommend the mounted hook (like in the example) or the immediate flag on the watcher这将在每次路由更改时调用 routeLoaded 方法(我推断这是您需要的,因为您使用的是
<router-view>
元素),如果您还想最初调用它,我会推荐安装的钩子(就像在示例中一样)或观察者上的立即标志
In my opinion on this situation, you should use component life cycle method of the loaded component, either use mounted method or created method.在这种情况下,我认为你应该使用加载组件的组件生命周期方法,要么使用mounted方法,要么使用created方法。
or if your script doesn't depend on any vue component (store) you can use router.afterEach hook或者如果您的脚本不依赖于任何 vue 组件(存储),您可以使用 router.afterEach 挂钩
router.afterEach((to, from) => { if (to.name !== 'ROUTENAME'){ // do something }});
The solution for me was to set up a custom event in every page's mounted()
hook with a mixin and listen for that event on the body
for example.对我来说,解决方案是在每个页面的
mounted()
钩子中使用 mixin 设置一个自定义事件,并在body
上监听该事件。 If you wanted to strictly tie it with the router's afterEach
or the route watcher to ensure the route has indeed changed before the event was fired, you could probably set up a Promise
in the afterEach
and resolve it in the page's mounted()
by either the event or sharing the resolve
function through the window
.如果您想将其与路由器的
afterEach
或路由观察程序严格绑定以确保在事件触发之前路由确实已更改,您可以在afterEach
中设置一个Promise
并通过页面的mounted()
解决它事件或通过window
共享resolve
功能。
An example:一个例子:
// 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;
}
}
In case of router-view, we can manually detect router-view.$el change after $route is changed在router-view的情况下,我们可以手动检测router-view.$el在$route改变后的变化
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()
}
},
}
You can accomplish this by hooking into VueJS lifecycle hooks
:您可以通过挂钩 VueJS
lifecycle hooks
来完成此操作:
i.一世。
beforeCreate
: This function will be called before the component is created beforeCreate
:该函数将在组件创建之前被调用
ii. ii.
created
: This function will be called after the component is created, but note although the component is created, it hasn't been mounted yet. created
: 这个函数会在组件创建后调用,但是注意组件虽然创建了,但是还没有挂载。 So you won't be able to access the this
of the component.所以你将无法访问组件的
this
。 However, this is a good place to make Network Requests
that will update the data properties.但是,这是进行将更新数据属性的
Network Requests
的好地方。
iii. iii.
mounted
: This function is called once the component has been rendered and the elements can be accessed here. mounted
:一旦组件被渲染并且可以在此处访问元素,就会调用此函数。 This is what you're looking for.这就是你要找的。
iv. iv.
beforeDestroy
: This function is called before the component is destroyed. beforeDestroy
:在组件被销毁之前调用此函数。 This can be useful to stop any listeners (setTimeout, setInterval..), that you created.这对于停止您创建的任何侦听器(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/>
`
})
i.一世。
beforeRouteEnter
: called before the route that renders this component is confirmed. beforeRouteEnter
:在渲染该组件的路由被确认之前调用。 oes NOT have access to this
component instance, because it has not been created yet when this guard is called! oes 无权访问
this
组件实例,因为调用此守卫时它尚未创建!
ii. ii.
beforeRouteUpdate
: called when the route that renders this component has changed, but this component is reused in the new route. beforeRouteUpdate
:当渲染此组件的路由发生变化时调用,但此组件在新路由中被重用。
iii. iii.
beforeRouteLeave
: called when the route that renders this component is about to be navigated away from. beforeRouteLeave
:当渲染该组件的路由即将被导航离开时调用。
References:参考:
VueJS Documentation (LifeCycle): VueJS Instance VueJS 文档(生命周期): VueJS 实例
Vue Router Documentation (Navigation Guards): Navigation Guards Vue路由器文档(导航卫士): 导航卫士
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.