一、 导航守卫
导航是什么?
导航:“导航”表示路由正在发生改变。
为什么使用导航守卫
真实的项目中需要判断权限或者登录状态决定用户能访问的路由,但是因为路由是在浏览器地址栏中的,用户可以输入,如果不加以拦截就可以看到本不该看到的页面;为了避免这种情况,我们需要使用导航守卫,在路由发生变化时作出相应的判断,判断用户是否可以去到他想去往的页面的路由;
常用的导航守卫:
let router = new VueRouter({....});
1. 全局前置守卫
router.beforeEach((to, from, next) => {....})
当一个路由发生变化时(从一个页面跳到另一个页面时),就会触发 beforeEach 中得回调函数,该回调函数有三个参数:
- to 路由对象,即将进入的页面的路由信息
- from 路由对象,当前正要离开页面路由信息
- next 函数,交出控制权或者中断导航
- 3.1 next() 交出控制权,执行下面的功能
- 3.2 next(false) 中断当前导航,如果url改变了,将会回退到当前页面
- 3.3 next(‘/‘) 跳转到另一个路由,next 可以接收和 $router.push() 一样的参数
- 当使用导航守卫时,无论是否通过验证,都要调用 next 方法,如果通过校验则执行 next() ,不通过则重定向或者中断;如果不调用,那么整个路由变化处于挂起状态,无法渲染任何组件;
2. 路由独享守卫
- 你可以在路由配置上直接定义 beforeEnter 守卫;
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: () => import(/* webpackChunkName: "about" */ './views/About.vue'),
beforeEnter (to, from, next) {
console.log(to)
console.log(from)
next()
}
}
]
})
- beforeEnter 方法同样有三个参数,其3个参数和全局守卫的三个参数相同,在进入该路由组件之前都会调用该钩子,我们在这个钩子中进行校验,如果校验通过,则执行 next(),只有执行 next,才能渲染该路由对应的组件;
3.组件内守卫
最后,你可以在路由组件内直接定义以下路由导航守卫;
- beforeRouteEnter 在渲染该组件的对应路由前调用,该钩子中不能访问this,因为实例还未创建
- beforeRouteUpdate 在当前路由改变,但是该组件被复用时调用,适用于动态路由的参数发生变化时
- beforeRouteLeave 导航离开该组件的对应路由时调用,即要从当前页面去往其他页面时调用,可以用来做保存拦截,例如提示用户信息尚未保存等;
export default {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
二、用webpack配置vue的单页面应用
真实项目中我们不是单独使用 Vue,而是结合 webpack 等打包工具;因为 webpack 可以更方便的实现模块化,导入导出依赖。而且使用 webpack 配合 vue-loader,我们的组件可以写成 .vue 的文件。
使用配置 Vue 应用的 webpack
在之前的 webpack 配置基础上增加 vue-loader 和一个 vue-loader 的插件;
安装 vue-loader、vue-template-compiler
npm install vue-loader vue-template-compiler --save-dev
示例配置文件
let HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
// 使用 vue-loader 需要:
// 1. 安装 vue-template-compiler
// 2. 使用 VueLoaderPlugin
module.exports = {
entry: './src/main.js',
output: {
path: __dirname + './dist',
filename: 'bundle.js'
},
devtool: 'eval-source-map',
devServer: {
contentBase: './src/index.html',
historyApiFallback: true, // 单页面应用路由切换时不请求服务器
port: 8081,
inline: true,
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
secure: false
}
}
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
},
exclude: /node_modules/
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
},
{
test: /\.(png|jpg|gif|woff|ttf)$/,
use: 'url-loader'
},
{
test: /\.vue$/,
use: 'vue-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new VueLoaderPlugin()
]
};
三、vue-cli
vue-cli 是 Vue 官方提供的脚手架,其中内置了 webpack 的一些默认配置,可以快速搭建项目;目前市面上常见的版本主要有 2.x 和 3.x;3.x 是最新版本,我们以最新版本为例;
3.1 安装
- 全局安装 @vue/cli 脚手架
npm install @vue/cli -g
执行 vue —version 输出版本号即为成功
3.2 安装后初始化项目
- 在任意目录下(不要有中文名字)打开命令行
- 数据 vue create 项目名字,如 vue create my-app
- 接下来按照提示按照选择依赖包或者选择默认,一般我们选择手动配置;
- 接着等待依赖安装
- cd my-app
- npm run serve
3.3 修改vue-cli、webpack的配置
- 在项目目录下新建 vue.config.js 文件
- 一些常见的修改
module.exports = {
outputDir: '../dist', // 在打包输出后的路径
lintOnSave: true, // 默认值 true 启用 ESLint 语法检查
productionSourceMap: false, // 生产环境是否需要 source-map 如果设为 false 可以加速打包
devServer: { // vue-cli 支持所有的 dev-server 配置,
port: 8082,
open: true,
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
secure: false
}
}
}
};
四、element-ui 使用
4.1 安装 element-ui
npm install element-ui --save
4.2 全局导入 element-ui
- 在main.js 中导入
import Vue from 'vue';
import ElementUI from 'element-ui'; // 导入 elementUI
import 'element-ui/lib/theme-chalk/index.css'; // 导入 css
import App from './App.vue';
Vue.use(ElementUI);
4.3 使用 element-ui 的组件
- element-ui 的组件默认全部注册,无需导入,直接使用即可;
示例
<template>
<div class="home">
<el-input v-model="msg" prefix-icon="el-icon-search"></el-input>
</div>
</template>
<script>
export default {
name: 'home',
data() {
return {
msg: ''
}
},
components: {
HelloWorld
}
}
</script>