vue-router 3.X 讲解

最近小哆啦在学习之余,发现自己在vue-router中有好多不了解的知识点,小哆啦决定梳理一遍vue-router3.x

参考资料:Vue Router (vuejs.org)

说起前端路由有些朋友可能会问什么是路由?何为前端路由?

小哆啦查阅资料之后发现其实最开始提出路由这个概念的是后端,是来跟后端服务器进行交互的一种方式,通过不同的路径,来请求不同的资源,请求不同的页面是路由的其中一种功能。

前端随着 ajax 的流行,数据请求可以在不刷新浏览器的情况下进行。异步交互体验中最盛行的就是 SPA ------ 单页应用。单页应用不仅仅是在页面交互时无刷新的,连页面跳转都是无刷新的,为了实现单页应用,所以就有了前端路由。

前端路由是指在单页面应用(SPA)中,通过JavaScript来管理应用的不同视图之间的导航。

vue-router是什么

这里的路由并不是指我们平时所说的硬件路由器,这里的路由就是SPA(单页应用)的路径管理器 。再通俗的说,vue-router就是WebApp的链接路径管理系统。 vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。传统的页面应用,是用一些超链接来实现页面切换和跳转的。在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换。路由模块的本质 就是建立起url和页面之间的映射关系至于我们为啥不能用a标签,这是因为用Vue做的都是单页应用,就相当于只有一个主的index.html页面,所以你写的标签是不起作用的,你必须使用vue-router来进行管理。

介绍

Vue Router是Vue.js官方的路由管理器。它和 Vue.js 的核⼼深度集成,让构建单⻚⾯应⽤变得易如反掌。包含的功能有:

  • 动态路由匹配
  • 嵌套的路由/视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过渡系统的视图过渡效果
  • 细粒度的导航控制
  • 带有⾃动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中⾃动降级
  • ⾃定义的滚动条⾏为

使用

先说一下安装吧。

安装

js 复制代码
npm install vue-router

如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能:

js 复制代码
Vue.use(VueRouter)

创建和挂载根实例。

JS 复制代码
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
  router
}).$mount('#app')

动态路由匹配

动态路由匹配是 Vue Router 中非常强大且灵活的功能,它允许你在路由配置中定义带有动态部分的路径,并根据这些动态部分动态渲染组件或执行逻辑。

  1. 路由配置 在路由配置中使用冒号 : 来表示动态的部分,这部分会被当作参数添加到 $route.params 对象中。

    javascript 复制代码
    const routes = [
      {
        path: '/user/:id',
        component: User,
        props: true, // 将$route.params作为组件的props传递
        children: [
          {
            path: 'profile',
            component: UserProfile,
          },
          {
            path: 'posts',
            component: UserPosts,
          },
        ],
      },
    ];

    上述例子中,/user/:id 定义了一个动态路由,:id 是动态的部分,例如 /user/123。路由还包含了两个子路由:/user/:id/profile/user/:id/posts

  2. 组件中的使用 在匹配到动态路由时,路由参数会自动添加到 $route.params 对象中,可以在组件中通过 $route.params 来获取这些参数。

    vue 复制代码
    <!-- User.vue -->
    
    <template>
      <div>
        <h2>User Page</h2>
        <p>User ID: {{ $route.params.id }}</p>
    
        <!-- 匹配子路由时,子组件会渲染到这里 -->
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    export default {
      // 组件逻辑
    };
    </script>

    在这个例子中,$route.params.id 就是动态路由中的参数,例如当访问 /user/123 时,$route.params.id 就是 123

  3. 嵌套路由 动态路由和嵌套路由可以结合使用,形成更复杂的路由结构。在上述的路由配置中,/user/:id 下包含了两个子路由:/user/:id/profile/user/:id/posts。这种嵌套结构可以更好地组织和管理不同层次的页面。

  4. 编程式导航 在组件中,你可以使用 $router.push 进行编程式导航,传递不同的动态参数来匹配不同的路径。

    javascript 复制代码
    // 编程式导航
    this.$router.push('/user/123');

    这样的导航会触发动态路由的匹配,并在组件中更新相应的参数。

