路由 之 初识

一.认识路由

 1.路由:就是通过互联的网络吧信息从源地址输到目的地的活动  --维基百科

2.后端路由阶段:

   一个页面有自己对应的网址,即url,url会发送到服务器 ,服务器通过正则对该url进行匹配,并最后交给一个controller进行处理,controller最终生成html或者数据,返回给前端,这就完成了一个I/0操作

  缺点:前端开发人员进行开发,需要懂后端语言才行

          html代码和对应的逻辑混在一起,编写和维护非常的糟糕.

3.前后端分离路由阶段

  随着ajax,有了前后端分离的开发模式,前端通过ajax请求得到的数据,通过js将数据渲染.这样后端专注数据,前端专注交互和可视化,并且移动端出现后,后端不需要任何处理,还是之前使用的一套api即可

4.单页面应用阶段

  其实SPA最主要的特点就是在前后端分离基础上添加了一层前端路由,也就是前端来维护一套路由规则.

5.前端路由的核心

  改变url,但是页面不进行整体的刷新

 url发生改变是,页面不刷新,而是将 codewhy.com (html+css+js全部资源) 中属于该url部分的相关内容渲染出来

二.vue-router基本使用

 (1)安装vue-router

npm i vue-router --save

(2)在模块化工程中使用它(因为是一个插件,所以可以通过Vue.use()来安装路由功能)

  第一步:导入路由对象,并且调用Vue.use(VueRouter)

  第二步:创建路由实例,并且传入路由映射配置

  第三步:在vue实例中挂载创建的路由实例

具体操作代码和文件

1>在vue项目中的src中添加router文件夹,在router添加index.js文件

2>index.js文件写内容

//配置路由信息
import VueRouter from "vue-router";
import Vue from "vue";

//1.通过vue.use(插件),安装插件
Vue.use(VueRouter);

//2.创建VueRouter对象
const routes = [];
const router = new VueRouter({
  //配置路由和组件之间的应用关系
  routes,
});

//3.将router对象传入到vue实例中
export default router;

3>main.js写内容

import Vue from "vue";
import App from "./App.vue";
import router from "./router/index"; // './router' 这样会自动找到index.js

Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App),
  router: router,
}).$mount("#app");

(3)使用vue-router的步骤 映射配置和呈现

  第一步:创建路由组件

  第二步:配置路由映射,组件和路径映射关系

  第三步:使用路由:通过<router-link>和<router-view>  

具体操作代码和文件

1>在components文件夹中添加 Home.vue

<template>
  <div>
    <h2>我是首页</h2>
    <p>我是首页内容</p>
  </div>
</template>
<script>
export default {
  name: "Home",
  data() {
    return {
      message: "张三",
    };
  },
};
</script>
<style></style>

2>在components文件夹中添加 About.vue  

<template>
  <div>
    <h2>我是导航栏</h2>
    <p>导航栏内容</p>
  </div>
</template>
<script>
export default {
  name: "About",
  data() {
    return {
      message: "张三",
    };
  },
};
</script>
<style></style>

3>修改index.js

import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../components/Home.vue";
import About from "../components/About.vue";

//1.通过vue.use安装插件
Vue.use(VueRouter);

//2.创建vuerouter对象
const routes = [
  {
    path: "/home",
    component: Home,
  },
  {
    path: "/about",
    component: About,
  },
];
const router = new VueRouter({
  routes,
});

export default router;

4>修改App.vue文件

<template>
  <div id="app">
    <router-link to="/home">首页</router-link>
    <router-link to="/about">导航</router-link>
    <router-view></router-view>  //用于占位
  </div>
</template>

<script>
// import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

5>执行命令

npm run serve

6>路由的默认值(重定向) 修改index.js的内容

const routes = [
  {
    path: "",
    redirect: "/home",  //重定向
 //path:''
//component:Home  这样写的确可以加载,但是网页的路径并没有修改,所以采用重定向
  },
  {
    path: "/home",d
    component: Home,
  },
  {
    path: "/about",
    component: About,
  },
];

7>修改为history模式

   路由默认的是hash模式,那么在 浏览器上默认是有 "#"的:例如     http://localhost:8080/#/home

   修改index.js文件

  

import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../components/Home.vue";
import About from "../components/About.vue";

//1.通过vue.use安装插件
Vue.use(VueRouter);

//2.创建vuerouter对象
const routes = [
  {
    path: "",
    redirect: "/home",
  },
  {
    path: "/home",
    component: Home,
  },
  {
    path: "/about",
    component: About,
  },
];
const router = new VueRouter({
  mode: "history",   //添加这部分内容
  routes,
});

export default router;

  

(4)router-link的其他属性补充

  router-link在vue中默认渲染的是a标签

