Skip to content

47.Vue-Router 有几种钩子函数,具体是什么及执行流程是怎样的?

  • 导航被触发。
  • 在失活的组件里调用 beforeRouteLeave 守卫。
  • 调用全局的 beforeEach 守卫。
  • 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  • 在路由配置里调用 beforeEnter。
  • 解析异步路由组件。
  • 在被激活的组件里调用 beforeRouteEnter。
  • 调用全局的 beforeResolve 守卫 (2.5+)。
  • 导航被确认。
  • 调用全局的 afterEach 钩子。
  • 触发 DOM 更新。
  • 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

模拟守卫运行

js
// 1.实现sleep方法用于延迟
async function sleep(n = 1000) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, n);
  });
}
// 2.模拟离开钩子
const routeLeaveGuards = [
  () => {
    console.log("leave1");
    return sleep(3000);
  },
  () => {
    console.log("leave2");
  },
];
// 3.模拟进入钩子
const beforeEachGuards = [
  (next) => {
    console.log("each1");
    setTimeout(() => {
      next();
    }, 10000);
  },
  () => {
    console.log("each2");
  },
];
// 4.当前要运行的钩子,将钩子转化成promise
let guards = [];
function guardToPromiseFn(guard) {
  return () =>
    new Promise((resolve, reject) => {
      const next = resolve;
      let guardReturn = guard(next);
      Promise.resolve(guardReturn).then(next);
    });
}
for (let guard of routeLeaveGuards) {
  guards.push(guardToPromiseFn(guard));
}
// 5.组合钩子
function runGuardQueue(guards) {
  return guards.reduce(
    (promise, guard) => promise.then(() => guard()),
    Promise.resolve()
  );
}
runGuardQueue(guards).then(() => {
  guards = [];
  for (let guard of beforeEachGuards) {
    guards.push(guardToPromiseFn(guard));
  }
  return runGuardQueue(guards);
});
// 1.实现sleep方法用于延迟
async function sleep(n = 1000) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, n);
  });
}
// 2.模拟离开钩子
const routeLeaveGuards = [
  () => {
    console.log("leave1");
    return sleep(3000);
  },
  () => {
    console.log("leave2");
  },
];
// 3.模拟进入钩子
const beforeEachGuards = [
  (next) => {
    console.log("each1");
    setTimeout(() => {
      next();
    }, 10000);
  },
  () => {
    console.log("each2");
  },
];
// 4.当前要运行的钩子,将钩子转化成promise
let guards = [];
function guardToPromiseFn(guard) {
  return () =>
    new Promise((resolve, reject) => {
      const next = resolve;
      let guardReturn = guard(next);
      Promise.resolve(guardReturn).then(next);
    });
}
for (let guard of routeLeaveGuards) {
  guards.push(guardToPromiseFn(guard));
}
// 5.组合钩子
function runGuardQueue(guards) {
  return guards.reduce(
    (promise, guard) => promise.then(() => guard()),
    Promise.resolve()
  );
}
runGuardQueue(guards).then(() => {
  guards = [];
  for (let guard of beforeEachGuards) {
    guards.push(guardToPromiseFn(guard));
  }
  return runGuardQueue(guards);
});

源码执行流程解析

Released under the MIT License.