vue路由---基础篇

目录

前端路由和后端路由

Vue Router的使用

vue路由属性

路由的跳转方式

路由动态匹配

响应路由参数的变化

捕获所有路由或 404 Not found 路由

路由的嵌套

路由-二三级路由跳转

路由重定向

路由传参

编程式的导航

动态路由传参

路由-路由抽离


前端路由和后端路由

  • 后端路由:对于普通的网站,所有的超链接都是url地址,所有url都对应服务器上对应的资源
  • 前端路由:对于单页面应用程序来说,主要通过url的hash(#)来实现不同页面的切换,同时hash还有一个特点HTTP请求中不会包含hash相关的内容,所以单页面程序中的页面跳转主要用hash实现

在单页面应用程序中这种通过hash来改变页面的方式称作前端路由区别于后端路由

Vue Router的使用

1、导入vue-router包

2、路由挂载到Vue实例中

3、每个路由规则都是一个对象,这个规则对象身上必须有两个属性

  • 属性1 path表示监听哪个路由链接地址
  • 属性2 component,表示如果路由是前面匹配到的path,则展示component属性对应的组件,component属性值必须是一个组件模板对象,不能是组件的引用名称

4、在控制的div中使用

5、在搜索栏输入对应的匹配规则,login

6、使用vue官方提供的router-link元素使用,它默认渲染为一个a标签

vue路由属性

1、to属性

//vue路由中to属性的作用中做跳转链接,相当于a标签的“href”属性。
<router-link :to="/home">Home</router-link>

<!--渲染结果-->
<a href="/home">Home</a>

2、replace属性

//vue路由中replace属性的作用是页面切换时不会留下历史记录。

<router-link :to="/home"replace></router-link>

3、tag属性

<router-link to="/login" tag="span">登录</router-link>
<router-link to="/register">注册</router-link>

运行程序检查元素,如下图:渲染为一个 span标签了

但是这个 登录 ,依然可以点击切换,说明不管你把它展示成为啥标签,在 router-link内部 或者说 vue-router内部,会永远为它绑定一个点击的触发事件。

4、name属性

一个对象中存在三个属性,分别是代表路径的 path 、代表组件的 component 、以及name。这个 name 属性的意义就在于,我们可以使用这个name 属性来动态的绑定 当前路由,而不是只能跳转固定的 path路径,也就是说,我一旦 给某个路由设置了 name 属性,那么我在跳转路由的时候,如果是通过绑定的 name 属性值 进行跳转,而不是根据绑定的 path 路径来跳转的话,那么,我的跳转就可以是动态的了,即使这个路由的 path 更改了,我的 name也是指向当前更改后的路由

 //配置路由
const routes = [
  { path: '/', name:"indexLink", component: Home },
  { path: '/menu', name:"menuLink", component: Menu },
  { path: '/login', component: Login },
  { path: '/register', component: Register },
  { path: '/admin', component: Admin },
  { path: '/about', component: About },
  { path: '*', redirect:  "/menu" },
]

当我们在定义了 name 属性之后,我们可以使用 绑定的方法 v-bind: 或者 :来在 router-link 的 to 属性中,绑定该路径

<template>
    <header>
        <nav class="navbar navbar-expand-lg navbar-light bg-light">
           <ul class="navbar-nav">
               <li>
                   <router-link :to="{name : 'indexLink'}" class="nav-link" >主页</router-link>
                </li>
               <li>
                   <router-link :to="{name : 'menuLink'}" class="nav-link" >菜单</router-link>
                 </li>
               <li>
                   <router-link to="admin" class="nav-link">管理</router-link>
                </li>
               <li>
                   <router-link to="about" class="nav-link">关于我们</router-link>
                </li>       
           </ul>
           <ul class="navbar-nav ml-auto">
               <li>
                   <router-link to="login" class="nav-link">登录</router-link>
                </li>
               <li>
                   <router-link to="register" class="nav-link">注册</router-link>
                </li>
           </ul>
        </nav>
    </header>
</template>

路由的跳转方式

1、第一种就是我们很熟悉的直接在 router-link 里面 to 属性后接路径,或者是通过路由 name 属性绑定

<li>
   <router-link :to="/" class="nav-link" >主页</router-link>
   <router-link :to="{name : 'indexLink'}" class="nav-link" >主页</router-link>
</li>

2、绑定一个方法,通过方法触发

<template>
    <div>
        <h1>HOME</h1>
        <button @click="goToMenu" class="btn">返回上一次浏览页面</button>
    </div>
</template>
 
<script>
    export default({
        methods: {
            goToMenu(){
                // this指代的是对象 $router是固定方法,go(-1)则是上次浏览页面
                this.$router.go(-1) 
            }
        }
    })
</script>

3、指定跳转的地址:通过replace 方法.通过 replace(),指定需要跳转到的路由的 path 路径

<template>
    <div>
        <h1>HOME</h1>
        <button @click="goToMenu" class="btn">点击跳转</button>
    </div>
</template>
 
<script>
    export default({
        methods: {
            goToMenu(){
            
                this.$router.replace('/menu')
            }
        }
    })
</script>

4、跳转到指定的路由名字下:通过 replace(),指定需要跳转的路由的 name 属性{name:'menuLink'}

template>
    <div>
        <h1>HOME</h1>
        <button @click="goToMenu" class="btn">点击跳转</button>
    </div>
</template>
 
<script>
    export default({
        methods: {
            goToMenu(){
            
                this.$router.replace({name:'menuLink'})
            }
        }
    })
</script>

5、最常用的,push 方法:该方法和replace方法一样,即可 通过路由地址跳转,也可通过路由名字跳转

<template>
    <div>
        <h1>HOME</h1>
        <button @click="goToMenu" class="btn">点击跳转</button>
    </div>
</template>
 
<script>
    export default({
        methods: {
            goToMenu(){
                this.$router.push('/menu')
                 this.$router.push({name:'menuLink'})
            }
        }
    })
</script>

replace 和 push 都能进行路由的 path路径、name属性 跳转,name他们的区别在哪里?

replace:通过replace 跳转的路由,不会存在在浏览器的 历史记录里,只会将需要跳转的路由替换当前的路由

push:通过push 跳转的路由,存在于浏览器的历史记录中,可以通过 浏览器的前进后退按钮。回到之前会之后的路由

路由动态匹配

const User = {
  template: '<div>User</div>'
}

const router = new VueRouter({
  routes: [
    // 动态路径参数 以冒号开头
    { path: '/user/:id', component: User }
  ]
})

现在呢,像 /user/foo 和 /user/bar 都将映射到相同的路由。

一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。于是,我们可以更新 User 的模板,输出当前用户的 ID:

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

你可以在一个路由中设置多段“路径参数”,对应的值都会设置到 $route.params 中。例如:

模式

匹配路径

$route.params

/user/:username

/user/evan

{ username: 'evan' }

/user/:username/post/:post_id

/user/evan/post/123

{ username: 'evan', post_id: '123' }

响应路由参数的变化

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

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

const User = {
  template: '...',
  watch: {
    $route(to, from) {
      // 对路由变化作出响应...
    }
  }
}
const User = {
  template: '...',
  beforeRouteUpdate(to, from, next) {
    // react to route changes...
    // don't forget to call next()
  }
}

捕获所有路由或 404 Not found 路由

常规参数只会匹配被 / 分隔的 URL 片段中的字符。如果想匹配任意路径,我们可以使用通配符 (*):

{
  // 会匹配所有路径
  path: '*'
}
{
  // 会匹配以 `/user-` 开头的任意路径
  path: '/user-*'
}

当使用通配符路由时,请确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。路由 { path: '*' } 通常用于客户端 404 错误。如果你使用了History 模式,请确保正确配置你的服务器

当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:

// 给出一个路由 { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
// 给出一个路由 { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch // '/non-existing'

路由的嵌套

使用children属性实现路由嵌套,子路由path前不要加/,否则永远以根路径开始请求

路由-二三级路由跳转

1、新建项目之后,在 components 文件夹下,新建 about 文件夹

2、引入二级路由,同样的是在main.js 文件下引入,这四个组件都是在 components/about 这个文件夹下,所以路径要写对

//二级路由引入
import Contact from './components/about/Contact'
import Delivery from './components/about/Delivery'
import History from './components/about/History'
import OrderingGuide from './components/about/OrderingGuide'

3、配置二级路由,因为二级路由都是在 about.vue 页面显示的,所以应该写在一级路由 about 的内部,在内部添加一个 children 属性,值为一个数组,数组内部存在多个路由对象,对象内部存在 path 、name、component 三个属性

//配置路由
const routes = [                       
  { path: '/', name:"indexLink", component: Home },
  { path: '/menu', name:"menuLink", component: Menu },
  { path: '/login', name:"loginLink", component: Login },
  { path: '/register', name:"registerLink", component: Register },
  { path: '/admin', name:"adminLink", component: Admin },
  { path: '/about', name:"aboutLink", component: About ,children:[
    { path: '/about/contact', name:'contactLink' , component: Contact },
    { path: './delivery', name:'deliveryLink' , component: Delivery },
    { path: './history', name:'historyLink' , component: History },
    { path: './orderingGuide', name:'orderingGuideLink' , component: OrderingGuide },
  ]},
  { path: '*', redirect:  "/menu" },
]

页面效果:

4、配置3级路由。若是还存在三级路由,那就找到对应页面,在对应页面路由的内部继续引入,我现在是在联系我们内部引入的,所以新建一个文件夹,用来盛放三级路由

5、 重复上述引入二级路由步骤,引入三级路由,注意路由路径。components文件夹下的一级文件,就是一级路由,about文件夹下的一级文件,就是二级路由,contact文件夹下的一级文件,就是三级路由

//三级路由引入
import Phone from './components/about/Contact/Phone'
import PersionName from './components/about/Contact/PersionName'

6、重复上述配置二级路由步骤,配置三级路由

//配置路由
const routes = [    
   // 一级路由                   
  { path: '/', name:"indexLink", component: Home },
  { path: '/menu', name:"menuLink", component: Menu },
  { path: '/login', name:"loginLink", component: Login },
  { path: '/register', name:"registerLink", component: Register },
  { path: '/admin', name:"adminLink", component: Admin },
  { path: '/about', name:"aboutLink", redirect: "/about/contact", component: About ,children:[
   // 二级路由
    { path: '/about/contact', name:'contactLink' ,redirect:"/about/contact/phoneLink", component: Contact ,children:[
       // 三级路由
      { path: '/about/contact/phoneLink',name:"phoneLink", component: Phone },
      { path: './persionNameLink',name:"persionNameLink", component: PersionName }
    ]},
    { path: './delivery', name:'deliveryLink' , component: Delivery },
    { path: './history', name:'historyLink' , component: History },
    { path: './orderingGuide', name:'orderingGuideLink' , component: OrderingGuide },
  ]},
  { path: '*', redirect:  "/menu" },
]

7、二级路由页面。点击切换二级路由

<template>
    <div class="row mb-5">
        <div class="col-4">
            <!-- 导航 -->
            <div class="list-group mb-5">
                <router-link tag="li" :to="{name: 'historyLink'}">
                    <a class="list-group-item list-group-item-action">历史订单</a>
                </router-link>
                <router-link tag="li" :to="{name: 'contactLink'}">
                    <a class="list-group-item list-group-item-action">联系我们</a>
                </router-link>
                <router-link tag="li" :to="{name: 'orderingGuideLink'}">
                    <a class="list-group-item list-group-item-action">点餐文档</a>
                </router-link>
                <router-link tag="li" :to="{name: 'deliveryLink'}">
                    <a class="list-group-item list-group-item-action">快递信息</a>
                </router-link>
            </div>
        </div>
        <div class="col-8">
            <!-- 导航所对应的内容 点击切换对应的二级路由页面 且 展示-->
            <router-view></router-view>
        </div>
    </div>
</template>

8、三级路由页面。点击切换三级路由

<template>
    <div class="card text-dark bg-light mb-3">
        <div class="card-header">联系我们</div>
        <div class="card-body">
            <h4 class="card-title">联系我们</h4>
            <p class="cad-text">3104527996@qq.com</p>
            <div>
                <router-link :to="{name :'phoneLink'}">电话</router-link>
                <router-link :to="{name :'persionNameLink'}">联系人</router-link>
 
                <!-- 点击上面的 router-link 切换对应三级路由 且 展示-->
                <router-view></router-view>
            </div>
        </div>
    </div>
</template>

此时,页面已经可以正常切换二级和三级路由了,但是在二级和三级路由中,没有设置默认显示页面,所以在配置 二级 和 三级 路由时设置 redirect 属性,以此来指定显示的二级 和三级 路由, ps:但是,需要注意的是,在一级路由里指定二级路由时,需要是完全一样的路径,其实path: './delivery', 和 path: '/about/contact', 两个在页面中显示的路径都是一样的,但是指定的时候必须要写成 path: '/about/contact', 这样的

//配置路由
const routes = [                       
  { path: '/', name:"indexLink", component: Home },
  { path: '/menu', name:"menuLink", component: Menu },
  { path: '/login', name:"loginLink", component: Login },
  { path: '/register', name:"registerLink", component: Register },
  { path: '/admin', name:"adminLink", component: Admin },
  { path: '/about', name:"aboutLink", redirect: "/about/contact", component: About ,children:[
      { path: '/about/contact', name:'contactLink' ,redirect:"/about/contact/phoneLink", component: Contact ,children:[
          { path: '/about/contact/phoneLink',name:"phoneLink", component: Phone },
          { path: './persionNameLink',name:"persionNameLink", component: PersionName }
        ]
    },
    { path: './delivery', name:'deliveryLink' , component: Delivery },
    { path: './history', name:'historyLink' , component: History },
    { path: './orderingGuide', name:'orderingGuideLink' , component: OrderingGuide },
  ]},
  { path: '*', redirect:  "/menu" },
]

路径配置时,直接写 /about 类似的就是直接在根目录下的,若是写成 ./delivery 类似的,前面加 . 的,就代表是在当前路径下

路由重定向

路由重定向指的是:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面;通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向:

路由传参

1.如果使用查询字符串 给路由传递参数则不需要修改路由规则的path属性

2.使用query传递参数

3.通过params方式传递路由参数,login后面会被解析为id的值

路由传参分为 params 传参与 query 传参

params 传参类似于网络请求中的 post 请求,params 传过去的参数不会显示在地址栏中(但是不能刷新)。params 只能配合 name 使用,如果提供了 path,params 会失效。

query 传参类似于网络请求中的 get 请求,query 传过去的参数会拼接在地址栏中(?name=xx)。query 较为灵活既可以配合 path 使用,也能配合 name 使用

name是什么呢?name 是配置路由时给 path 取的别名,方便使用。但要注意的是 “地址栏显示的路径始终是 path 的值

name 最重要的一点就是配合 params 进行路由的参数传递。我们来看一个列子:当我们登录之后我们需要把用户名带到主页进行展示。当然方法有许多比如localStorage,sessionStorag,中央事件总线bus,但我们这里需要学习路由传参。


方式一:通过 params 传参


方式二:通过 query 传参

params 传参后,刷新页面会失去拿到的参数。所以路由参数要修改为 '/login/:username'(官方称为动态路由)

但是这样就不会类似于 post 请求,他会把接收到的参数替换作为地址。

假如传入参数为:params: { username: ‘admin’},那么最终访问的地址为:http://localhost:8080/home/admin

总结

  1. 通过登录的例子来看,如果用户名不是敏感信息,可以直接放在地址栏中(使用query参数)
  2. 为什么不用params传参?由于 params 传参不能刷新。或满足刷新需求,但要对地址进行修改,用户名一样会显示在地址栏中

编程式的导航

注意:在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push

想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

当你点击 <router-link> 时,这个方法会在内部调用,所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)。