<router-link to="/home" tag="button" replace  active-class="active"></router-link>

to:指定跳转路径
tag:将router-link渲染为button标签
      若没有该属性,默认是a标签
replace:不会留下history记录,所以指定replace情况下,浏览器的前进后退键是不能返回到上一个页面中的
active-class="active"

//没有看到任何效果
style{
       active:{
         color:red    
      }
}

 那么 active-class="active"不需要了,可以通过在index.js配置一个信息

const router = new VueRouter({
  mode: "history",
  routes,
  linkActiveClass: "active",//就这一句代码
});

(5)通过代码跳转路由 修改app.vue文件即可

<template>
  <div id="app">
    <!-- <router-link to="/home" replace>首页</router-link>
    <router-link to="/about" replace>导航</router-link> -->
    <button @click="homeClick">首页</button>
    <button @click="aboutClick">关于</button>
    <router-view></router-view>
  </div>
</template>

<script>
// import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  methods: {
    //通过代码的方式来修改路径
    homeClick() {
      //所有的组件都有一个属性:router  来自vue-router
      this.$router.push("/home");
//this.$router.replace('/home') 这个操作就相当于上面 router-link 的replace的属性作用 }, aboutClick() { this.$router.push("/about"); }, }, }; </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } .active { color: "red"; } </style>

 重点:this.$router 相当于index.js中 new VueRouter实例

           this.$route 表示的是那个路由处于活跃状态:表示 index.js页面中 routes的 哪个path是活跃的

(6)vue-router动态路由的使用 (也是传参的一种方式)

 分析:为什么要动态路由,原因是若进入的home,about页面都是开放的,可是登录user(用户界面时),那么路径就是 /user/zhangsan ,表示是张三登录的

1/修改index.js页面

import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../components/Home.vue";
import About from "../components/About.vue";
import User from "../components/User.vue";

//1.通过vue.use安装插件
Vue.use(VueRouter);

//2.创建vuerouter对象
const routes = [
  {
    path: "",
    redirect: "/home",
  },
  {
    path: "/home",
    component: Home,
  },
  {
    path: "/about",
    component: About,
  },
  {
    path: "/user/:abc",  //表示是谁登录了用户界面
    component: User,
  },
];
const router = new VueRouter({
  mode: "history",
  routes,
});

export default router;

  

2> 添加User.vue页面

<template>
  <div>
    <h2>用户</h2>
    <p>这是用户</p>
    <p>{{ $route.params.abc }}</p>
    <!-- <p>{{ userid }}</p> -->
  </div>
</template>
<script>
export default {
  name: "User",
  data() {
    return {
      message: "用户信息",
    };
  },
  computed: {
    userid() {
      return this.$route.params.abc;
    },
  },
};
</script>
<style></style>

3>修改App.vue

<template>
  <div id="app">
    <!-- <router-link to="/home" replace>首页</router-link>
    <router-link to="/about" replace>导航</router-link> -->
    <!-- <button @click="homeClick">首页</button>
    <button @click="aboutClick">关于</button>
    <button></button> -->
    <router-link to="/home" replace>首页</router-link>
    <router-link to="/about" replace>关于</router-link>
    <router-link :to="'/user/' + userid" replace>用户</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
// import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  data() {
    return {
      userid: "张三",
    };
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.active {
  color: "red";
}
</style>

重点:this.$route 表示的是那个路由处于活跃状态:表示 index.js页面中 routes的 哪个path是活跃的 

(7)路由的懒加载

官方给出的解释:

      当打包构建时,js包会非常大,影响页面加载,那么把不同路由对应的组件分割成不同的代码块,那么当路由被访问的时候才加载,这样就更高效

分析官方的解释:

      路由通常定义很多页面

      一般情况下,很多页面放在一个js文件中,会造成index.html这个页面非常大

      一次性从服务器请求下来的页面,可能需要花费一定的时间,甚至会出现短暂的空白

懒加载做了啥?

     路由懒加载主要作用是将路由对应的组件打包成一个个js代码块

     只有这个路由被访问时,才加载对应的组件

懒加载的方式(如图)

重构index.js文件

import Vue from "vue";
import VueRouter from "vue-router";
// import Home from "../components/Home.vue";
// import About from "../components/About.vue";
// import User from "../components/User.vue";

const Home = () => import("../components/Home.vue");
const About = () => import("../components/About.vue");
const User = () => import("../components/User.vue");
//1.通过vue.use安装插件
Vue.use(VueRouter);

//2.创建vuerouter对象
const routes = [
  {
    path: "",
    redirect: "/home",
  },
  {
    path: "/home",
    component: Home,
  },
  {
    path: "/about",
    component: About,
  },
  {
    path: "/user/:abc",
    component: User,
  },
];
const router = new VueRouter({
  mode: "history",
  routes,
});

export default router;

  

重点: npm run build  会多生成三个js文件,因为一个懒加载文件就会生成一个js文件

三.vue-router嵌套路由

 (1)认识嵌套路由

 (2)通过home/news   和 home/message 路径访问

1>在components添加HomeNews.vue文件

<template>
  <div>
    <h2>我是新闻</h2>
    <p>我是新闻内容</p>
  </div>
</template>
<script>
export default {
  name: "HomeNews",
  data() {
    return {
      message: "张三",
    };
  },
};
</script>
<style></style>

2>在components添加HomeMessage.vue文件 

<template>
  <div>
    <h2>我是消息</h2>
    <p>我是消息内容</p>
  </div>
</template>
<script>
export default {
  name: "HomeMessage",
  data() {
    return {
      message: "张三",
    };
  },
};
</script>
<style></style>

3>修改index.js文件

import Vue from "vue";
import VueRouter from "vue-router";
// import Home from "../components/Home.vue";
// import About from "../components/About.vue";
// import User from "../components/User.vue";

const Home = () => import("../components/Home.vue");
const HomeNews = () => import("../components/HomeNews.vue"); //添加的内容
const HomeMessage = () => import("../components/HomeMessage.vue"); //添加的内容
const About = () => import("../components/About.vue");
const User = () => import("../components/User.vue");
//1.通过vue.use安装插件
Vue.use(VueRouter);

//2.创建vuerouter对象
const routes = [
  {
    path: "",
    redirect: "/home",
  },
  {
    path: "/home",
    component: Home,
    children: [
      { path: "", redirect: "news" },
      {
        path: "news",
        component: HomeNews,
      },
      {
        path: "message",
        component: HomeMessage,
      },
    ],
  },
  {
    path: "/about",
    component: About,
  },
  {
    path: "/user/:abc",
    component: User,
  },
];
const router = new VueRouter({
  mode: "history",
  routes,
});

export default router;

4>修改home.vue文件

<template>
  <div>
    <h2>我是首页</h2>
    <p>我是首页内容</p>
    <router-link to="/home/news" replace>新闻</router-link>
    <router-link to="/home/message" replace>消息</router-link>
    <router-view></router-view>
  </div>
</template>
<script>
export default {
  name: "Home",
  data() {
    return {
      message: "张三",
    };
  },
};
</script>
<style></style>

  

四.vue-router参数传递

(1)传递参数的方式

   第一种:params  

        配置路由格式:/router/:id

        传递的方式:在path后面跟上对应的值 <router-link :to=" '/home/' +变量名  ">

        传递后形成的路径:/router/123,router/abc

  第二种:query

         配置路由格式:/router,也就是普通的配置

         传递的方式:对象中使用query的key作为传递方式

        传递后形成的路径:/router?id=123,/router?id=abc

演示传递参数,创建新的组件,以下步骤

 第一步:创建新的组件Profile.vue

第二步:配置路由映射

第三步:添加跳转的<router-link>

1>components文件夹添加Profile.vue文件

<template>
  <div>
    <h2>我是档案</h2>
    <p>我是档案内容</p>
  </div>
</template>
<script>
export default {
  name: "Profile",
  data() {
    return {
      message: "张三",
    };
  },
};
</script>
<style></style>

2>配置路由映射 index.js

import Vue from "vue";
import VueRouter from "vue-router";
// import Home from "../components/Home.vue";
// import About from "../components/About.vue";
// import User from "../components/User.vue";

const Home = () => import("../components/Home.vue");
const HomeNews = () => import("../components/HomeNews.vue");
const HomeMessage = () => import("../components/HomeMessage.vue");
const About = () => import("../components/About.vue");
const User = () => import("../components/User.vue");
const Profile = () => import("../components/Profile.vue");
//1.通过vue.use安装插件
Vue.use(VueRouter);

//2.创建vuerouter对象
const routes = [
  {
    path: "",
    redirect: "/home",
  },
  {
    path: "/home",
    component: Home,
    children: [
      { path: "", redirect: "news" },
      {
        path: "news",
        component: HomeNews,
      },
      {
        path: "message",
        component: HomeMessage,
      },
    ],
  },
  {
    path: "/about",
    component: About,
  },
  {
    path: "/user/:abc",
    component: User,
  },
  {
    path: "/profile",
    component: Profile,
  },
];
const router = new VueRouter({
  mode: "history",
  routes,
});

export default router;

3>App.vue文件

 

<template>
  <div id="app">
    <!-- <router-link to="/home" replace>首页</router-link>
    <router-link to="/about" replace>导航</router-link> -->
    <!-- <button @click="homeClick">首页</button>
    <button @click="aboutClick">关于</button>
    <button></button> -->
    <router-link to="/home" replace>首页</router-link>
    <router-link to="/about" replace>关于</router-link>
    <router-link :to="'/user/' + userid" replace>用户</router-link>
    <!-- <router-link to="/profile">档案</router-link> -->
    <router-link :to="{ path: '/profile', query: { name: 'why', age: 18 } }"  //这里用的是query
      >档案</router-link
    >
    <router-view></router-view>
  </div>
</template>

<script>
// import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  data() {
    return {
      userid: "张三",
    };
  },
  methods: {
    //通过代码的方式来修改路径
    homeClick() {
      //所有的组件都有一个属性:router  来自vue-router
      this.$router.push("/home");
    },
    aboutClick() {
      this.$router.push("/about");
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.active {
  color: "red";
}
</style>

  

4>需改profile文件

<template>
  <div>
    <h2>我是档案</h2>
    <p>我是档案内容</p>
    <p>{{ $route.query.name }}</p>
  </div>
</template>
<script>
export default {
  name: "Profile",
  data() {
    return {
      message: "张三",
    };
  },
};
</script>
<style></style>

5>修改app.vue文件

<template>
  <div id="app">
    <!-- <router-link to="/home" replace>首页</router-link>
    <router-link to="/about" replace>导航</router-link> -->
    <!-- <button @click="homeClick">首页</button>
    <button @click="aboutClick">关于</button>
    <button></button> -->
    <router-link to="/home" replace>首页</router-link>
    <router-link to="/about" replace>关于</router-link>
    <router-link :to="'/user/' + userid" replace>用户</router-link>
    <!-- <router-link to="/profile">档案</router-link> -->
    <router-link :to="{ path: '/profile', query: { name: 'why', age: 18 } }"
      >档案</router-link
    >
    <router-view></router-view>
  </div>
</template>

<script>
// import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  data() {
    return {
      userid: "张三",
    };
  },
  methods: {
    //通过代码的方式来修改路径
    homeClick() {
      //所有的组件都有一个属性:router  来自vue-router
      this.$router.push("/home");
    },
    aboutClick() {
      this.$router.push("/about");
    },
    profileClick() {
      this.router.push({
        path: "/profile",
        query: {
          name: "profile",
          age: 18,
          height: 1.87,
        },
      });
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.active {
  color: "red";
}
</style>

五.vue-router导航守卫

为什么要使用导航守卫?

网页标题是通过title来显示但是只有一个固定的HTML,切换不同的页面时,标题并不会改变

但是可以通过js来修改title内容,window.document.title ='新的标题'

第一种通过代码来实现

(1)修改home.vue文件

export default {
  name: "Home",
  data() {
    return {
      message: "张三",
    };
  },
  created() {
    document.title = "首页"; //这一部分
  },
};

(2)修改index.js文件

import Vue from "vue";
import VueRouter from "vue-router";
// import Home from "../components/Home.vue";
// import About from "../components/About.vue";
// import User from "../components/User.vue";

const Home = () => import("../components/Home.vue");
const HomeNews = () => import("../components/HomeNews.vue");
const HomeMessage = () => import("../components/HomeMessage.vue");
const About = () => import("../components/About.vue");
const User = () => import("../components/User.vue");
const Profile = () => import("../components/Profile.vue");
//1.通过vue.use安装插件
Vue.use(VueRouter);

//2.创建vuerouter对象
const routes = [
  {
    path: "",
    redirect: "/home",
  },
  {
    path: "/home",
    component: Home,
    children: [
      { path: "", redirect: "news" },
      {
        path: "news",
        component: HomeNews,
      },
      {
        path: "message",
        component: HomeMessage,
      },
    ],
  },
  {
    path: "/about",
    component: About,
  },
  {
    path: "/user/:abc",
    component: User,
  },
  {
    path: "/profile",
    component: Profile,
  },
];
const router = new VueRouter({
  mode: "history",
  routes,
});

router.beforeEach((to, from, next) => {
  document.title = to.matched[0].meta.title;
  console.log(to);
  next();
});

export default router;

第二种:通过配置来实现 

{
    path: "/about",
    component: About,
    meta: {
      title: "关于",
    },
  },

index.js文件

//前置钩子
router.beforeEach((to, from, next) => { document.title = to.matched[0].meta.title; console.log(to); next(); }); 

 后置钩子:afterEach

   全局守卫(上面的代码就是全局守卫) 

          路由独享守卫

         组件内守卫

六.keep-alive

原文地址:https://www.cnblogs.com/zmztya/p/14438232.html