5.响应路由参数的变化

当使用路由参数时,例如从 /user/foo 导航到 /user/bar原来的组件实例会被复用 。因为两个路由都渲染同个组件,比起销毁再 创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用

复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象:

js 复制代码
const User = {
  template: '...',
  watch: {
    $route(to, from) {
      // 对路由变化作出响应...
    }
  }
}

或者使用 beforeRouteUpdate 导航守卫:

js 复制代码
const User = {
  template: '...',
  beforeRouteUpdate(to, from, next) {
    // react to route changes...
    // don't forget to call next()
  }
}

有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:路由定义得越早,优先级就越高。

嵌套路由

嵌套路由是指在 Vue Router 中,一个路由可以包含另一个路由,形成一个嵌套的关系。这种嵌套的结构使得你可以更好地组织和管理复杂的页面布局,其中某些部分的渲染是由子路由处理的。例如:

text 复制代码
/user/foo/profile                     /user/foo/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

借助 vue-router,使用嵌套路由配置,就可以很简单地表达这种关系。

  1. 路由配置:

    在路由配置中,通过 children 属性定义子路由。

    javascript 复制代码
    const routes = [
      {
        path: '/dashboard',
        component: Dashboard,
        children: [
          {
            path: 'profile',
            component: UserProfile,
          },
          {
            path: 'posts',
            component: UserPosts,
          },
        ],
      },
    ];

    在上述配置中,/dashboard 路由下包含了两个子路由:/dashboard/profile/dashboard/posts

  2. 组件中的使用:

    在父组件中通过 <router-view> 标签来指定子路由的渲染位置。

    vue 复制代码
    <!-- Dashboard.vue -->
    
    <template>
      <div>
        <h2>Dashboard</h2>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    export default {
      // 父组件逻辑
    };
    </script>

    当访问 /dashboard 时,Dashboard 组件会渲染,并在 <router-view> 处渲染当前活动的子路由。

  3. 编程式导航:

    在父组件中使用 $router.push 进行导航到子路由。

    javascript 复制代码
    // 编程式导航到子路由
    this.$router.push('/dashboard/profile');
  4. 嵌套子路由的组件:

    在子路由对应的组件中,可以通过 $route 对象来访问路由参数。

    vue 复制代码
    <!-- UserProfile.vue -->
    
    <template>
      <div>
        <h3>User Profile</h3>
        <p>User ID: {{ $route.params.id }}</p>
      </div>
    </template>
    
    <script>
    export default {
      // 子路由组件逻辑
    };
    </script>
  5. 命名视图(Named Views):

    对于复杂的布局,你可以使用命名视图来同时渲染多个视图。

    vue 复制代码
    <!-- Dashboard.vue -->
    
    <template>
      <div>
        <h2>Dashboard</h2>
        <router-view name="profile"></router-view>
        <router-view name="posts"></router-view>
      </div>
    </template>
    
    <script>
    export default {
      // 父组件逻辑
    };
    </script>

    在路由配置中,使用 components 属性定义多个组件。

    javascript 复制代码
    const routes = [
      {
        path: '/dashboard',
        components: {
          default: Dashboard,
          profile: UserProfile,
          posts: UserPosts,
        },
      },
    ];

    每个命名视图对应于一个具体的子路由。

通过这些方式,嵌套路由使得你可以更好地组织和管理复杂的页面结构,使得代码结构清晰,可维护性更强。

编程式的导航

编程式导航是指通过代码来实现路由的切换,而不是通过用户的导航行为(如点击链接)触发路由的变化。Vue Router 提供了一些方法用于编程式导航,常用的方法包括 $router.push$router.replace$router.go 等。