如果提供了 pathparams 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path

动态路由传参

  1. 直接调用$router.push 实现携带参数的跳转

  1. 配置params

  1. query传递的参数会显示在url后面?id=?

注意: 在子组件中 获取参数的时候是$route.params 而不是$router !!!

路由-路由抽离

路由直接引入在 main.js 文件内部,而main.js 内部还需要引入其他的文件,这就不可避免的造成了main.js内部文件过大,代码过于臃肿,所以,我们需要将引入的路由抽离出来,直接在main.js内部引用这个文件,这样可以大大的缩减main.js内部的代码量

1、新建router.js文件,将路由全部引入这个文件中

//一级路由引入
import Home from './components/Home'
import Menu from './components/Menu'
import Login from './components/Login'
import Register from './components/Register'
import Admin from './components/Admin'
import About from './components/about/About'
 
//二级路由引入
import Contact from './components/about/Contact'
import Delivery from './components/about/Delivery'
import History from './components/about/History'
import OrderingGuide from './components/about/OrderingGuide'
 
//三级路由引入
import Phone from './components/about/Contact/Phone'
import PersionName from './components/about/Contact/PersionName'
 
export const routes = [                       //配置路由
    { path: '/', name:"indexLink", component: Home },
    { path: '/menu', name:"menuLink", component: Menu },
    { path: '/login', name:"loginLink", component: Login },
    { path: '/register', name:"registerLink", component: Register },
    { path: '/admin', name:"adminLink", component: Admin },
    { path: '/about', name:"aboutLink", redirect: "/about/contact", component: About ,children:[
      { path: '/about/contact', name:'contactLink' ,redirect:"/about/contact/phoneLink", component: Contact ,children:[
        { path: '/about/contact/phoneLink',name:"phoneLink", component: Phone },
        { path: './persionNameLink',name:"persionNameLink", component: PersionName }
      ]},
      { path: '/delivery', name:'deliveryLink' , component: Delivery },
      { path: '/history', name:'historyLink' , component: History },
      { path: '/orderingGuide', name:'orderingGuideLink' , component: OrderingGuide },
    ]},
    { path: '*', redirect:  "/menu" },
  ]

