路由 之 初识
一.认识路由
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文件写内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //配置路由信息 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写内容
1 2 3 4 5 6 7 8 9 10 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <template> <div> <h2>我是首页</h2> <p>我是首页内容</p> </div> </template> <script> export default { name: "Home" , data() { return { message: "张三" , }; }, }; </script> <style></style> |
2>在components文件夹中添加 About.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <template> <div> <h2>我是导航栏</h2> <p>导航栏内容</p> </div> </template> <script> export default { name: "About" , data() { return { message: "张三" , }; }, }; </script> <style></style> |
3>修改index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <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>执行命令
1 | npm run serve |
6>路由的默认值(重定向) 修改index.js的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <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配置一个信息
1 2 3 4 5 | const router = new VueRouter({ mode: "history" , routes, linkActiveClass: "active" , //就这一句代码 }); |
(5)通过代码跳转路由 修改app.vue文件即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <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页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <template> <div> <h2>我是新闻</h2> <p>我是新闻内容</p> </div> </template> <script> export default { name: "HomeNews" , data() { return { message: "张三" , }; }, }; </script> <style></style> |
2>在components添加HomeMessage.vue文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <template> <div> <h2>我是消息</h2> <p>我是消息内容</p> </div> </template> <script> export default { name: "HomeMessage" , data() { return { message: "张三" , }; }, }; </script> <style></style> |
3>修改index.js文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <template> <div> <h2>我是档案</h2> <p>我是档案内容</p> </div> </template> <script> export default { name: "Profile" , data() { return { message: "张三" , }; }, }; </script> <style></style> |
2>配置路由映射 index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | <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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | <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文件
1 2 3 4 5 6 7 8 9 10 11 | 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文件
1 2 3 4 5 | //前置钩子router.beforeEach((to, from, next) => { document.title = to.matched[0].meta.title; console.log(to); next(); }); |
后置钩子:afterEach
全局守卫(上面的代码就是全局守卫)
路由独享守卫
组件内守卫
六.keep-alive
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现