路由 之 初识
一.认识路由
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