编程式导航方法 声明式导航对应方式
$router.push 方法: <router-link to="/user/123">User Profile</router-link>
$router.replace 方法: <router-link :to="..." replace>
$router.go 方法: 通常不直接有对应的声明式导航方式,用于在导航历史中前进或后退
  1. $router.push 方法

$router.push 方法用于导航到一个新的 URL。它接受一个包含 pathqueryparams 等选项的对象。

javascript 复制代码
this.$router.push({ path: '/user/123', query: { name: '张三' } });

在组件内部,你可以这样使用:

javascript 复制代码
// 在组件中使用 $router.push
methods: {
  navigateToUserPage() {
    this.$router.push({ name: 'user', params: { id: 123 } });
  }
}
  1. $router.replace 方法

$router.replace 方法与 $router.push 类似,但是它不会在导航历史中留下新的记录,而是替换当前的历史记录。

javascript 复制代码
this.$router.replace({ path: '/user/123', query: { name: '张三' } });
  1. $router.go 方法

$router.go 方法用于在导航历史中前进或后退指定步数。

javascript 复制代码
// 后退一步
this.$router.go(-1);

// 前进一步
this.$router.go(1);
  1. 使用命名路由

在路由配置中定义了命名路由,可以通过名称进行导航。

javascript 复制代码
// 在路由配置中定义命名路由
const routes = [
  { path: '/user/:id', name: 'user', component: User },
];

// 在组件中使用命名路由
this.$router.push({ name: 'user', params: { id: 123 } });
  1. 使用路由路径

直接指定路径进行导航。

javascript 复制代码
this.$router.push('/user/123');

注意事项

  • 在组件内部可以通过 this.$router 访问路由实例。
  • 在使用编程式导航时,确保目标路径是有效的,并且对应的组件已经在路由配置中定义。
  • 使用编程式导航时,可以携带路由参数、查询参数等信息,具体取决于路由配置的定义。

编程式导航通常在用户进行某些操作后触发,例如提交表单、点击按钮等。在这些情况下,你可以使用编程式导航来实现页面的切换。

命名路由

命名路由是在 Vue Router 中给路由配置指定一个名称的方式。通过给路由对象添加 name 属性,你可以为路由起一个简短、有意义的名字。命名路由在编程式导航和声明式导航中都很有用。

在路由配置中使用命名路由

javascript 复制代码
const routes = [
  {
    path: '/user/:id',
    name: 'user',
    component: User,
  },
  {
    path: '/dashboard',
    name: 'dashboard',
    component: Dashboard,
  },
];

在上述路由配置中,userdashboard 就是命名路由的名称。

声明式导航中使用命名路由

在模板中使用 <router-link> 时,可以通过 to 属性指定命名路由:

html 复制代码
<router-link :to="{ name: 'user', params: { id: 123 }}">User Profile</router-link>

编程式导航中使用命名路由

在组件内部,你可以使用 $router.push$router.replace$router.go 等方法中的 name 属性进行编程式导航:

javascript 复制代码
// 编程式导航到命名路由
this.$router.push({ name: 'user', params: { id: 123 } });

获取当前路由的名称

在组件内部,可以通过 $route.name 获取当前路由的名称:

javascript 复制代码
// 获取当前路由的名称
const currentRouteName = this.$route.name;

为何使用命名路由

  1. 可读性和维护性: 使用命名路由可以使代码更具可读性和维护性,尤其在大型应用中,通过名称而不是路径来标识路由更容易理解。

  2. 灵活性: 使用命名路由可以在不改变路由路径的情况下修改路由配置,而不会影响到使用该路由的地方。

  3. 动态路径参数: 命名路由可以更方便地处理动态路径参数,如 :id

重定向和别名

重定向(Redirects)

重定向是指在路由匹配时将用户重定向到另一个路径。在 Vue Router 中,可以通过 redirect 属性实现重定向。

在路由配置中使用重定向

