Vue插件

注册插件需要一个公开的方法install,它的第一个参数时Vue构造器,第二个参数是一个可选的选项对象。

See the Pen Vue插件 by whjin (@whjin) on CodePen.

前端路由与vue-router

SPA的核心就是前端路由,对于一个网址,每次GET或POST等请求在服务端有一个专门的正则配置列表,然后匹配到具体的一条路径后,分发到不同的Controller,进行各种操作,最终将html或数据返回给前端,这样就完成了一次IO。

前端路由,即由前端来维护一个路由规则。实现方式有两种;

  1. 一种是利用urlhash,就是常说的锚点(#),JavaScript通过hashChange事件来监听url的改变;
  2. 另一种就是HTML5的history模式,它使url看起来像普通网站那样,以/分割,没有#,但也没并没有跳转,不过使用这种模式需要服务端支持,服务端在接收到所有的请求后,都指向同一个html文件,不然会出现404

因此,SPA只有一个html,整个网站所有的内容都在这个html里,通过JavaScript来处理。

如果要独立开发一个前端路由,需要考虑到页面的可插拔、生命周期、内存管理等问题。

vue-router

vue-router的实现原理与通过is特性实现动态组件的方法类似,路由不同的页面事实上就是动态加载不同的组件。

创建一个数组来指定路由匹配列表,每一个路由映射一个组件:

const Routers = [
    {
        path: '/index',
        component: (resolve) => require(['./views/index.vue'], resolve)
    },
    {
        path: '/about',
        component: (resolve) => require(['./views/about.vue'], resolve)
    }
];

Routers里每一项的path属性就是指定当前匹配的路径,component是映射的组件。

webpack会把每一个路由都打包为一个js文件,在请求道该页面时,再去加载这个页面的js,也就是异步实现的懒加载(按需加载)。这样做的好处是不需要在打开首页的时候就把所有的页面内容全部加载进来,只在访问时才加载。

使用了异步路由后,变移除的每个页面的js都叫做chunk(块),它们命名默认是0.main.js1.main.js
可以在webpack配置的出口output里通过设置chunkFilename字段修改chunk命名。

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

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

const RouterConfig = {
    //使用HTML5的History路由模式
    mode: 'history',
    routes: Routers
};

const router = new VueRouter(RouterConfig);

new Vue({
    el: "#app",
    router: router,
    render: h => {
        return h(App)
    }
});

在RouterConfig里设置modehistory会开启HTML5的History路由模式,通过/设置路径。如果不配置mode,就会使用#来设置路径。

开启History路由,在生产环境时必须进行配置,将所有路由都指向同一个html,或设置404页面,否则刷新时页面就会出现404

在路由列表里,可以在最后新加一项,当访问的路径不存在时,重定向到首页:

{
    path: '*',
    redirect: '/index'
}

路由列表的path可以带参数,比如/user/123,其中用户ID123是动态的,但它们路由到同一个页面,在这个页面里,期望获取这个ID,然互殴请求相关数据。

跳转

vue-router有两种跳转页面的方法,第一种是使用内置的<router-link>组件,它会被渲染为一个<a>标签。

<template>
    <div>
        <h1>首页</h1>
        <router-link to="/about">跳转到about</router-link>
    </div>
</template>

它的用法与一般的组件一样,to是一个prop,指定需要跳转的路径,也可以用v-bind动态设置。

使用<router-link>,在HTML5的History模式下会拦截点击,避免浏览器重新加载页面。

还有其他一些prop,常用的有:

有时候,跳转页面可能需要在JavaScript中进行,类似于window.location.href。这时可以使用第二种跳转方法,使用router实例的方法。

<template>
    <div>
        <h1>介绍页</h1>
        <button @click="handleRouter">跳转到user</button>
    </div>
</template>

<script>
    export default {
        methods: {
            handleRouter() {
                this.$router.push('/user/123');
            }
        }
    }
</script>

$router还有其他一些方法:

高级用法

在SPA项目中,如何修改网页的标题?

在页面发生路由变化时,统一设置。

vue-router提供了导航钩子beforeEachafterEach,它们会在路由即将改变前和改变后触发,所以设置标题可以在beforeEach钩子完成。

See the Pen vue-router导航钩子 by whjin (@whjin) on CodePen.

导航钩子有3个参数:

路由列表的meta字段可以自定义一些信息,将每个页面的title写入meta来统一维护,beforeEach钩子可以从路由对象to里获取meta信息,从而改变标题。

某些页面需要校验是否登录,如果登录就可以访问,否则跳转到登录页。通过localStorage来简单判断是否登录。

router.beforeEach((to, from, next) => {
    if (window.localStorage.getItem('token')) {
        next()
    } else {
        next('/login')
    }
});

next()的参数设置为false,可以取消导航,设置为具体的路径可以导航到指定的页面。