lua 服务器
服务端路由
服务端路由时指的是服务器根据用户访问的 URL 路径返回不同的响应结果。
在传统的服务端渲染的 web 应用中点击一个链接时,浏览器会从服务端获得全新的 HTML页面,然后重新加载整个页面。
然而,在单页面应用中,客户端的 JavaScript 可以拦截页面的跳转请求,动态获取新的数据,无需重新加载的情况下更新当前页面。
这样通常可以带来更顺滑的用户体验,尤其是在更偏向“应用”的场景下,因为这类场景下用户通常会在很长的一段时间中做出多次交互。
在这类单页应用中,“路由”是在客户端执行的。一个客户端路由器的职责就是利用诸如 History API 或是 hashchange 事件这样的浏览器 API 来管理应用当前应该渲染的视图。
路由的应用场景:
单页面应用(SPA应用):
路由
监听浏览器 hashchange 事件实现路由
如果你只需要一个简单的页面路由,而不想为此引入一整个路由库,你可以通过动态组件的方式,监听浏览器 hashchange 事件或使用 History API 来更新当前组件。
<script> import About from "./components/About.vue"; import Home from "./components/Home.vue"; import NotFound from "./components/Not Found.vue"; const routes = { //路由默认跳转到Home组件 '/': Home, '/about': About } export default { data() { return { currentPath: window.location.hash } }, computed: { //计算属性的方法,响应式的,缓存 currentView() { //过滤#,匹配路由 return routes[this.currentPath.slice(1) || '/' ] || NotFound } }, mounted() { window.addEventListener('hashchange', () => { //只要window变化了就,把当前的路径给App组件下的属性this.currentPath this.currentPath = window.location.hash }) } } </script> <template> <a href="#/">Home</a> | <a href="#/about">About</a> | <a href="#/non-existent-path">Broken Link</a> <br> <component :is="currentView" /> </template>使用Vue Router+Vue2实现路由
用 Vue + Vue Router 创建单页应用非常简单:通过 Vue.js,我们已经用组件组成了我们的应用。当加入 Vue Router 时,我们需要做的就是将我们的组件映射到路由上,让 Vue Router 知道在哪里渲染它们。
1.安装路由
npm i vue-router@3注意:
vue3对应的vue-router版本是4
vue2对应的vue-router版本是3
我这里是vue2
2.导入VueRouter插件(main.js)
import Vue from 'vue' import App from './App.vue' import VueRouter from "vue-router" import './assets/main.css' //关闭vue的生产提示 Vue.config.productionTip = false //使用路由器插件 Vue.use(VueRouter) new Vue({ render: (h) => h(App), }).$mount('#app')3.编写创建路由器router(并暴露)的js文件(router/index.js)
import VueRouter from "vue-router"; import Home from "../components/Home"; import About from "../components/About"; import NotFound from "../components/Not Found"; //创建路由器并暴露 export default new VueRouter({ //多个路由 routes:[ { path:'/about', component:About }, { path:'/Home', component:Home } ] })4.引入router(main.js)
import router from "./router"; new Vue({ render: (h) => h(App), router:router }).$mount('#app')5. 使用router-link激活路由以及路由视图的展示
<template> <div> <h1>Router Demo</h1> <router-link to="/home">Home</router-link>|| <router-link to="/about">About</router-link> <router-view></router-view> </div> </template>注意点
路由嵌套
现在定制一个需求
当我点击Home路由组件的时候,我希望它再来一个嵌套的路由。因此我们就需要对Home组件也进行路由的激活和视图展示:
那么新增了两个子路由,对应的,就必须去路由器添加:
export default new VueRouter({ //多个路由 routes:[ { path:'/about', component:About }, { path:'/home', component:Home, children:[ { path:'message', component:Message }, { path:'news', component:News } ] } ] })children属性作为子路由的拓展,值得注意的是子路由的path下不能像父级路由那样添加/,因为vue-router底层的只要匹配到children属性,就会帮我们省略这一步骤。
路由传参
假如我现在有这么一个需求
当我点击哪个message,就显示哪个message的信息。
于是我们需要在嵌套一个三级子路由,并且由于对象格式相同,我们可以放到一个新的组件里,然后利用路由传参实现。
1.定义一个新的组Details.vue
2. 配置路由
export default new VueRouter({ //多个路由 routes:[ { path:'/about', component:About }, { path:'/home', component:Home, children:[ { path:'message', component:Message, children:[ { path :'details', component:Details } ] }, { path:'news', component:News } ] } ] })3.Message组件下以对象格式传参
<template> <div> <ul> <li v-for="m in messageList" :key="m.id"> <router-link :to="{ path:'/home/message/details', query:{ id:m.id, title:m.title } }"> {{ m.title }} </router-link> </li> </ul> <router-view></router-view> </div> </template> <script> export default { name: "Message", data() { return { messageList: [ {id: 1, title: "message01"}, {id: 2, title: "message02"}, {id: 3, title: "message03"}, ] } } } </script>在Message组件下创建属性messageList集合,然后通过v-for遍历它并且显示在列表标签内,最后用router-link :to可以携带一个对象,path:url路径,query:参数。注意query的值也必须是一个对象格式的。
4.Details.vue取参数进行回显
<template> <ul> <li>消息编号:{{$route.query.id}}</li> <li>消息标题:{{$route.query.title}}</li> </ul> </template>路由优化
路由命名name
<router-link :to="{ path:'/home/message/details', query:{ id:m.id, title:m.title } }"> {{ m.title }} </router-link>在开发环境中,如果我们真的用path属性去表示路由的路径,这实在过于冗余,因此可以在路由器的配置下做手脚:每一个路由可以有一个唯一的名字,供name属性引用
{ path:'message', component:Message, children:[ { name:'link_detail', path :'details', component:Details } ] },那么routeLink下的:to的值便不再需要path属性,而是用name来表示路由的名字。
<router-link :to="{ name:'Link_detail', query:{ id:m.id, title:m.title } }"> {{ m.title }} </router-link>利用路由params实现ResultFul风格请求
由于query属性是一对key-value的形式作为携带的参数。
如果想要实现ResultFul的请求方式,也就是说在url上隐藏key的显示,只显示value,也没有?和&作为分割。
更为简洁的写法::to表示里面只能是对象 ``用表示里面的只能是字符串,因此结合起来就可以表示字符串的对象了。
<router-link :to="`/home/message/details/${m.id}/${m.title}`">以:id 的形式作为占位符,id是params下的属性。
children:[ { name:'link_detail', path :'details/:id/:title', component:Details } ]那么在回显的时候,不再是$route.query.id,而是 $route.params.id
<template> <ul> <li>消息编号:{{$route.params.id}}</li> <li>消息标题:{{$route.params.title}}</li> </ul> </template>路由props
props:{}
children:[ { name:'link_detail', path :'details/:id/:title', component:Details, //props的值会传给Details组件的props props:{a:"1",b:"2"} } ]<template> <ul> <li>消息编号:{{ id }}</li> <li>消息标题:{{ title }}</li> a:{{ a }} b:{{ b }} </ul> </template> <script> export default { name: "Details", mounted() { console.log("Details被挂载了", this) }, props: ['a', 'b'] } </script>这种做法可以在某个路由下通过props:对象 的形式去携带一个对象给路由组件,那么路由组件可以通过props:数组 的形式表示这些对象属性。缺点是只能携带定值。
props:true(最常用)
children:[ { name:'link_detail', path :'details/:id/:title', component:Details, props:true } ]props:true表示该路由组件携带的params参数,以props的形式传给当前路由组件
<template> <ul> <li>消息编号:{{id}}</li> <li>消息标题:{{title}}</li> </ul> </template> <script> export default { name: "Details", mounted() { console.log("Details被挂载了",this) }, props:['id','title'] } </script>props(){}(插一句,用的不是很多)
由于上一种方式只能把组件携带的params参数传递给props,如果你想组件携带的query参数传递给props,那么这里演示一个通过props函数:将携带的query参数传递给props,但是不要忘记把请求的方式改回query参数。
children: [ { name: 'link_detail', path: 'details', component: Details, props($routes) { return { id: $routes.query.id, title:$routes.query.title } } } ]