javascript 复制代码
const routes = [
  {
    path: '/',
    redirect: '/home', // 将根路径重定向到 /home
  },
  {
    path: '/home',
    component: Home,
  },
  {
    path: '/dashboard',
    redirect: '/home', // 将 /dashboard 重定向到 /home
  },
];

在上述示例中,如果用户访问根路径 /,将被重定向到 /home;如果用户访问 /dashboard,同样会被重定向到 /home

重定向函数

你还可以使用一个函数来动态计算重定向目标。函数接收 to 路由对象作为参数,你可以基于当前的路由状态动态地决定重定向目标。

javascript 复制代码
const routes = [
  {
    path: '/admin',
    redirect: to => {
      // 动态计算重定向目标
      if (isAdminUser()) {
        return '/admin/dashboard';
      } else {
        return '/login';
      }
    },
  },
  // ...
];

重定向的使用场景:

  • 默认首页: 重定向常用于将用户导航到默认首页。例如,将根路径 / 重定向到 /home
  • 路由重构: 在进行路由结构调整或优化时,可以使用重定向确保用户访问旧路径时被正确导向到新路径,而不会导致404错误。
  • 动态条件重定向: 可以使用函数来动态计算重定向目标,根据用户的状态或权限进行条件性的重定向。

别名(Alias)

别名是指为路由创建额外的路径,而不改变该路由的实际路径。这在需要提供多个路径访问同一组件的情况下很有用。在 Vue Router 中,可以通过 alias 属性实现别名。

在路由配置中使用别名:****

javascript 复制代码
const routes = [
  {
    path: '/about',
    component: About,
    alias: '/about-us', // 创建别名,/about-us 也会访问 About 组件
  },
  {
    path: '/contact',
    component: Contact,
  },
];

在上述示例中,当用户访问 /about/about-us 时,都会渲染 About 组件。

别名函数:

别名也可以是一个函数,允许你动态计算别名路径。

javascript 复制代码
const routes = [
  {
    path: '/admin',
    component: Admin,
    alias: to => {
      // 动态计算别名路径
      return `/dashboard${to.path}`;
    },
  },
  // ...
];

通过使用别名和重定向,你可以更灵活地配置路由,适应不同的导航需求和场景。这些功能允许你以一种更动态和可扩展的方式管理路由。

重定向的使用场景:

  • 默认首页: 重定向常用于将用户导航到默认首页。例如,将根路径 / 重定向到 /home
  • 路由重构: 在进行路由结构调整或优化时,可以使用重定向确保用户访问旧路径时被正确导向到新路径,而不会导致404错误。
  • 动态条件重定向: 可以使用函数来动态计算重定向目标,根据用户的状态或权限进行条件性的重定向。

结合使用场景

  • 权限控制: 通过结合使用重定向和别名,可以实现基于用户权限的导航控制。例如,用户未登录时重定向到登录页面,同时提供别名以确保旧路径的兼容性。
  • 路由模块化: 当应用结构较为庞大,路由配置较为复杂时,可以使用别名和重定向来模块化路由配置,提高可维护性。
  • A/B 测试: 在进行 A/B 测试时,可以使用别名为不同版本提供不同路径,而不改变实际路由逻辑。

路由组件传参

在 Vue Router 中,路由组件传参有多种方式,主要包括动态路径参数、查询参数、状态管理(如 Vuex)、props 和路由元信息等。下

1. 动态路径参数

动态路径参数是指在路由路径中使用冒号 : 定义的参数,这些参数会被 Vue Router 解析并作为 $route.params 对象传递给路由组件。

在路由配置中定义动态路径参数

javascript 复制代码
const routes = [
  {
    path: '/user/:id',
    component: User,
  },
];

在路由组件中接收动态路径参数

javascript 复制代码
// User.vue
export default {
  mounted() {
    // 获取动态路径参数
    const userId = this.$route.params.id;
    console.log('User ID:', userId);
  },
};

2. 查询参数

查询参数是指在 URL 中使用 ? 后跟的键值对,通过 $route.query 对象传递给路由组件。

在路由组件中接收查询参数