或者:

我们将路由文件单离出来放在 routes.js 之后,在mian.js 是不能直接引用的,因为我们还没有释放这个 配置的路由,所以,在配置路由的 const 声名之前,添加 export 来释放已配置的路由,使其可以全局调用

2、在main.js内部调用该路由文件,使用的也是import引入方法

import Vue from 'vue'
 
import VueRouter from 'vue-router'   
 
import App from './App'
 
import  routes  from './routes'       //引入路由文件
 
 
Vue.config.productionTip = false
 
Vue.use(VueRouter)                    //使用路由
 
 
const router = new VueRouter({        //实例化路由对象,将routes配置的路由放进去
  routes,                             //传递routes路由数组
  mode : "history"                    //干掉浏览器#
})
 
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,     //将 路由 挂载到根实例对象中 需要通过router 配置参数注入路由
  components: { App },
  template: '<App/>'
})

3、如果是侧边菜单栏的话,可以这样组成路由文件

3.1、在src目录下,新建一个routers文件夹,该文件夹下,新建一个index.js文件,用来盛放所有路由

3.2、对于左侧的菜单,可以针对每个菜单新建一个路由文件,然后将这个菜单的二级、三级路由,全部引入到这个文件,然后export 将其暴露出来

import Container from "@/layout/container"
 
