Vue-Router

基础内容

`const routes 中的内容`
 {
    path:"",//路径
    name:"",//命名
    component:()=>import(""),//组件
    meta:{},//元对象
    children:[
      // 子路由
    ]
    // 生命周期钩子函数
  }

`RouterView 组件可以使 Vue Router 知道你想要在哪里渲染当前 URL 路径对应的路由组件`

SPA 单页面引用

SSR 服务端渲染
	没有客户端,完全访问服务端,服务端返回html页面
`优势`:获取页面速度快,只需要向服务器做一次请求,可以做SEO搜索引擎优化,SSR渲染意味着有若干个页面,每个页面都可以做SEO优化
`劣势`:点击跳转内容时,需要重新刷新页面

CSR 客户端渲染 
	从服务器中先获取客户端的页面,当点击时访问服务器获取对应的数据,然后根据数据重新渲染当前页面的部分内容
`优势`:不需要刷新页面,局部更新部分内容
`劣势`:先从服务器获取基础页面,然后再次访问服务器获取部分数据,然后再基础页面中渲染,因为只有单页面,所以可以做SEO搜索引擎
优化的部分特别少,基本上无法达到引流的目的

实现简单的跳转

1.App.js 文件还是负责引用文件
2.view下 BaseView.vue 负责视图效果
3.router下 放入对应的路由文件 BaseRouter.ts 用来引入子组件 并且写入routes内容
4.router下 index.js 需要引入BaseRouter.ts 这个路由,并且解构获取BaseRouter的内容
5.components下 还是用来放在文件夹 用来存放子组件

// BaseView.vue
<template>
  <div>
    <router-link to="/">首页</router-link>
    <hr />
    <router-link to="/a">ViewA</router-link>
    <hr />
    <router-link to="/b">ViewB</router-link>
    <router-view />
  </div>
</template>
<script>
</script>

// BaseRouter.ts
import ChildA from '@/components/base/ChildA.vue'
import ChildB from '@/components/base/ChildB.vue'
import MainView from '@/components/base/MainView.vue'
export default [
  {
    path: "/",
    name: "main",
    component: MainView
  },
  {
    path: "/a",
    name: "a",
    component: ChildA
  },
  {
    path: "/b",
    name: "b",
    component: ChildB
  }
]

// index.js
import BaseRouter from "@/router/BaseRouter.ts"
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
const routes = [
  ...BaseRouter
]
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})
// 导出创建的 router
export default router

在组合式和选项式中略有不同

选项式中

1.this.$route 当前路由中带过来的数据
2.this.$router 用来路由跳转的
3.this.$router.push("") 给里面设置路径,就会跳转到对应的路径路由的组件,会添加历史记录
4.this.$router.replace("") 跳转到路径设置的组件,但是不会添加历史记录
5.this.$router.push({name:""}) 设置一个对象,对象里是name,根据name跳转到对应的页面

<script>
// 选项式中
export default {
  name: "App",
  methods: {
    clickHandler1() {
      // this.$router 用来路由跳转的
      console.log(this.$router)
      // this.$route 当前路由中带过来的数据
      console.log(this.$route)

      // 给里面设置路径,就会跳转到对应的路径路由的组件,会添加历史记录
      this.$router.push("/")

      // 设置一个对象,对象里是name,根据name跳转到对应的页面
      this.$router.push({name:"main"})

      // 跳转到路径设置的组件,但是不会添加历史记录
      this.$router.replace("/")
    },
    clickHandler2() {
      // this.$router.push("/a")
      // this.$router.push({name:"a"})
      this.$router.replace("/a")
    },
    clickHandler3() {
      // this.$router.push("/b")
      this.$router.push({name:"b"})
    }
  }
}
</script>

组合式中

<script setup>
// 组合式中

// 可以先直接导入router文件 但是这样获取不到值还时要引入一些内容
// import router from "@/router";
import { useRouter, useRoute, Router, RouteLocationNormalizedLoaded } from "vue-router";

// 获取当前的路由跳转对象
const router = useRouter();
const route=useRoute();

function clickHandler1(){
  router.push("/")
  console.log(route)
}

function clickHandler2(){
  router.push("/a")
}

function clickHandler3(){
  router.push("/b")
}
</script>

路由传参

params传参( 动态路由传参)

`方式1`
// 使用router-link标签  params传参
<router-link to="/">首页</router-link>
<hr />
<router-link to="/a">ViewA</router-link>
<hr />
    
<router-link to="/b/123/nihao">ViewB</router-link>
<router-link :to="{ name: 'b-child', params: { id: '123', name: 'xietian' } }">ViewB</router-link>