javascript 复制代码
// User.vue
export default {
  mounted() {
    // 获取查询参数
    const queryParam = this.$route.query.param;
    console.log('Query Parameter:', queryParam);
  },
};

3. 状态管理(Vuex)

Vuex 是 Vue.js 的状态管理库,通过 Vuex 可以实现全局状态的管理,从而在不同的组件中传递数据。

在路由组件中使用 Vuex 状态

javascript 复制代码
// 在路由组件中使用 Vuex 状态
export default {
  computed: {
    // 从 Vuex 获取状态
    userName() {
      return this.$store.state.user.name;
    },
  },
};

4. Props

可以通过 props 将路由参数传递给组件。在路由配置中使用 props: true,然后在组件中通过 props 接收参数。

在路由配置中启用 props

javascript 复制代码
const routes = [
  {
    path: '/user/:id',
    component: User,
    props: true, // 启用 props
  },
];

在路由组件中接收 props

javascript 复制代码
// User.vue
export default {
  props: ['id'],
  mounted() {
    // 在组件中使用 props
    console.log('User ID:', this.id);
  },
};

5. 路由元信息(Meta)

可以通过路由元信息传递额外的信息给路由组件。

在路由配置中定义元信息

javascript 复制代码
const routes = [
  {
    path: '/user/:id',
    component: User,
    meta: { requiresAuth: true },
  },
];

在路由组件中接收元信息

javascript 复制代码
// User.vue
export default {
  beforeRouteEnter(to, from, next) {
    // 获取元信息
    const requiresAuth = to.meta.requiresAuth;
    console.log('Requires Auth:', requiresAuth);

    // 使用 next 函数接收参数,可在组件实例创建前访问组件实例
    next(vm => {
      // 在组件实例内部使用元信息
      console.log('Inside Component - Requires Auth:', vm.$route.meta.requiresAuth);
    });
  },
};

注意

  1. 动态路径参数: 动态路径参数会在 URL 中展示,例如 /user/123 中的 123
  2. 查询参数: 查询参数会在 URL 中展示,例如 /user?id=123 中的 id=123
  3. 状态管理(Vuex): Vuex 状态不会直接在 URL 中展示。 Vuex 是用于在整个应用中共享状态的,不会影响当前路由的 URL。
  4. Props: Props 通过组件的属性传递,不会在 URL 中展示,如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。
  5. 路由元信息(Meta): 路由元信息不会直接在 URL 中展示。它是附加在路由配置中的元信息,用于在路由组件内部访问附加信息,而不会影响 URL。

路由守卫

导航守卫(Navigation Guards)是 Vue Router 提供的一组用于在路由导航过程中进行控制的钩子函数。这些钩子函数允许你在导航到某个路由之前或之后执行一些逻辑,例如进行权限验证、取消导航、修改路由参数等。

Vue Router 提供了三种导航守卫:

  1. 全局导航守卫: 这些守卫影响所有路由,包括全局 beforeEachbeforeResolveafterEach
  2. 路由独享的守卫: 这些守卫只会影响单个路由,可以在路由配置中使用 beforeEnter
  3. 组件内的守卫: 这些守卫只会影响某个组件,包括 beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave

1. 全局导航守卫

beforeEach(to, from, next)

  • 注意事项:
    • 必须调用 next() 才能继续导航,否则路由会被中断。
    • 如果多次调用 next(),导航会按照调用的顺序执行。
  • 使用场景:
    • 权限验证:在每个路由导航前检查用户是否有权限访问。
    • 页面切换动画:在导航前执行一些动画效果。

beforeResolve(to, from, next)挺讨厌66用由于用咿咿呀呀咿咿呀呀一样一样咿呀咿呀呦也有一家他v'b'b'v'c'b'n'n'b'v'c't'yvbbvcbnnbvcty

  • 注意事项:
    • 通常用于异步路由组件的解析,一般情况下不需要特别关注。
  • 使用场景:
    • 在确认导航前解析异步组件,确保组件在导航完成时已经加载完毕。