const servicePage = [
  {
    path: "/businessmanage",
    component: Container,
    meta: {
      title: "企业管理",
      icon: "el-icon-s-claim",
      menuShow: true
    },
    children: [
      {
        path: "/businessmanage",
        component: () => import("@/views/Businessmanage/Businessmanage"),
        name: "企业信息",
        meta: {
          title: "企业信息"
        },
        show: true
      },
      {
        path: "/businesslist",
        component: () => import("@/views/Businessmanage/Businesslist"),
        name: "企业账户列表",
        meta: {
          title: "企业账户列表"
        },
        show: true
      },
      {
        path: "/balancelist",
        component: () => import("@/views/Businessmanage/balancelist.vue"),
        name: "账户余额列表",
        meta: {
          title: "账户余额列表"
        },
        show: true
      },
      {
        path: "/graderank",
        component: () => import("@/views/Businessmanage/graderank.vue"),
        name: "企业等级配置",
        meta: {
          title: "企业等级配置"
        },
        show: true
      }
    ]
  }
]
 
export default servicePage

3.3、对于每个菜单,都新建一个文件,且每个文件都将其暴露出来,以供引用

3.4、在index.js文件中,引入这些文件,作为二级路由,在children中引入,且 使用数组扩展运算符,将其展开。将组合的路由数组,暴露出来