`方式2`
1.在路由文件中的 path里要写入传参对应的值的名字 path: "/b/:id/:name",
2.在vue文件中 在需要传参的路由的 router.push中 写传入的值 router.push("/b/123/小波")
3.在当前组件中写入对应文件
// BaseView.vue中
<script setup>
// 组合式中
<button @click="clickHandler3">ViewB</button>

import { useRouter, useRoute, Router, RouteLocationNormalizedLoaded } from "vue-router";

// 获取当前的路由跳转对象
const router = useRouter();
const route = useRoute();

function clickHandler3() {
  // 第一种方式
  router.push("/b/123/小波")

  // 第二种方式 
  router.push({ name: "b-child", params: { id: "123", name: "xiaocha" } })
}

// BaseRouter.ts中(路由文件)
import ChildA from '@/components/base/ChildA.vue'
import ChildB from '@/components/base/ChildB.vue'
import MainView from '@/components/base/MainView.vue'
export default [
  {
    path: "/",
    name: "main",
    component: MainView
  },
  {
    path: "/a",
    name: "a",
    component: ChildA
  },
  {
    path: "/b",
    name: "b",
    component: ChildB
  },
  {
    path: "/b/:id/:name",
    name: "b-child",
    component: ChildB
  }
]

// ChildB.vue中
<template>
  <div>ChildB</div>
</template>

// params传参 
<script setup>
import { useRoute, RouteLocationNormalizedLoaded } from "vue-router";
// 获取到需要传入的值
const route = useRoute();
console.log(route.params);
</script>

`注意点`
1.params传参 只能用来传参字符串
2.因为路由跳转,会将router-view中的组件卸载后,加载一个新的组件放在router-view,这意味着原有的那个组件会被销毁,重新放入时是新的组件

query传参

// 使用query传参,传的参数只能是字符串,对象和数组是无法进行传参
// 若是要传入对象和数组 要转换为JSON字符串,但是一般不会传对象和数组

`方式1`
// 使用router-link  进行 query传参
<RouterLink to="/">首页</RouterLink>
<RouterLink :to="{ name: 'a', query: { name: 'xietian', age: 20} }">按钮1</RouterLink>
<RouterLink to="/b?name=xietian$age=30">按钮2</RouterLink>



1.在vue文件中 在需要传参的路由的 router.push中 写传入的值 router.push("/b/123/小波")
2.在当前组件中写入对应文件		不需在路由文件中的 path里要写入传参对应的值的名字 
`方式2`
// QueryView.vue中
<template>
  <div>
    <div>
      <button @click="clickHandler1">首页</button>
      <button @click="clickHandler2">按钮1</button>
      <button @click="clickHandler3">按钮2</button>
    </div>
    <RouterView />
  </div>
</template>
<script setup>
import { RouterView } from 'vue-router';
import router from "@/router"

function clickHandler1() {
  router.push("/")
}

function clickHandler2() {
  // router.push("/a")
  router.push({ name: "a", query: { name: "lyf", age: 24 } })
}

function clickHandler3() {
  // router.push("/b")
  router.push("/b?name=xt$age=35")
}
</script>

// QueryRouter.ts中(路由文件)
import ChildA from "@/components/query/ChildA.vue"
import ChildB from "@/components/query/ChildB.vue"
import MainView from "@/components/query/MainView.vue"
export default [
  {
    path: "/",
    name: "main",
    component: MainView
  },
  {
    path: "/a",
    name: "a",
    component: ChildA
  },
  {
    path: "/b",
    name: "b",
    component: ChildB
  }
]

// 子组件中(任取一个举例)
<template>
  <div>ChildA</div>
</template>
<script setup>
import { useRoute, RouteLocationNormalizedLoaded } from "vue-router";

const route = useRoute();
console.log(route)
</script>

路由命名

// 可以为任何路由提供 name
	`优点`:没有硬编码的 URL(没写路由的)
		 params 的自动编码/解码
		 防止你在 url 中出现打字错误。
		 绕过路径排序(如显示一个)

命名视图路由

可以在一个路由中修改多个不同的视图容器内容,放入不同的命名路由视图中
// ViewNameView.vue中
<template>
  <div>
    <div>
      <button @click="clickHandler1">首页</button>
      <button @click="clickHandler2">页面1</button>
    </div>
    <div class="div1">
      <RouterView name="left" />
    </div>
    <div class="div1">
      <RouterView name="right" />
    </div>
    <div class="div1">
      <RouterView />
    </div>
  </div>
</template>

