Skip to content

路由

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

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命名:

js
output: {
  publicPath: 'dist',
  filename: '[name.js]',
  chunkFilename: '[name].chunk.js'
}

有了chunk后,在每个页面 .vue 文件里写的样式也需要配置后才会打包进main.css,否则仍然会通过JS动态创建<style>标签的形式写入,配置插入:

js
// webpack.config.js
plugins: [
  new ExtractTextPlugin({
    filename: '[name].css',
    allChunks: true
  })
]

然后继续在main.js里完成配置和路由实例:

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钩子完成

js
// 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钩子来实现:

js
router.afterEach((to, from, next) => {
  window.scrollTo(0, 0)
})

共 20 个模块,1301 篇 Markdown 文档。