afterEach(to, from)

  • 注意事项:
    • 无法中断导航,因为它在导航完成后触发。
    • 不能修改导航的结果。
  • 使用场景:
    • 页面埋点:在每个导航完成后执行埋点逻辑。
    • 日志记录:记录用户的访问记录。
javascript 复制代码
const router = new VueRouter({
  routes: [...],
});

router.beforeEach((to, from, next) => {
  // 在路由导航前执行逻辑,例如权限验证
  if (to.meta.requiresAuth && !userLoggedIn()) {
    next('/login');
  } else {
    next();
  }
});

router.beforeResolve((to, from, next) => {
  // 在导航被确认之前执行逻辑,例如解析异步路由组件
  resolveAsyncComponent(to, next);
});

router.afterEach((to, from) => {
  // 在每个导航完成后执行逻辑,例如埋点
  trackPageView(to.path);
});

2. 路由独享的守卫

beforeEnter(to, from, next)

  • 注意事项:
    • 必须调用 next() 才能继续导航,否则路由会被中断。
    • 在这个守卫中无法访问组件实例 this
  • 使用场景:
    • 特定路由的权限验证:对某个路由独立进行权限验证
javascript 复制代码
const routes = [
  {
    path: '/dashboard',
    component: Dashboard,
    beforeEnter: (to, from, next) => {
      // 在进入路由前执行逻辑
      if (isAdmin()) {
        next();
      } else {
        next('/login');
      }
    },
  },
];

3. 组件内的守卫

  • beforeRouteEnter(to, from, next)

    • 注意事项:
      • 由于在导航前触发,因此无法直接访问组件实例 this
      • 必须通过 next 回调函数中的参数访问组件实例。
    • 使用场景:
      • 需要在组件进入前执行逻辑,例如在进入前弹出确认框。

    beforeRouteUpdate(to, from, next)

    • 注意事项:
      • 在组件复用时触发。
      • 适用于需要在路由更新时执行逻辑,如重新请求数据。
    • 使用场景:
      • 在路由更新时,例如从 /user/1 切换到 /user/2,需要重新加载用户数据。

    beforeRouteLeave(to, from, next)

    • 注意事项:
      • 在离开当前路由时触发。
      • 适用于需要在离开组件前执行清理操作的场景。
    • 使用场景:
      • 在用户离开编辑页面时,弹出确认框询问是否保存未提交的数据
javascript 复制代码
export default {
  beforeRouteEnter(to, from, next) {
    // 在进入该组件前执行逻辑,不能访问组件实例
    if (userNeedsConfirmation()) {
      next(vm => {
        // 可以访问组件实例
        vm.showConfirmationDialog();
      });
    } else {
      next();
    }
  },
  beforeRouteUpdate(to, from, next) {
    // 在路由更新但是复用该组件时触发
    // 例如,可以在这里重新请求组件数据
    fetchData();
    next();
  },
  beforeRouteLeave(to, from, next) {
    // 在离开当前路由时触发
    // 可以执行一些清理操作
    cleanup();
    next();
  },
};

next总结

  • next() 用于继续导航。
  • next(false) 用于中断导航。
  • next('/path') 用于重定向到指定路径。
  • next(error) 用于中断导航并处理错误。
  • next(vm => {}) 用于在组件实例创建后执行逻辑。