<script setup>
import { RouterView } from 'vue-router';
import router from '@/router';

function clickHandler1() {
  router.push("/")
}

// 命名视图路由之后 跳转到/a 可以同时显示出多个路由
function clickHandler2() {
  router.push("/a")
}
</script>
<style lang="stylus">
.div1
  width:300px;
  height:300px;
  border:1px solid #000;
  float:left ;
</style>

// viewName.ts中
import MainView from "@/components/viewName/MainView.vue"
import ChildA from "@/components/viewName/ChildA.vue"
import ChildB from "@/components/viewName/ChildB.vue"
import ChildC from "@/components/viewName/ChildC.vue"
export default [
  {
    path: "/",
    name: "main",
    component: MainView
  },
  {
    path: "/a",
    // name: "a" 路由命名
    name: "a",
    // 这里放在了不同的命名路由视图中 left就是router-view中的name
    // left: ChildA  就是命名路由视图
    components: {
      left: ChildA,
      right: ChildB,
      default: ChildC
    }
  }
]

嵌套路由

`使用过程中一般嵌套两层`

// 在ChildA中 嵌套 ChildB、ChildC
//NextView.vue中
<template>
  <div>
    <div>
      <button @click="clickHandler1">首页</button>
      <button @click="clickHandler2">页面A</button>
    </div>
    <div class="div1">
      <RouterView></RouterView>
    </div>
  </div>
</template>

<script setup>
import { RouterView } from 'vue-router';
import router from '@/router';

function clickHandler1() {
  router.push("/")
}

function clickHandler2() {
  router.push("/a")
}
</script>

<style lang="stylus" scoped>
.div1
  width:500px;
  height:500px;
  border:1px solid #000;
  margin:0 auto
</style>

// ChildA.vue中
<template>
  <div>
    <button @click="clickHandler1">按钮B</button>
    <button @click="clickHandler2">按钮C</button>
    <div class="div2">
      <RouterView></RouterView>
    </div>
  </div>
</template>
<script setup>
import router from '@/router';
// 跳转到/a 下面的 b、c
function clickHandler1(){
  router.push("/a/b")
}

function clickHandler2(){
  router.push("/a/c")
}
</script>

<style lang="stylus" scoped>
.div2
  width:100%;
  height:300px;
  margin-top:50px;
  background-color:rgba(255,0,0,0.2)
</style>

// NextRouter.ts中
import MainView from "@/components/nextView/MainView.vue"
import ChildA from "@/components/nextView/ChildA.vue"
import { RouteLocationNormalized } from "vue-router"

export default [
  {
    path: "/",
    name: "main",
    component: MainView
  },
  {
    path: "/a",
    name: "a",
    component: ChildA,
    // 子路由中的内容会放在父组件的ChildA中routerView中,而不是放在顶层的routerView中
    children: [
      {
        // /a  /的作用是根路由
        // path:"/a/b" 与下面的写法一样
        path: "b",
        name: "b",
        component: ChildB
      },
      {
        path: "c",
        name: "c",
        component: ChildC
      }
    ]
  }
]

路由重定向

{
    path: "/b",
    name: "b",
    // 路由重定向
    redirect:(to)=>{
      // 重定向直接跳转转到/a 下的b中,并传递数据
      return {path:"/a/b",query:to.query}
    }
  }

路由守卫

路由活动的生命周期,都会通过执行一个函数来完成工作,函数都是当时间触发时回调执行的,所以这些函数又叫做钩子函数
路由的生命周期钩子函数,主要在于 当触发路由前,触发路由后执行的,所以叫守卫

`三大类`
1.全局守卫	在router主文件中写入
	全局路由前置守卫	beforeEach		用来决定是否跳转
    //当进入这个路由时,跳出之前触发,必须返回要跳转的路由对象
    
    全局解析守卫	beforeResolve  用来解析数据
    //与beforeEach类似,在beforeEach之后执行
    //所有组件内守卫和异步路由组件被解析之后,解析守卫就被正确调用
    //一般我们可以在这里处理一些数据,比如元数据
    
    全局后置钩子守卫   afterEach
    //路由后置钩子守卫没有next,执行return true
    //当所有跳转完成后执行这个钩子函数 
    //它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用
    
2.路由独享守卫  beforeEnter   在各自的路由配置中写入
    // 在路由前置守卫和路由解析守卫之间执行,还没有跳转路由
    // 这个位置是针对当前这一个路由去执行守卫函数,只针对当前路由完成部分的数据处理等内容

3.组件内守卫  在组件内执行路由守卫
		组件内进入守卫  beforeRouteEnter
		组件内更新守卫  beforeRouteUpdate
		组件内离开守卫  beforeRouteLeave
        
        