import Vue from "vue"
import Router from "vue-router"
import Layout from "@/layout/Layout"
import HomePage from "./modules/home"
import Dataversion from "./modules/dataversion"
import management from "./modules/management"
import Franchisee from "./modules/franchisee"
import order from "./modules/order"
import marketTools from "./modules/marketTools"
import subCommission from "./modules/subCommission"
import setup from "./modules/setup"
 
// 重写push方法 解决重复点击相同路由报错
const routerPush = Router.prototype.push
Router.prototype.push = function push(location) {
  return routerPush.call(this, location)
}
 
Vue.use(Router)
export const constantRouterMap = [
  {
    path: "/",
    redirect: "/home",
    component: Layout,
    children: [...HomePage, ...management, ...Franchisee, ...Dataversion, ...order, ...setup, ...marketTools, ...subCommission],
    hidden: true
  }
]
 
const router = new Router({
  mode: "history",
  routes: constantRouterMap
})
 
export default router

3.5、在main.js文件中,引入这个index.js文件,且挂载到根组件上

import Vue from "vue"
import App from "./App.vue"
import router from "./router/index"
import store from "./store"
import "@/assets/iconfont/iconfont.css"
import "@/style/index.less"
import "./permission"
 
Vue.config.productionTip = false
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount("#app")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值