完整的导航解析流程

  1. 导航被触发: 当用户点击页面中的链接或通过编程式导航(router.pushrouter.replace等)时,导航被触发。
  2. 触发全局前置守卫: 所有注册的全局 beforeEach 导航守卫被调用。这是在任何路由改变之前执行的全局守卫,用于执行一些全局的任务,例如权限验证。
  3. 触发路由独享的守卫: 对于目标匹配到的路由,执行它们独享的 beforeEnter 导航守卫。这是在全局守卫之后、路由独享守卫之前执行的守卫。
  4. 触发解析异步组件: 如果目标路由包含异步加载的组件,会触发 beforeResolve 导航守卫,用于解析异步组件。
  5. 触发全局解析守卫: 所有注册的全局 beforeResolve 导航守卫被调用。这是在路由解析完成之前执行的守卫。
  6. 导航被确认: 调用 next() 表示导航被确认,可以继续。如果在上述步骤中没有中断导航的情况下,导航将被确认。
  7. 更新视图: 导航被确认后,Vue Router 会更新视图,将新的组件渲染到页面中。
  8. 触发全局后置守卫: 所有注册的全局 afterEach 导航守卫被调用。这是在视图更新之后执行的全局守卫,用于执行一些全局的任务,例如页面埋点。

路由元信息

路由元信息是 Vue Router 提供的一种机制,用于在路由配置中附加一些额外的信息。这些信息可以在导航守卫和组件内部使用,为路由的管理和控制提供了更多的灵活性。

在路由配置中添加路由元信息

在每个路由对象中,可以通过 meta 字段添加路由元信息。例如:

javascript 复制代码
const routes = [
  {
    path: '/dashboard',
    component: Dashboard,
    meta: {
      requiresAuth: true, // 用于权限验证
      title: 'Dashboard Page', // 用于设置页面标题
    },
  },
  // 其他路由配置...
];

在导航守卫中使用路由元信息

在导航守卫中,可以通过路由对象的 meta 字段访问路由元信息。例如:

javascript 复制代码
router.beforeEach((to, from, next) => {
  // 获取路由元信息
  const requiresAuth = to.meta.requiresAuth;

  // 在导航前进行权限验证
  if (requiresAuth && !userLoggedIn()) {
    next('/login');
  } else {
    next();
  }
});

在组件中使用路由元信息

在组件内部,可以通过访问路由对象的 meta 字段来获取路由元信息。例如:

javascript 复制代码
export default {
  created() {
    // 获取路由元信息
    const pageTitle = this.$route.meta.title;
    document.title = pageTitle || 'Default Page Title';
  },
};

常见的路由元信息用途

  1. 权限验证: 使用 requiresAuth 之类的标志来表示该路由需要登录权限。

  2. 页面标题: 使用 title 字段来表示页面的标题,方便在导航守卫和组件中设置页面标题。

  3. 面包屑导航: 在路由元信息中添加用于生成面包屑导航的信息。

  4. 布局控制: 在路由元信息中添加布局相关的信息,例如是否显示侧边栏、顶部栏等。

过渡动效

过渡动效在Vue.js中是通过<transition>组件实现的,它基于CSS过渡和一些JavaScript钩子函数。:

过渡动效的原理

  1. 过渡类名的生成: 过渡类名是由<transition>组件的name属性生成的,这个属性定义了过渡类名的前缀。例如,如果name设置为"fade",则相关的过渡类名将是"fade-enter"、"fade-enter-active"、"fade-enter-to"等。

  2. 触发时机: 过渡动效分为进入(enter)和离开(leave)两个阶段。这些阶段是在元素插入或从DOM中移除时触发的,通常通过v-ifv-show或动态组件进行切换。

  3. CSS过渡类名: Vue会自动根据状态为元素添加或移除相应的CSS类名,这些类名可以用于定义过渡效果。常见的类名有.enter-active-class.leave-active-class.enter-class.leave-class等。

过渡动效的使用

  1. 基本结构: 使用<transition>包裹需要过渡的元素。
vue 复制代码
<transition name="fade">
  <!-- 这里是需要过渡的元素 -->
  <div v-if="show" class="box">
    Content to be transitioned
  </div>
</transition>
  1. 定义过渡效果样式: 在样式表中定义过渡效果的相关样式。
css 复制代码
/* 定义过渡效果的样式 */
.fade-enter-active, .fade-leave-active {
  transition: opacity 1s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}
  1. JavaScript钩子函数: 使用<transition>组件提供的JavaScript钩子函数来处理过渡的不同阶段。
