路由
SPA 单页面富应用的核心就是前端路由
每次GET或POST等请求在服务端有一个专门的正则配置列表,然后匹配到具体的一条路径后,分发到不同的Controller进行各种操作,最终将html或数据返回给前端,这就完成了一次IO
前后端分离开发模式 -> 后端只提供API来返回数据,前端通过Ajax获取数据后,再用一定的方式渲染到页面里。这么做的有点是前后端做的事情分得更清楚,后端专注数据,前端专注在交互和可视化上
那么缺点在于: 首屏渲染需要时间来加载css和javascript
SPA -> 在前后端分离的基础上,加一层前端路由
前端路由,即由前端来维护一个路由规则。实现有两种。一种是利用url的hash,就是常说的锚点# JavaScript通过hashChange事件来监听url变化,IE7及以下需要用轮询,另一种是HTML5的history模式,它使url看起来像普通网站那样,以 / 分割,没有# 但页面并没有跳转。使用该种模式需要服务端支持,服务端在接受到所有的请求后,都指向同一个html文件,不然会出现404。因此SPA只有一个html,整个网站所有内容都在html里,通过js来处理。
前端路由的优点有很多,比如页面持久性。
基本用法
main.js
const Routers = [
{
path: '/index',
component: resolve => require(['./views/index.vue'], resolve)
// component: require('./view/index.vue')
},
{
path: '/about',
component: resolve => require(['./views/about.vue'], resolve)
// component: require('./view/about.vue')
}
]Routers里的每一项path属性就是指定当前匹配的路径,component是映射的组件。 这样写,webpack会把每一个路由都打包为一个js问件,在请求到该页面时,才去加载这个页面的js,也就是异步实现的懒加载(按需加载)
若需要一次性加载可以改为注释的写法。使用异步路由后,编译出的每个页面的js都叫作chunk块,它们命名默认是0.main.js... 1.main.js等 可以在webpack配置的出口 output里通过设置chunkFilename字段修改chunk命名:
output: {
publicPath: 'dist',
filename: '[name.js]',
chunkFilename: '[name].chunk.js'
}有了chunk后,在每个页面 .vue 文件里写的样式也需要配置后才会打包进main.css,否则仍然会通过JS动态创建<style>标签的形式写入,配置插入:
// webpack.config.js
plugins: [
new ExtractTextPlugin({
filename: '[name].css',
allChunks: true
})
]然后继续在main.js里完成配置和路由实例:
const RouterConfig = {
// 使用HTML5的History路由模式
mode: 'history',
routes: Routers
}
const router = new VueRouter(RouterConfig)
new Vue({
el: '#app',
router,
render: h => {
return h(app)
}
})若使用了History路由模式,在package.json中需要修改dev命令
"scripts": {
"dev": "webpack-dev-server --open --history-api-fallback --config webpack.config.js"
}
增加了 --history-api-fallback 所有的路由都会指向 index.html
Router高级用法
路由改变时,动态地修改 document.title。可以使用vue-router提供的导航钩子 beforeEach和afterEach 它们会在路由即将改变前和改变后触发,所以设置标题可以在beforeEach钩子完成
// route/index.js
const routes = [
{
path: './index',
meta: {
title: 'index'
},
component: resolve => require(['./views/index.vue'], resolve)
},
{
path: './about',
meta: {
title: 'about'
},
component: resolve => require(['./views/about.vue'], resolve)
}
]
const router = new Router({
routes,
//将激活的路由添加一个mui-active类名称
linkActiveClass: 'active',
// mode: 'history',
})
router.beforeEach((to, from, next) => {
window.document.title = to.meta.title
next()
})导航钩子有3个参数:
- to即将要进入的目标的路由对象
- from 当前导航即将要离开的路由对象
- 调用该方法后,才能进入下一个钩子
光修改标题还不够,当页面较长时,路由切换当前的 scrollHeight值不会改变,更好的体验是能返回顶端 可以通过afterEach钩子来实现:
router.afterEach((to, from, next) => {
window.scrollTo(0, 0)
})