本篇是关于路由的学习。来源于王红元老师和各位大佬的文章。
1.什么是路由
通过互联的网络把信息从源地址传输到目的地址的活动。
路由器提供了两种机制: 路由和转送 路由是决定数据包从来源到目的地的路径. 转送将输入端的数据转移到合适的输出端.
路由表:本质上就是一个映射表, 决定了数据包的指向
2.后端渲染和前端渲染
后端渲染阶段(jsp):获取url地址,在服务器上直接渲染好页面 发送给前端
后端路由:后端处理url和页面之间的映射关系,当我们在页面中需要请求不同路径内容的时候,交给服务器来进行处理,服务器渲染好整个页面,并且将页面返回给客户端,这种情况下渲染好的页面,不需要单独加载任何js和css,可以直接交给浏览器展示,有利于SEO优化。
客户端 =>静态服务器资源 =>服务端
前后端分离阶段:通过ajax分离前后端,后端负责提供数据,不负责任何阶段的内容,通过ajax获取数据,并且通过Javascript将数据渲染到页面中
前端渲染(js):浏览器中显示的网页中的大部分内容,都是由前端写的js代码在浏览器中执行,最终渲染出来的网页
单页面富应用阶段(spa) 前后端分离+前端路由 前端路由:配置映射关系,一个url对应一个组件
核心:改变url,但是页面不进行整体的刷新,前端自行监听url的改变
3.url的hash和html5的history
1.hash锚点(#):通过监听浏览器的onhashchange()事件变化,查找对应的路由规则。hash模式在每次刷新页面时是直接更改#后的东西,本质上是改变window.location的href属性。
2.history原理: 利用H5的新增的两个API pushState() 和 replaceState() 和一个事件onpopstate监听URL变化。
history每次刷新会重新向后端重新请求服务器。history模式URL要和后端进行一致,如果后端没有及时响应,就会报错404!history的好处是可以进行修改历史记录,并且不会立刻像后端发起请求。
history.pushState():添加一个url,可以返回
history.replaceState():替代原来的url,不能返回
history.go(num):num表示前进或后退(负值)
两者区别(面试)
1.表现形式的区别
hash: 带#参数在 "?" 之后通过 "&" 拼接。
history: 没有 "#" ,参数在路径中。
2.原理的区别:
hash模式是基于锚点和 onhashchange事件实现的,将锚点的值作为路由地址,当地址发生变化时触发onhashchange事件,根据路径决定页面上呈现的内容。因为向服务器发送请求不会带#后面的内容,因此修改#后面的内容不会触发浏览器的刷新,不会去请求服务器。
history模式是基于Html5中的 history Api:history.pushState(IE10以上才支持)和history.replaceState方法实现的。
history.push 和 history.pushState方法的区别是,history.pushState方法不会请求服务器,只会改变导航栏的地址并记录历史。
vue-router
1.安装
npm install vue-router --save
2.创建router/index.js文件夹
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
3.创建router实例
import Vue from 'vue'
import VueRouter from 'vue-router'
// 1.安装插件
Vue.use(VueRouter)
// 2.创建router
const routes = [
]
const router = new VueRouter({
routes,
mode: 'history'
})
export default router
4.挂载到Vue实例中
//main.js中
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
5.配置组件和路径的映射关系
const Home = () => import('../views/home/Home')
const routes = [
{
path: '',
component: '/home'
},
]
6.使用路由
<router-link to='/home'/>
<router-view></router-view>
<router-link to='/xxx'>: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个<a>标签
<router-link>还有一些其他属性:
tag:可以指定<router-link>之后渲染成什么组件(vue-router4.x开始,该属性被废除)
replace: 不会留下history记录, 所以指定replace的情况下, 后退键返回不能返回到上一个页面中
active-class: 处于被点击状态,当<router-link>对应的路由匹配成功时, 会自动给当前元素设置一个
router-link-active的class名
作用:给被点击的设置样式。设置active-class可以修改默认的名称
但是通常不会修改类的属性, 会直接使用默认的router-link-active即可.
<router-view>:(占位符)(组件渲染的位置) 该标签会根据当前的路径, 动态渲染出不同的组件,网页的其他内容, 比如顶部的标题/导航, 或者底部的一些版权信息等会和<router-view处于同一个等级。
在路由切换时, 切换的是<router-view>挂载的组件, 其他内容不会发生改变.
7.redirect是重定向:一开始跳转到默认的地址上
path配置的是根路径: / 也就是我们将根路径重定向到/home的路径下
{
path: '/',
redirect: '/home'
},
8.默认情况下改变的hash的地址,想要更换模式
const router = new VueRouter({
routes,
mode: 'history'
})
动态路由
路径不确定,在path里定义参数项:id在路径中使用一个动态字段来实现,我们称之为 路径参数 :
this.$route.params.id:可以拿到后续的路由参数信息
谁处于被选中状态,$route就为该状态的组件
//router/index.js
const routes = [
{
path: '/home/:id',
component: '/home'
},
]
//动态路由配置 App.vue
<router-link :to="'/user'+Id"/>
//拿到动态路由参数
<p>{{$route.params.id}}</p>
data(){
return{
Id:'11111'
}
}
路由懒加载(用的时候再加载)
作用:将路由对应的组件打包成一个个的js代码块.只有在这个路由被访问到的时候, 才加载对应的组件
方式一: 结合Vue的异步组件和Webpack的代码分析.
const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};
方式二: AMD写法
const About = resolve => require(['../components/About.vue'], resolve);
方式三: 在ES6中, 我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割.
const Home = () => import('../components/Home.vue')
嵌套路由
{
path: '/home',
component: UserHome,
meta: {
activeNum: 0
},
children: [
{
path: '/home/searchPopup',
name: 'SearchPopup',
// 路由懒加载
component: () => import(/* webpackChunkName: "SearchPopup" */ '../views/SearchPopup.vue')
}
]
},
<router-link to='/home/searchPopup'></router-link>
<router-view></router-view>
编程式导航
调用API的方法实现导航的方式
(1)this.$router.push('/xxx'):跳转到指定hash地址,并增加一条历史记录,可以进行后退或前进
(2)this.$router.replace('/xxx):跳转到指定的hash地址,并替换掉当前的hash地址,页面不可后退或前进,只存在一条历史记录
(3)this.$router.go(n):n表示数值,前进or后退 this.$router.back() 后退 this.$router.forward前进
传递参数的的方式
1.query(大量传递参数)
配置路由格式: /router, 也就是普通配置
传递的方式: 对象中使用query的key作为传递方式
传递后形成的路径: /router?id=123, /router?id=abc
获取参数:$route.query.xxx
2.params
配置路由格式:/router/:id
传递方式:在path后面跟上对应的值/router/123
3.两种方式
第一种:在跳转时就设置参数
<router-link to="{
path:'/user/'+123,
query:{name:'why':age:18
}"
></router-link>
第二种:通过this.$router.push()
methods: {
// 跳转至详情页
toPruductDetail(id) {
// query传递参数
this.$router.push('/pruductDetail?id=' + id)
//完整版
this.$router.push({
path:'/user/'+123,
query:{name:'why',age:18}
})
}
}
4.获取参数 {{$route.query/params.id}}
router 和route 的由来
$router为VueRouter实例,想要导航到不同URL,则使用$router.push方法
$route为当前router跳转对象里面可以获取name、path、query、params等
导航守卫
vue-router提供的导航守卫主要用来监听路由的进入和离开的.beforeEach和afterEach的钩子函数, 它们会在路由即将改变前和改变后触发.
导航钩子的三个参数解析:
to: 即将要进入的目标的路由对象.
from: 当前导航即将要离开的路由对象.
next: 调用该方法后, 才能进入下一个钩子.
//前置路由守卫(全局守卫) 配置在router/index.js中
router.beforeEach((to, from, next) => {
//判断用户有无登录
const token = localStorage.getItem('token')
if (to.path === '/cart') {
if (token) {
next()
}
//必须有next()
next()
})
路由元信息
有时,你可能希望将任意信息附加到路由上,如过渡名称、谁可以访问路由等。这些事情可以通过接收属性对象的meta属性来实现,并且它可以在路由地址和导航守卫上都被访问到。定义路由的时候你可以这样配置 meta 字段:
const routes = [
{
path: '/posts',
component: PostsLayout,
children: [
{
path: 'new',
component: PostsNew,
// 只有经过身份验证的用户才能创建帖子
meta: { requiresAuth: true }
},
{
path: ':id',
component: PostsDetail
// 任何人都可以阅读文章
meta: { requiresAuth: false }
}
]
}
]
keep-alive
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。(组件缓存)
它们有两个非常重要的属性:
include - 字符串或正则表达,只有匹配的组件会被缓存
exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存
只有该组件使用了keep-alive时才有以下两个生命周期函数
当组件被缓存时,自动触发 deactivated
当组件被激活时,自动触发 activated