`to和from中的内容`
fullPath  //全路径 包括路由路径 hash 和 query
hash  //hash历史记录是才有 #后面的内容
href  //与全路径相似
matched //当前路由父子关系数组,包括父级路由,子级路由
meta   //元数据,用来针对某个路由存储的数据
name  //路由名,可以用来跳转路由
params  //params参数,动态路由的参数
path  //路径,仅有路由路径
query  //query参数,在路由地址?后面的内容
redirectedFrom  //重定向来源路由,从什么路由重定向来的
`使用`
// 全局守卫 在router主文件中写入
1.全局路由前置卫
// 当进入这个路由时,跳转之前触发,必须返回要跳转的路由对象

// to 就是路由将要跳转到的目标路由对象
// from 从什么路由开始跳转,也就是当前还没有跳转的路由对象
// next 是一个函数,当执行next将会继续向目标路由跳转

// 使用场景:当在页面中没有登录的情况下,进入了某些子项,例如购物车,这时候不能跳转到购物车页面,因为没有登录,需要判断当前是否登录,如果没有登录,这时候跳转回登录页面,如果登录过了,就会跳转到购物车页面

// 每次路由跳转,不管任何路由都会进入一次
router.beforeEach((to, from, next) => {
  // next();

  // 如果写成下面的内容,就会当除了跳转a以外的任何路由都是禁止的
  if (to.name !== "a") router.replace("/a")
  else next()
  // 根据以上内容 可以用来在不满足条件时只让页面跳转到登录页面
})

2.全局解析守卫
// 用来解析数据,将数据传递给新的路由中
router.beforeResolve((to, from, next) => {
  console.log("beforeResolve");
  // console.log(to.meta);
  // 在这里进行新数据添加和解析
  if (!to.meta.abc) {
    to.meta.abc = "b"
  }
  console.log(to, from);
  next();
})

3.全局后置钩子守卫
// 路由后置钩子守卫没有next,执行return true
router.afterEach((to, from) => {
  console.log("afterEatch")
  // 表示正常可以跳转到路由部分,我们可以设置一些页面信息,修改title等等
  document.title = to.meta.title
  return true;
})

4.路由独享守卫  放在路由中
beforeEnter: (to, from, next) => {
          // 在路由前置守卫和路由解析守卫之间执行,还没有跳转路由
          // 这个位置是针对当前这一个路由去执行守卫函数,只针对当前路由完成部分的数据处理等内容
          console.log("beforeEnter");
          console.log(to, from, next);
          next();
        }

5.组件内进入守卫  beforeRouteEnter
// 组件进入时触发
  beforeRouteEnter(to, from, next) {
    console.log("beforeRouteEnter");
    next();
  }

6.组件内更新守卫  beforeRouteUpdate
// 当组件时动态路由,路由跳转,页面不刷新时,更新进入  /a/:id   /a/123 --> /a/234  
//													  由a页面下的123页面 跳转至 a页面下的234页面
  beforeRouteUpdate(to, from, next) {
    console.log("beforeRouterUpdate");
    next()
  }

7.组件内离开守卫  beforeRouteLeave
// 导航离开该组件的对应路由时调用,通常用来禁止用户还未保存修改前突然离开
// 当希望阻止用户离开当前页面时,可以调用next(false)
beforeRouteLeave(to, from, next) {
    console.log("beforeRouterLeave");
    next();
  }

完整的路由守卫触发流程

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

路由元信息meta

// 对于某个路由存储信息,存储数据,可以任意信息附加到路由上,如过渡名称、谁可以访问路由等
// 可以在路由地址和导航守卫上都被访问到
// 可以用来权限设置
{
    path: "/login",
    name: "login",
    component: ChildB,
   ` meta: { login: true, user: ["A", "B"] }`
  }

router.beforeEach((to,from,next)=>{
  `if(to.meta.login){
    console.log("这是登录跳转的");
  }`
  next();
})

过渡路由

路由和过渡标签配合使用
`transition不能直接使用在router-view`,因此我们给router-view使用插槽,将返回的组件放在一个动态组件中
// 让每个路由的组件有不同的过渡,你可以将元信息和动态的 name 结合在一起,放在<transition> 上

<router-view #default="{ Component, route }">
      // 获取route内 meta中的transition
	 // 通过名称不同组件显示不同效果
      <transition :name="route.meta.transition">
          // 绑定动态组件
        <component :is="Component"></component>
      </transition>
</router-view>

