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 中⾃动降级
  • ⾃定义的滚动条⾏为

使用

先说一下安装吧。

安装

npm install vue-router

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

Vue.use(VueRouter)

创建和挂载根实例。

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

动态路由匹配

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

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

    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 来获取这些参数。

    <!-- 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 进行编程式导航,传递不同的动态参数来匹配不同的路径。

    // 编程式导航
    this.$router.push('/user/123');
    

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

5.响应路由参数的变化

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

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

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

或者使用 beforeRouteUpdate 导航守卫:

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

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

嵌套路由

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

/user/foo/profile                     /user/foo/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

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

  1. 路由配置:

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

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

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

  2. 组件中的使用:

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

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

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

  3. 编程式导航:

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

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

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

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

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

    <!-- 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 属性定义多个组件。

    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 等选项的对象。

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

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

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

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

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

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

// 后退一步
this.$router.go(-1);

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

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

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

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

直接指定路径进行导航。

this.$router.push('/user/123');

注意事项

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

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

命名路由

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

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

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

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

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

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

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

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

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

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

获取当前路由的名称

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

// 获取当前路由的名称
const currentRouteName = this.$route.name;

为何使用命名路由

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

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

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

重定向和别名

重定向(Redirects)

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

在路由配置中使用重定向

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

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

重定向函数

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

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

重定向的使用场景:

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

别名(Alias)

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

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

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

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

别名函数:

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

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 对象传递给路由组件。

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

const routes = [
  {
    path: '/user/:id',
    component: User,
  },
];

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

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

2. 查询参数

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

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

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

3. 状态管理(Vuex)

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

在路由组件中使用 Vuex 状态

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

4. Props

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

在路由配置中启用 props

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

在路由组件中接收 props

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

5. 路由元信息(Meta)

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

在路由配置中定义元信息

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

在路由组件中接收元信息

// 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)

  • 注意事项:
    • 无法中断导航,因为它在导航完成后触发。
    • 不能修改导航的结果。
  • 使用场景:
    • 页面埋点:在每个导航完成后执行埋点逻辑。
    • 日志记录:记录用户的访问记录。
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
  • 使用场景:
    • 特定路由的权限验证:对某个路由独立进行权限验证
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)

    • 注意事项:
      • 在离开当前路由时触发。
      • 适用于需要在离开组件前执行清理操作的场景。
    • 使用场景:
      • 在用户离开编辑页面时,弹出确认框询问是否保存未提交的数据
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 字段添加路由元信息。例如:

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

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

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

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

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

在组件中使用路由元信息

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

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>包裹需要过渡的元素。
<transition name="fade">
  <!-- 这里是需要过渡的元素 -->
  <div v-if="show" class="box">
    Content to be transitioned
  </div>
</transition>
  1. 定义过渡效果样式: 在样式表中定义过渡效果的相关样式。
/* 定义过渡效果的样式 */
.fade-enter-active, .fade-leave-active {
  transition: opacity 1s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}
  1. JavaScript钩子函数: 使用<transition>组件提供的JavaScript钩子函数来处理过渡的不同阶段。
<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参数,用于控制滚动行为。

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属性,分别表示水平和垂直方向的滚动位置。

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 }; // 使用保存的位置,或者滚动到顶部
  }
}

示例

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),则滚动到相应的元素。如果有保存的位置,使用保存的位置进行滚动。如果没有保存的位置,滚动到页面顶部。

原文链接:https://juejin.cn/post/7332410158268153897 作者:DoraBigHead

(0)
上一篇 2024年2月7日 下午4:41
下一篇 2024年2月7日 下午4:52

相关推荐

发表回复

登录后才能评论