前端路由 | 后端路由 |
---|---|
对单页面程序来讲,主要通过URL中的hash #号 来实现不同页面之间的切换。同时hash有一个特点,http请求中不会包含hash的相关内容,单页面程序的页面跳转主要用hash实现 | 对于普通网站,所有的超链接都是URL地址,所有的url地址对应服务器上的资源 |
简单路由
https://cn.vuejs.org/v2/guide/routing.html
main.js
import NotFound from '@/views/NotFound' // 错误路由匹配页
data: {
currentRoute: window.location.pathname
},
computed: {
ViewComponent () {
return routes[this.currentRoute] || NotFound
}
},
render (h) { return h(this.ViewComponent) }
router
import App from '@/App'
import About from '@/views/About'
const routes = {
'/': App,
'/about': About
}
export default routes
使用路由:
1.引入vue–router
2.创建router实例,注册路由对象
3.给路由展示区
VueRouter构造函数用于创建路由实例,默认为hash路由。在hash模式下a标签的href给#/login和/login是不同的,#代表页面内锚点跳,没有#要跳转。
<a href = " #/login ">登录</a>
不会跳转,<a href = " /login ">登录</a>
跳转到F:/login去,浏览器报错找不到文件
步骤:
在模版内写路由展示区
<router-view></router-view>
定义路由对象
const router = new VueRouter({
路由表 routes
routes:[
{path:'/home',component:Login}
]
})
将路由对象注册到vue实例中
new Vue({
router
})
以上为hash模式配合a标签,但a标签必须写#/login
,我们使用<router-link to="/login"></router-link>
不需要写#/login
。
如果mode='history'
模式测试a标签不能实现组件切换。
hash模式:
<a href="#/login">登录</a>
<router-link to="/register">注册</router-link> 注意使用router-link不需要#
<router-view></router-view>
const router=new VueRouter({
routes:[{}],
})
router-link 默认不支持 target="_blank",但实际上 vue 2.0 支持新开页面,但是要求 tag 必须为 a ,渲染成其他标签则不生效(只有a标签有target属性)
路由钩子(导航守卫)
1.全局守卫
全局前置守卫:
beforeEach((to,from,next)=>{
next()
next(false)
next('/') || next({path:'/'})
可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: 'home' 之类的选项
以及任何用在 router-link 的 to prop 或 router.push 中的选项
})
全局后置钩子
afterEach((to,from)=>{
钩子不会接受 next 函数也不会改变导航本身
})
2.5新增:全局解析守卫
beforeResolve()
2.组件守卫
beforeRouteEnter (to, from, next) {
在渲染该组件的对应路由被 confirm 前调用
不!能!获取组件实例 `this`
因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
在当前路由改变,但是该组件被复用时调用
举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
导航离开该组件的对应路由时调用
可以访问组件实例 `this`
}
3.路由独享守卫
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {}
}
]
})
动态路由匹配(路由传参)
如果在路由中通过 url字符串查询传参数,则不需要修改规则的path属性,直接就能用
query方式
<router-link to="/login?id=10"></router-link>
在组件内通过this.$route的query对象中拿数据
created(){
this.$route.query.id
$route为路由器,内有query和path/params等属性
}
params方式
<router-link to="/login/123/zhangsan"></router-link>
路由表需要特殊配置
routes:[
{ path:'/login/:id/:name',component:Login }
]
在组件内通过this.$route的params对象中拿数据
created(){
this.$route.params.id
}
params通过metched将path在内部预解析为一个正则表达式,然后用正则解析fullPath,解析出来的结果就可以拿到params对象
二级路由
二级路由是通过路由表里的children属性配置
const routes=[
{path:'/home',component:Home,children:[
注意,子路由path属性不加/,如果加/则匹配的不是/home/login,而是跟目录下的/login
这时router-link的to属性需要写成'/login'而不是'/home/login'
如果带斜线写'/login'让人看不明白,不要带斜线。否则只能匹配跟url下的路径
{path:'login',component:Login}
]}
]
路由表component和components区别
一个url只匹配单个组件
const routes=[
{ path:'/' , component:Head }
]
匹配多个组件
模版内:
<router-view></router-view> 匹配默认组件
<router-view name="left"></router-link> left组件
<router-view name="main"></router-link> main组件
js:
const routes=[
{ path:'/' , component:{
default:Head, 默认匹配
left:Left,
main:Main
}}
]
SPA
现在的应用都流行单页面,在用户通过某些操作后更改地址url后,动态的进行不同模版内容的无刷新切换,用户体验更好。
在vue中使用官方提供的vue-router来配置单页,通过url的变化,触发hashchange事件进行路由之间的切换(卸载和安装)
ajax请求,通过路由,页面不会整体重载
Router
基础
vue 路由的mode(模式)有几种, 分别是什么?在那些环境下运行?
-
hash
(mode默认),使用 URL hash 值来作路由。支持所有包括不支持 HTML5 History Api 的浏览器。直接使用a标签<a href="#/home"></a>
-
history
: 依赖H5 History API
和服务器配置。【需要后端支持,后端需要配置】<router-link to=""> Vue提供,to跳转 </router-link>
-
abstract
: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。
-
使用步骤
-
安装
npm i vue-router -S
-
在src目录下创建一个
router
目录, 里面创建一个index.js
文件 , 这个目录是放router
模块用的 -
在
index.js
内引入第三方的依赖包, 并注册路由。分别引入自定义组件,为router实例做准备。import Vue from 'vue' import VueRouter from 'vue-router' 自定义组件引入 import Home from "../components/pages/Home"; import Category from "../components/pages/Category"; Vue.use( VueRouter ) //使用vue-router这个第三方插件
注意:
import
这个关键字要放在整个文件的上层 -
创建
router
对象实例,并创建路由表,选取模式mode
const routes = [ { path: '/home', //当前路由路径 component: Home, // 当前路由对应组件 children:[{}], // 子路由 name, // 命令路由 redirect: '/home' // 重定向 }//每一个对象就是一个路由 ] const router = new VueRouter({ routes, //路由表 必写 mode: 'history' // 模式 })
-
导出router实例
export default router
-
入口文件main.js中引入路由实例 router , 然后在根实例中注册
import router from './router/index.js' // index.js可以省略 new Vue({ router, render: (h) => App }).$mount('#app')
-
路由展示区域
- 如果是根级路由, 那么我们放在
App.vue
组件中,用router-view
的组件展示。 - 如果
mode
为history
模式,那么还需讲所有的a标签换成<router-link to="" tag="li">
- 可以指定router-link渲染指定标签:
router-link tag="li"
<router-view />
- 如果是根级路由, 那么我们放在
-
当页面第一次的打开的时候, 需要做一个重定向, 就是要自动跳转到 /home 这个路由上
const routes = [ { //我们要求这个路由的配置要放在路由表的最上方 path: '/', redirect: '/home' } ]
-
业务: 错误路由匹配,
const routes = [ { path: '/', redirect: '/home' //重定向 }, ...... { path: '/error', component: Error }, { //这个就是错误路由匹配, vue规定这个必须放在最下面,它必须将上面的路由全找一遍,找不到才用当前这个 path: '**', redirect: '/error' } ]
-
vue路由模式的确定
- 如果你使用的是 hash , 那么a标签就可以了、
- 如果你使用 history , 那么我们最好将a标签改成 router-link 这个组件
- router-link 这个组件 身上必须要有一个 to 属性
-
二级路由
const routes = [ { path: '/shopcar', component: Shopcar, children: [ { path: 'yyb', //不写 / component: Yyb } ] } ]
- 注意: 写好配置之后,不要忘记了, 在一级路由组件的
.vue
文件中添加二级路由展示区域
- 命名路由
作用: 简写路径
使用(.vue){ path: '/shopcar', component: Shopcar, //子路由 children: [ { name: 'yyb' //命名路由 } }
<router-link :to = "{name:'yyb'}"/>
- 动态路由
-
数据预载(数据获取)
两种方式:导航完成前获取,导航完成后获取
- 导航完成前
export default {
created () {
// 组件创建完后获取数据,
// 此时 data 已经被 observed 了
this.fetchData()
},
}
1.这里设置的必须为对象,
next(vm=>{
Vue.set(vm.dataArrt,key,value)
})
2.next(vm=>{
vm.setData(vm.dataAttr,value)
})
路由懒加载
https://segmentfault.com/a/1190000012705647?utm_source=tag-newest
按需加载路由
- Vue异步组件
- webpack代码分割
函数封装
const routerLayLoad = componentsPath => imoprt( '@/view/' + componentsPath )
路由表内
const routes=[
{
path:'',
components:routerLayLoad( 'index/components/CommonHeader.vue' )
}
]
杂碎
动画
别人给的六个类名+自己写c3、使用animate.css、八个动画钩子写、类库涡轮city,使用方式跟jquery一致
- 安装
npm i animate.css -S
- main.js引入
import 'animate.css'
- 在vue文件中用
transition
包裹router-view
。 transition
标签添加enter-active-class="animated + 类"
和leave-acitve-class="animated + 类"
属性
main.js:
import 'animate.css'
vue文件:
<transition
enter-active-class="animated slideInLeft"
leave-active-class="animated slideOutLeft"
mode="out-in"
name="router"
>
<router-view></router-view>
</transition>
缓存
<router-link
active-class="active"
keep-alive
class="nav-link"
to="/home"
>
首页
</router-link>
路由激活
- 在rout-link标签中添加
active-class
属性,值为类名 - 写一个
active
的样式
<router-link active-class="active" class="nav-link" to="/home">首页</router-link>
<style>
.active{
color:rosybrown;
}
</style>
滚动行为
官网中的滚动行为不好用
router实例中scrollBehavior中的savedPositon参数只能通过浏览器的前进后退键才管用,通过超链接切换的无法滚动
移动端:上拉刷新,下拉加载。原生JS无法实现,通过第三方库解决
devServer.proxy
- 使用中间件:http-proxy-middleware
- 根目录新建vue.config.js文件
- App.vue的new Vue实例中created(){}钩子使用axios请求