// meta中存储的transition用于过渡动画的名称,这个名称可以让不同的组件显示时有不同的动画效果
export default [
  {
    path: "/",
    name: "main",
    component: ChildA,
    meta: { transition: "a" }
  },
  {
    path: "/login",
    name: "login",
    component: ChildB,
    meta: { transition: "b" }
  },
  {
    path: "/c",
    name: "c",
    component: ChildC,
    meta: { transition: "c" }
  },
]

路由懒加载

`原因`
如果直接导入,这时候页面开始的时候就会将所有的组件都导入,将会降低首页显示速度,因此,

// 除了第一个默认路径(根路径),其他所有路由都使用懒加载

{
    path: "/c",
    name: "c",
        // 懒加载
    `component: () => import("@/components/metaView/ChildC.vue")`,
    meta: { transition: "c" }
  }

动态创建路由

1.第一步
// 动态创建路由时
// 在全局内写入这个数组
const routeList = [
  '/info/ChildB',
  '/info/ChildC',
  '/sys/ChildD',
  '/film/ChildE'
]

2.`第二步 需要在主路由文件内写以下内容`
router.beforeEach((to, from, next) => {
  // 若
  if (!to.meta.bool) {
    // 获取routeList数组中的每一项-->都是地址
    // path 就是地址 对应每一项item
    // name 通过截取item值获取
    // component 组件名需要使用懒加载 通过item截取获取
    routeList.forEach(item => {
      router.addRoute({
        path: item,
        name: item.split("/").pop(), 
        component: () => import(`@/components/dynamicView/${item.split("/").pop()}`)
      })
    })
    to.meta.bool = true
  }
  next()
})

3.第三步 获取到创建的动态路由并使用
<template>
  <div>
    <div>
// value.path 是要跳转的路径
      <button v-for="(value, key) in list" :key="key" @click="router.push(value.path)">{{ value.name }}</button>
    </div>
    <router-view></router-view>
  </div>
</template>

<script setup>
import router from "@/router/index";
import { reactive } from "vue"

const list = reactive([
  { name: "按钮1", path: "/info/ChildB" },
  { name: "按钮2", path: "/info/ChildC" },
  { name: "按钮3", path: "/sys/ChildD" },
  { name: "按钮4", path: "/film/ChildE" },
])
</script>

路由滚动条

// 写在主路由文件下
// 固定写法
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
    // 这个触发的条件就是当点击回退或者前进时才会回退,重新点击跳转路由时并不会
  `scrollBehavior: (to, from, pos)` => {
    // 这里的pos就是上次的滚动条位置
    if (pos) {
      return pos;
    }
    return { top: 0 }
  }
})

配置404页面

// 在主路由文件内写以下内容
const routes = [
  // ...MetaRouter
  ...DynamicRouter,

  // 配置404页面
`{ path: "/:pathMatch(.*)", component: () => import("@/views/404Page.vue") }`
]

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue RouterVue.js 官方提供的路由管理器。它允许你在 Vue.js 应用中实现单页面应用(SPA)的路由功能。通过使用 Vue Router,你可以定义不同的路由路径和对应的组件,使得在用户访问不同的路径时,能够动态地加载相应的组件内容,实现页面的切换。 Vue Router 提供了路由配置的方式,可以在路由配置中定义各个路径对应的组件,并且可以设置路由参数、路由守卫等。 在 Vue.js 应用中使用 Vue Router 需要先安装依赖包。你可以使用 npm 或 yarn 进行安装,命令如下: ```bash npm install vue-router # 或者 yarn add vue-router ``` 安装完成后,你需要在你的 Vue.js 应用中引入 Vue Router,并在 Vue 实例中使用它。你可以在入口文件(如 main.js)中进行配置,示例代码如下: ```javascript import Vue from 'vue' import VueRouter from 'vue-router' import Home from './components/Home.vue' import About from './components/About.vue' Vue.use(VueRouter) const routes = [ { path: '/', component: Home }, { path: '/about', component: About } ] const router = new VueRouter({ routes }) new Vue({ router, render: h => h(App) }).$mount('#app') ``` 在上面的示例代码中,我们引入了两个组件 Home 和 About,并定义了两个路由路径 '/' 和 '/about' 对应的组件。然后创建了一个 VueRouter 实例,并传入了路由配置。最后,我们将创建的 router 实例传入到 Vue 实例中,使得整个应用具有路由功能。 这只是一个简单的示例,Vue Router 还提供了更多的配置选项和路由功能,比如嵌套路由、命名路由、动态路由等等。你可以查阅 Vue Router 的官方文档来获取更详细的信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值