Vue.js提供了插件机制,可以在全局添加一些功能。它们可以简单到几个方法、属性,也可以很复杂,比如一整套组件库。
注册插件需要一个公开的方法install,它的第一个参数是Vue构造器,第二个参数是一个可选的对象。例如:
MyPlugin.install = function (Vue, options) {
//全局注册组件(指令等功能资源类似)
Vue.component('component-name',{
//组件内容
})
//添加实例方法
Vue.prototype.$Notice = function () {
//逻辑...
}
//添加全局方法或属性
Vue.globalMethod = function () {
//逻辑...
}
//添加全局混合
Vue.minin({
mounted:function () {
//逻辑...
}
})
}
通过Vue.use()来使用插件:
Vue.use(MyPlugin)
//或
Vue.use(MyPlugin,{
//参数
})
1.1 前端路由与vue-router
1.1.1 什么是前端路由
webpack的主要使用场景是单页面富应用(SPA),而SPA的核心就是前端路由。那什么是路由呢?通俗地讲,就是网址。再专业一点,就是每次GET或者POST等请求在服务端有一个专门的正则配置列表,然后匹配到具体的一条路径后,分发到不同的Controller,进行各种操作,最终将html或数据返回给前端,这就完成了一次IO。
目前绝大多数的网站都是这种后端路由,也就是多页面的,这样的好处有很多,比如页面可以在服务端渲染好直接返回给服务器,不用等待前端加载任何js和css就可以直接显示网页内容,再比如对SEO的友好等。后端路由的缺点也是很明显的,就是模板是由后端来维护或改写的。前端开发者需要安装整套的后端服务,必要时还得学习像PHP或Java这些非前端语言来改写html结构,所以html和数据、逻辑混为一谈,维护起来既臃肿有麻烦。
然后就有了前后端分离的开发模式,后端只提供API来返回数据,前端通过Ajax获取数据后,再用一定的方式渲染到页面里,这么做的优点就是前后端的事情分得很清楚,后端专注在数据上,前端专注在交互和可视化上,如果今后再开发移动APP,那就正好能使用一套API。当然,缺点也很明显,就是首屏渲染需要时间来加载css和js。这种开发模式被很多公司认同,也出现了很多前端技术栈。在Node.js出现后,这种现象有了改善,就是所谓的大前端,得益于Node.js和JavaScript的语言特性,html模板可以完全由前端来控制,同步或异步渲染完全由前端自由决定,并且由前端维护一套模板,这就是为什么在服务端使用artTemplate、React以及Vue2的原因。什么是SPA呢?其实就是在前后端分离的基础上,加一层前端路由。
前端路由,即由前端来维护一个路由规则。实现有两种,一种是利用url的hash,就是常说的毛点(#),JavaScript通过hashChange事件来监听url的改变,IE7及以下需要使用轮询;另一种就是好HTML5的History模式,它使url看起来像普通网站那样,以“/”分割,没有#,但页面并没有跳转,不过使用这种模式需要服务端支持,服务端接收到所有的请求后,都指向同一个html文,不然会出现404。因此,SPA只有一个html,整个网站所有的内容都在这一个html里,通过JavaScript来处理。
前端路由的优点有很多,比如页面的持久性,像大部分音乐网站,你都可以在播放歌曲的同时跳转到别的页面,而音乐没有中断。再比如前后端的彻底分离。前端路由的框架通用的有Director,不过更多的还是结合具体框架来用,比如Angular的ngRouter,React的ReactRouter,以及Vue的vue-router。
如果要独立开发一个前端路由,需要考虑到页面的可插拔、页面的生命周期、内存管理等问题。
1.1.2 vue-router基本用法
路由不同的页面事实上就是动态加载不同的组件。
新建一个目录router,再通过NPM安装vue-router:
npm install --save vue-router
在main.js里使用Vue.ues()加载插件:
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './app.vue';
Vue.use(VueRouter);
每个页面对应一个组件,也就是对应一个.vue文件。在router目录下创建views目录,用于存放所有的页面,然后在views里创建index.vue和about.vue两个文件:
//index.vue
<template>
<div>首页</div>
</template>
<script>
export default {
}
</script>
//about.vue
<template>
<div>介绍页</div>
</template>
<script>
export default {
}
</script>
再在main.js里完成路由剩余配置。创建一个数组来制定路由匹配列表,每一个路由映射一个组件:
const Routers = [
{
path: '/index',
component: (resolve) => require(['./views/index.vue'], resolve)
},
{
path: '/about',
component: (resolve) => require(['./views/about.vue'], resolve)
}
];
Router里每一项的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,否则仍然会通过JavaScript动态创建<style>标签的形式写入。
1.1.3 跳转
vue-router有两种跳转页面的办法,第一种是使用内置的<router-link>组件,它会被渲染为一个<a>标签:
//index.vue
<template>
<div>
<h1>首页</h1>
<router-link to="/about">跳转到about</router-link>
</div>
</template>
它的用法与一般的组件一样,to是一个prop,指定需要跳转的路径,当然也可以用v-bind动态设置。使用<router-link>,在HTML5的History模式下会拦截点击,避免浏览器重新加载页面。
<router-link>还有其他的一些prop,常有的有:
· tag 可以指定渲染成什么标签,比如<router-link to="/about" tag="li">渲染的结果就是<li>而不是<a>
· replace 使用replace不会留下History记录,所以导航后不能用后退键返回上一个页面,如<router-link to="/about" replace>
· active-class 当<router-link>对应的路由匹配成功时,会自动给当前元素设置一个命名为router-link-active的class,设置prop: active-class可以修改默认的名称。在做类似导航栏时,可以使用该功能高亮显示当前页面对应的导航菜单项,但是一般不会修改active-class,直接使用默认值router-link-active就可以。
有时候,跳转页面可能需要在JavaScript里进行类似于window.location.href。这时可以用第二种跳转方法,使用router实例的方法。比如在about.vue里,通过点击事件跳转:
//about.vue
<template>
<div>
<h1>介绍页</h1>
<button @click="handleRouter">跳转到user</button>
</div>
</template>
<script>
export default {
methods: {
handleRouter(){
this.$router.push('/user/123');
}
}
}
</script>
$router还有其他一些方法:
· replace 类似于<router-link>的replace功能,它不会向history添加新纪录,而是替换掉当前的history记录,如this.$router.replace('/user/123')。
· go 类似于window.history,go(),在history记录中向前或者后退多少步,参数是整数。