不要让自己的底限成为你的上限
本文主要讲以下内容,会尽可能的通过简短的例子以更清晰的方式展示出来。less的安装使用,注入less全局模块;mixin分发 Vue 组件中的可复用功能;axios封装进行模块化请求接口;vue-router懒加载、路由拦截;filter过滤器,格式化文本。
- 使用less预编译语言代替传统css
- mixin注入使用
- axios封装
- vue-router懒加载、路由拦截
- filter过滤器
bugfix:
- 修复loadEnv.js中导出的环境参数在webpack.config.js中异常问题。
- 🐛: 修复eslint错误提示导致配置错误的
@babel/plugin-syntax-dynamic-import
Less
less是一门css扩展的预编译语言,不使用插件的情况下需要编译成传统css。它可以使用变量、常量、嵌套、混入、函数等功能,可以更有效有弹性的写出CSS。并且有些插件在编译less过程中会自动添加对应的css前缀。
安装less
npm i less less-loader style-resources-loader -D
style-resources-loader
是用于Webpack
的CSS
处理器资源加载器,它为您的样式资源(例如)注入多个导入的模块。如variables, mixinscss, sass, scss, less, stylus
。
src
下创建文件夹less
,然后创建common.less
文件,这里主要放全局的less样式,比如颜色、名称等等。示例:
@info: #2d8cf0;
@success: #19be6b;
@warning: #ff9900;
@error: #ed4014;
webpack.config.js
中配置
// webpack.config.js
module.exports = {
...
module: {
rules: [
{
test: /\.less$/,
use: [
'style-loader', 'css-loader', 'less-loader', {
loader: 'style-resources-loader',
options: {
patterns: [resolve('src/less/common.less')]
}
}
]
}
...
]
}
};
配置完这些就可以使用less
啦,其他的同理食用。
less使用
main.vue
中代码如下:
<template>
<div class="main">main
<div class="info">info</div>
<div class="success">success</div>
<div class="warning">warning</div>
<div class="error">error</div>
</div>
</template>
...
<style lang="less" scoped>
.main {
.info {
color: @info;
}
.success {
color: @success;
}
.warning {
color: @warning;
}
.error {
color: @error;
}
}
</style>
mixin
混入(mixin)提供了一种非常灵活的方式,来分发Vue组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
具体例子可以看axios之mixin切换页面取消接口请求
axios
在第一篇文章【进击的Vue一】搭建Vue全家桶中已经提过了axios,
在main.js
中把axios挂载在了Vue对象的原型中,直接使用不够优雅,而且如果在项目中去使用,那肯定要判断多种数据状态的返回,如果都直接在this.$http
中使用会显得重复累赘。
axios封装
src
目录下创建utils
目录,创建request.js
文件。
import axios from 'axios';
/**
* process.env.APP_BASEURL 环境中的参数,在不同的环境下自动使用对应环境参数
* timeout: 默认超时7秒
* 更多信息查看:https://www.npmjs.com/package/axios
*/
const request = axios.create({
baseURL: process.env.APP_BASEURL,
timeout: 7000
// headers: {
// common: {
// 'Authorization': 123
// }
// }
});
// 请求拦截
request.interceptors.request.use(
config => {
// post请求时候参数格式转换
if (config.method === 'post' || config.method === 'POST') {
config.data = qs.stringify(config.data);
}
// config是发送请求时候所带的一些内容,比如数据什么的
return config;
},
error => {
Promise.reject(error);
}
);
request.interceptors.response.use(
response => {
// 处理http状态码,以及处理后端接口返回的状态值
// const { status, data } = response;
// if (status === 200) {
// return data;
// } else {
// window.alert(status);
// }
const data = response.data;
return data;
},
error => {
// 处理请求错误
if (error.name === 'Error') {
// window.alert(error.message);
}
// return error;
}
);
export default request;
axios使用
src
目录下创建文件夹api
,这个文件只用来放需要请求的接口
,比如我需要请求获取数据的接口/getData
。
修改.env.development
的APP_BASEURL
,如果不带http|https
,axios
会默认认为这个是url后面的pathname的字符
APP_BASEURL="http://dev/"
APP_TEXT="开发测试文本"
NODE_ENV="development"
import request from '@/utils/request';
/**
* 请求接口
* 如果想要请求非BASE_URL以外的url,比如一个新的url: https://v1.hitokoto.cn,
* 直接在data中重新设置url即可,会把原来的url替换掉
* @param {Object} data
*/
export const getData = data =>
request({
url: '/getData',
method: 'GET',
...data
});
然后在页面使用:
import { getData } from '@/api/account/index';
export default {
created() {
...
// 使用方法一
getData().then(res => {
console.log('Promise then', res);
}).catch(err => {
console.log('Promise catch error', err);
});
// 使用方法二
this.getReqData();
},
methods: {
// async异步
async getReqData() {
// 重置替换掉原来的链接
const data = await getData({
baseURL: 'https://v1.hitokoto.cn',
url: ''
});
console.log('async异步获取', data);
}
}
};
因为不存在http://dev/
所以会是network error
。下图所示
axios之mixin切换页面取消接口请求
注意:有的业务场景是在切换页面之后就取消
axios
的请求,防止在新的页面还出现上个(上上上个)请求的消息提示。参考大佬的mixin
方式取消。
/**
* @name cancelRequestMixin.js
* @url https://juejin.cn/post/6844904023191977998
* @description 切换页面之后取消接口调用
*/
import axios from 'axios';
const CancelToken = axios.CancelToken;
const cancelRequestMixin = {
data() {
return {
axiosCancelToken: null, // cancelToken实例
axiosCancel: null // cancel方法
};
},
created() {
// 初始化生成axiosCancelToken实例,注册axiosCancel方法
this.axiosCancelToken = new CancelToken(c => {
this.axiosCancel = c;
});
},
beforeDestroy() {
// 组件销毁阶段调用axiosCancel方法取消请求
this.axiosCancel('取消请求');
}
};
export default cancelRequestMixin;
vue-router路由懒加载、路由拦截
vue-router路由懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
🐛:更新内容
在使用import的时候可能会报eslint的错误Parsing error: Unexpected token importeslint
,这个时候需要安装babel-eslint
。
npm i babel-eslint -D
然后在.eslintrc.js中配置:
module.exports = {
...
parserOptions: {
+ parser: 'babel-eslint',
ecmaVersion: 2018,
sourceType: 'module'
}
...
}
懒加载使用
component: () => import(/webpackChunkName:'name'/'@/views/name.vue')
router/index.js
文件修改:
import Vue from 'vue';
import VueRouter from 'vue-router';
import main from '@/views/main.vue';
Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'main',
component: main
},
{
path: '/auth',
name: 'auth',
meta: {
// auth字段表示需要权限才能进入
auth: true
},
component: () => import(/*webpackChunkName:'auth'*/'@/views/auth.vue')
},
{
// 作为拦截后的展示页面
path: '/403',
name: '403',
// 这里的import eslint一直报错,有人知道是为什么吗。。
component: () => import(/*webpackChunkName:'403'*/'@/views/403.vue')
},
{
// 所有不存在的路由都会跳转到404
path: '*',
name: '404',
component: () => import(/*webpackChunkName:'404'*/'@/views/404.vue')
}
];
const router = new VueRouter({
routes
});
export default router;
路由拦截
增加3个页面auth.vue
、403.vue
、404.vue
,内容自定义,用来展示路由拦截的例子。
auth.vue
页面展示需要权限的内容403.vue
提示没有权限
修改main.js
。
...
router.beforeEach((to, from, next) => {
if (to.meta.auth) {
if (!localStorage.getItem('token')) {
router.push('/403');
} else {
next();
}
} else {
next();
}
});
...
这时候想要进入auth就无法进入,会直接进入403页面,需要在
localStorage
中添加token: value
。
filter
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示。
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
创建filter.js
文件
这是一个格式化的函数例子
// 时间格式化
const dateFormatter = (formatter, date) => {
date = date ? new Date(date) : new Date();
const Y = date.getFullYear() + '';
const M = date.getMonth() + 1;
const D = date.getDate();
const H = date.getHours();
const m = date.getMinutes();
const s = date.getSeconds();
return formatter
.replace(/YYYY|yyyy/g, Y)
.replace(/YY|yy/g, Y.substr(2, 2))
.replace(/MM/g, (M < 10 ? '0' : '') + M)
.replace(/DD/g, (D < 10 ? '0' : '') + D)
.replace(/HH|hh/g, (H < 10 ? '0' : '') + H)
.replace(/mm/g, (m < 10 ? '0' : '') + m)
.replace(/ss/g, (s < 10 ? '0' : '') + s);
};
// 方便扩展
export { dateFormatter }
定义全局过滤器并使用
main.js
修改:
...
import * as filters from './filter';
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key]);
});
...
在代码中使用
<template>
<div>
<p>需要被拦截的页面</p>
<div class="money">{{ date | dateFormatter('YYYY-MM-DD')}}</div>
</div>
</template>
<script>
export default {
data() {
return {
date: new Date()
}
}
}
</script>
文章到这里就结束,vue项目搭建会上传到GitHub,需要的朋友可以自行拉取,后面的文章会以此为基础。如果有需要优化的地方或者有更好的建议可以在评论区留言(假装很多人看)。
Github仓库:github.com/heiyehk/web…
代码分支在:/tree/dev/20200624-Somefeatures