vue 复制代码
<script>
export default {
  data() {
    return {
      show: true,
    };
  },
  methods: {
    toggleShow() {
      this.show = !this.show;
    },
  },
};
</script>

在上述代码中,toggleShow方法用于切换show的值,触发元素的进入或离开过渡。

这样,当你改变show的值时,Vue会自动添加或移除相应的CSS类名,并根据定义的样式产生过渡效果。通过结合CSS和JavaScript钩子函数,你可以灵活地实现各种过渡动效。

在Vue Router中,可以通过使用滚动行为(Scroll Behavior)来定义页面切换时的滚动效果。滚动行为可以控制路由切换时页面的滚动位置,使用户在导航之间保持流畅的滚动体验。

滚动行为

在Vue Router中配置滚动行为需要在创建VueRouter实例时传递scrollBehavior选项。这个选项是一个函数,接收tofrom两个路由对象,以及savedPosition参数,用于控制滚动行为。

javascript 复制代码
const router = new VueRouter({
  routes: [
    // 定义你的路由
  ],
  scrollBehavior(to, from, savedPosition) {
    // 返回期望滚动到的位置
    if (savedPosition) {
      return savedPosition;
    } else {
      return { x: 0, y: 0 };
    }
  },
});

Scroll Behavior 函数参数

滚动行为的函数接收三个参数:

  • to:表示即将进入的路由对象。
  • from:表示即将离开的路由对象。
  • savedPosition:只有在通过浏览器的前进/后退按钮触发导航时才可用。保存了在浏览器历史记录中当前导航前的滚动位置。

Scroll Behavior 函数返回值

滚动行为函数应该返回一个对象,表示期望滚动到的位置。这个对象可以包含xy属性,分别表示水平和垂直方向的滚动位置。

javascript 复制代码
scrollBehavior(to, from, savedPosition) {
  // 通过 to.path 来判断是否进入了指定的路由
  if (to.path === '/about' && from.path === '/home') {
    return { x: 0, y: 0 }; // 滚动到顶部
  } else {
    return savedPosition || { x: 0, y: 0 }; // 使用保存的位置,或者滚动到顶部
  }
}

示例

javascript 复制代码
const router = new VueRouter({
  routes: [
    // 定义你的路由
  ],
  scrollBehavior(to, from, savedPosition) {
    if (to.hash) {
      // 如果路由带有 hash 值,滚动到目标元素
      return { selector: to.hash };
    } else if (savedPosition) {
      // 如果有 savedPosition,从保存的位置滚动
      return savedPosition;
    } else {
      // 默认滚动到页面顶部
      return { x: 0, y: 0 };
    }
  },
});

在这个例子中,如果路由带有哈希值(例如#section1),则滚动到相应的元素。如果有保存的位置,使用保存的位置进行滚动。如果没有保存的位置,滚动到页面顶部。

相关推荐
10年前端老司机1 小时前
什么!纯前端也能识别图片中的文案、还支持100多个国家的语言
前端·javascript·vue.js
摸鱼仙人~1 小时前
React 性能优化实战指南:从理论到实践的完整攻略
前端·react.js·性能优化
程序员阿超的博客2 小时前
React动态渲染:如何用map循环渲染一个列表(List)
前端·react.js·前端框架
magic 2452 小时前
模拟 AJAX 提交 form 表单及请求头设置详解
前端·javascript·ajax
小小小小宇7 小时前
前端 Service Worker
前端
只喜欢赚钱的棉花没有糖7 小时前
http的缓存问题
前端·javascript·http
小小小小宇8 小时前
请求竞态问题统一封装
前端
loriloy8 小时前
前端资源帖
前端
源码超级联盟8 小时前
display的block和inline-block有什么区别
前端
GISer_Jing8 小时前
前端构建工具(Webpack\Vite\esbuild\Rspack)拆包能力深度解析
前端·webpack·node.js