0.基础准备
1.环境安装
全局安装vue-cli(已装忽略)
npm install -g @vue/cli
2.创建uni-app基础框架
创建正式版
vue create -p dcloudio/uni-preset-vue my-project(项目名字)
之后,会提示选择项目模板,搭建框架选择默认模板
创建完成后,会生成对应名字的vue cli3项目,这个就是uni-app框架的基础,需要在此基础上改造,以适应日常开发情景。
3.启动vue cli3图形界面
vue cli3图形界面
vue ui
4.安装依赖
需要安装以下依赖:
样式预处理器(使用的是sass,也可以使用less等)
node-sass sass-loader
以node-sass为例,演示安装步骤:
1.在vue cli3图形界面中的左侧菜单选中【依赖】,点击右侧【安装依赖】按钮
2.在弹出的对话框中选择【运行依赖】【开发依赖】,node-sass是开发依赖,所以选择开发依赖,然后在搜索框中搜索node-sass
3.选择需要的node-sass依赖,点击对话框右下角的【安装node-sass】
4.在终端中会显示正在安装依赖
5.安装完成后,在【依赖】菜单中可以看到刚刚安装好的依赖
6.在项目的package.json中,会增加刚刚安装好的依赖,到此,说明依赖安装成功
5.安装插件
1.在vue cli3图形界面中的左侧菜单选中【插件】,可以看到已经安装的插件
2.点击右侧【添加插件】按钮
3.打开添加插件后可以看到默认选中了【所有插件】
4.在搜索框中输入eslint,按下回车键搜索,在搜索结果中选中@vue/cli-plugin-eslint插件,然后点击【安装】
5.在终端中会显示正在安装插件
6.插件安装完成后,会进入【配置插件】面板
7.点击右侧【selected】下拉选择框,选中【standard】风格(可以根据自己的项目选择合适的风格)
8.点击【完成安装】按钮
9.可以看到正在安装相关依赖
10.安装完成后会进入【文件改动】面板,点击【继续】按钮即可
11.可以看到插件已经安装完成
12.在项目的package.json中,会增加刚刚安装好的插件和依赖,到此,说明插件安装成功
6.添加配置
1.eslintignore配置
在根路径下添加【.eslintignore】文件,设置忽略eslint检查文件
在【.eslintignore】文件中写入以下内容即可
dist/*
plugins/*
node_modules/*
2.eslint配置
在.eslintrc.js文件中写入以下内容(可以根据需要配置eslint规则)
module.exports = {
root: true,
env: {
browser: true,
node: true
},
extends: [
'plugin:vue/essential',
'@vue/standard'
],
globals: {
Vue: true,
uni: true,
wx: true,
getApp: true,
feConfig: true,
Util: true,
Enums: true
},
parserOptions: {
parser: 'babel-eslint'
},
// add your custom rules here
rules: {
// js
'indent': ['off', 4],
// 开启语句强制分号结尾
'semi': ["error", "always"],
// 函数前面的空格
"space-before-function-paren": ["error", {
"anonymous": "never",
"named": "never",
"asyncArrow": "never"
}],
// allow paren-less arrow functions
'arrow-parens': 0,
// allow async-await
'generator-star-spacing': 0,
// only allow console in development
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
//
// Vue 可能的错误
//
// 禁止重复的二级键名
'vue/no-dupe-keys': 'error',
// 禁止出现语法错误
'vue/no-parsing-error': 'error',
// 禁止覆盖保留字
// 'vue/no-reservered-keys': 'error',
// 组件的 data 属性的值必须是一个函数
// @off 没必要限制
'vue/no-shared-component-data': 'error',
// 可以让 <template> 使用 key 属性
'vue/no-template-key': 'off',
// render 函数必须有返回值
'vue/require-render-return': 'error',
// prop 的默认值必须匹配它的类型
'vue/require-valid-default-prop': 'error',
// 计算属性必须有返回值
'vue/return-in-computed-property': 'error',
// template 的根节点必须合法
'vue/valid-template-root': 'error',
// v-bind 指令必须合法
'vue/valid-v-bind': 'error',
// v-cloak 指令必须合法
'vue/valid-v-cloak': 'error',
// v-else-if 指令必须合法
'vue/valid-v-else-if': 'error',
// v-else 指令必须合法
'vue/valid-v-else': 'error',
// v-for 指令必须合法
'vue/valid-v-for': 'error',
// v-html 指令必须合法
'vue/valid-v-html': 'error',
// v-if 指令必须合法
'vue/valid-v-if': 'error',
// v-model 指令必须合法
'vue/valid-v-model': 'error',
// v-on 指令必须合法
'vue/valid-v-on': 'error',
// v-once 指令必须合法
'vue/valid-v-once': 'error',
// v-pre 指令必须合法
'vue/valid-v-pre': 'error',
// v-show 指令必须合法
'vue/valid-v-show': 'error',
// v-text 指令必须合法
'vue/valid-v-text': 'error',
//
//
// 最佳实践
//
// @fixable html 的结束标签必须符合规定
// 有的标签不必严格符合规定,如 <br> 或 <br/> 都应该是合法的, 在此列为警告
'vue/html-end-tags': 'off',
// 计算属性禁止包含异步方法
'vue/no-async-in-computed-properties': 'error',
// 禁止出现难以理解的 v-if 和 v-for
'vue/no-confusing-v-for-v-if': 'error',
// 禁止出现重复的属性
'vue/no-duplicate-attributes': 'error',
// 禁止在计算属性中对属性修改, 是具体情况而定,有时候可能会用到,列为warn;
'vue/no-side-effects-in-computed-properties': 'warn',
// 禁止在 <textarea> 中出现 {{message}}
'vue/no-textarea-mustache': 'error',
// 组件的属性必须为一定的顺序
'vue/order-in-components': [2, {
"order": [
"el",
["name", "parent"],
"functional",
"delimiters",
["components", "directives", "filters"],
["extends", "mixins"],
["model", "props", "propsData"],
["data", "computed"],
["watch", "LIFECYCLE_HOOKS"],
"methods",
["template", "render", "renderError"]
]
}],
// <component> 必须有 v-bind:is
'vue/require-component-is': 'error',
// prop 必须有类型限制
'vue/require-prop-types': 'error',
// v-for 指令的元素必须有 v-bind:key
'vue/require-v-for-key': 'error',
//
//
// 风格问题
//
// @fixable 限制自定义组件的属性风格, Vue风格指南强烈建议,但和一般习惯差别略大,列为warn;
'vue/attribute-hyphenation': 'warn',
// html 属性值必须用双引号括起来
'vue/html-quotes': 'error',
// @fixable 没有内容时,组件必须自闭和。只要闭合即可,不限制。
'vue/html-self-closing': 'off',
// 限制每行允许的最多属性数量
// @off 没必要限制。但多行时应该每行一个属性。
'vue/max-attributes-per-line': 'off',
// @fixable 限制组件的 name 属性的值的风格
'vue/name-property-casing': 'error',
// @fixable 要求花括号插值两边必须有空格
'vue/mustache-interpolation-spacing': 'error',
// @fixable 禁止出现连续空格
'vue/no-multi-spaces': 'error',
// @fixable 限制 v-bind 的风格, 统一简写形式
'vue/v-bind-style': 'error',
// @fixable 限制 v-on 的风格,统一简写形式
'vue/v-on-style': 'error',
//
//
// 变量
//
// 定义了的 jsx element 必须使用
'vue/jsx-uses-vars': 'error',
'no-tabs': 'off'
}
}
3.开发环境配置
在【src】目录下新建【feConfig】目录
在【feConfig】目录下新建development.js、production.js、test.js三个文件分别对应开发环境、正式环境、测试环境
在三个文件内分别写入以下内容
// development.js
module.exports = {
api: {
// #ifndef H5
base: 'https://www.fastmock.site/mock/b0e7c0fd4d0c17abe3d7bda7f9be5104/demo'
// #endif
}
};
// production.js
module.exports = {
api: {
base: 'https://www.fastmock.site/mock/b0e7c0fd4d0c17abe3d7bda7f9be5104/demo'
}
};
// test.js
module.exports = {
api: {
base: 'https://www.fastmock.site/mock/b0e7c0fd4d0c17abe3d7bda7f9be5104/demo'
}
};
小贴士:https://www.fastmock.site是一个免费的mock数据平台
4.vue.config配置(先创建好文件,后面会详细讲解配置)
在根路径下添加【vue.config.js】文件,增加cli配置
写入以下内容
const path = require('path');
const webpack = require('webpack');
const configEnv = process.env.CONFIG_ENV;
module.exports = {
devServer: {
host: '0.0.0.0',
port: 8080,
open: true,
proxy: {
'/v1': {
target: 'https://www.fastmock.site/mock/b0e7c0fd4d0c17abe3d7bda7f9be5104/demo',
changeOrigin: true
},
'/v2': {
target: 'https://www.fastmock.site/mock/b0e7c0fd4d0c17abe3d7bda7f9be5104/demo',
changeOrigin: true
}
},
disableHostCheck: true
},
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
feConfig: path.resolve('.', './src/feConfig/' + (configEnv || 'development')),
Util: path.resolve('.', './src/utils/util'),
Enums: path.resolve('.', './src/contants/enum')
})
]
},
transpileDependencies: ['luch-request']
};
7.配置启动脚本
在项目的package.json中,可以看到【scripts】,启动脚本需要在里面配置。默认的命令有两类,dev和build,对应开发环境和生产环境,一般项目开发还需要测试环境,所以需要对启动命令进行改进
如何配置测试环境呢?
首先需要知道【环境变量】的概念,在node中通过process.env.NODE_ENV的值区分运行环境也就是【NODE_ENV】参数的值。在vue cli3中,【NODE_ENV】的值默认支持development和production两种,对应开发及生产环境。
想要支持测试环境,我们可以自己定义一个变量来区分当前运行环境,如:【CONFIG_ENV】,值为development、test、production,对应开发、测试、生成环境。
对应修改调整启动脚本如下:
"scripts": {
"serve": "npm run dev:h5",
"test": "npm run test:h5",
"build": "npm run build:h5",
"dev:h5": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve",
"dev:mp-weixin": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch",
"dev:mp-360": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=mp-360 vue-cli-service uni-build --watch",
"dev:mp-alipay": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=mp-alipay vue-cli-service uni-build --watch",
"dev:mp-baidu": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=mp-baidu vue-cli-service uni-build --watch",
"dev:mp-kuaishou": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build --watch",
"dev:mp-qq": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=mp-qq vue-cli-service uni-build --watch",
"dev:mp-toutiao": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=mp-toutiao vue-cli-service uni-build --watch",
"dev:quickapp-native": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=quickapp-native vue-cli-service uni-build --watch",
"dev:quickapp-webview": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=quickapp-webview vue-cli-service uni-build --watch",
"dev:quickapp-webview-huawei": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build --watch",
"dev:quickapp-webview-union": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=quickapp-webview-union vue-cli-service uni-build --watch",
"dev:app-plus": "cross-env CONFIG_ENV=development NODE_ENV=development UNI_PLATFORM=app-plus vue-cli-service uni-build --watch",
"dev:custom": "cross-env CONFIG_ENV=development NODE_ENV=development uniapp-cli custom",
"test:h5": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build",
"test:mp-weixin": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build",
"test:mp-360": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=mp-360 vue-cli-service uni-build",
"test:mp-alipay": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build",
"test:mp-baidu": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build",
"test:mp-kuaishou": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build",
"test:mp-qq": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=mp-qq vue-cli-service uni-build",
"test:mp-toutiao": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=mp-toutiao vue-cli-service uni-build",
"test:quickapp-native": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=quickapp-native vue-cli-service uni-build",
"test:quickapp-webview": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=quickapp-webview vue-cli-service uni-build",
"test:quickapp-webview-huawei": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build",
"test:quickapp-webview-union": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=quickapp-webview-union vue-cli-service uni-build",
"test:app-plus": "cross-env CONFIG_ENV=test NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build",
"test:custom": "cross-env CONFIG_ENV=test NODE_ENV=production uniapp-cli custom",
"build:h5": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build",
"build:mp-weixin": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build",
"build:mp-360": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=mp-360 vue-cli-service uni-build",
"build:mp-alipay": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build",
"build:mp-baidu": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build",
"build:mp-kuaishou": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build",
"build:mp-qq": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=mp-qq vue-cli-service uni-build",
"build:mp-toutiao": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=mp-toutiao vue-cli-service uni-build",
"build:quickapp-native": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=quickapp-native vue-cli-service uni-build",
"build:quickapp-webview": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=quickapp-webview vue-cli-service uni-build",
"build:quickapp-webview-huawei": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build",
"build:quickapp-webview-union": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=quickapp-webview-union vue-cli-service uni-build",
"build:app-plus": "cross-env CONFIG_ENV=production NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build",
"build:custom": "cross-env CONFIG_ENV=production NODE_ENV=production uniapp-cli custom",
"serve:quickapp-native": "node node_modules/@dcloudio/uni-quickapp-native/bin/serve.js",
"jest:android": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=android jest -i",
"jest:h5": "cross-env UNI_PLATFORM=h5 jest -i",
"jest:ios": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=ios jest -i",
"jest:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu jest -i",
"jest:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin jest -i",
"lint": "vue-cli-service lint",
"info": "node node_modules/@dcloudio/vue-cli-plugin-uni/commands/info.js"
}
其中【CONFIG_ENV】的值对应运行环境,如何识别CONFIG_ENV的值去区分环境呢?
在【vue.config.js】文件中定义了变量接收CONFIG_ENV的值,区分开发环境,代码如下:
const path = require('path');
const webpack = require('webpack');
const configEnv = process.env.CONFIG_ENV; // 环境变量
...
...
// 注入全局依赖,根据环境加载不同的文件,区分不同的运行环境
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
feConfig: path.resolve('.', './src/feConfig/' + (configEnv || 'development'))
...
})
]
}
到此,项目的基础功能就完成了,运行
npm run serve
在浏览器中我们可以看到demo页面
在项目开发中,通常会配置启动端口和代理,在【vue.config.js】文件中加入以下代码即可配置成功
...
...
module.exports = {
devServer: {
host: '0.0.0.0',
port: 8080,
open: true,
proxy: {
'/v1': {
target: 'https://www.fastmock.site/mock/b0e7c0fd4d0c17abe3d7bda7f9be5104/demo',
changeOrigin: true
},
'/v2': {
target: 'https://www.fastmock.site/mock/b0e7c0fd4d0c17abe3d7bda7f9be5104/demo',
changeOrigin: true
}
},
disableHostCheck: true
}
...
...
};
8.uView
uni-app生态非常丰富,uView是uni-app生态中优秀的UI框架,组件丰富,可以极大地提高开发效率,你也可以选择其它优秀的UI库,例如:uni-ui
在脚手架中如何安装配置uView呢?
1.使用npm形式安装(也可以选择下载后放入项目)
npm install uview-ui
2.引入uView主JS库
在项目根目录中的main.js中,引入并使用uView的JS库,注意这两行要放在import Vue之后
// main.js
import uView from "uview-ui";
Vue.use(uView);
3.在引入uView的全局SCSS主题文件
在项目根目录的uni.scss中引入此文件
/* uni.scss */
@import 'uview-ui/theme.scss';
4.引入uView基础样式
在App.vue中首行的位置引入,注意给style标签加入lang=”scss”属性
<style lang="scss">
/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
@import "uview-ui/index.scss";
</style>
5.配置easycom组件模式(easycom可以在页面直接使用组件,无需通过import引入组件)
此配置需要在项目根目录的pages.json中进行
// pages.json
{
"easycom": {
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
},
// 此为本身已有的内容
"pages": [
// ......
]
}
9.luch-request
开发小程序痛点之一就是发起请求,wx.request太过简单,没有类似axios的请求拦截器和响应拦截器,在需要对请求做统一处理、复杂处理时有明显短板,诸如请求loading、cookie、token二次请求、响应状态码统一处理等,需要自己在wx.request基础上大量封装,uni-app中uni.request除了上述问题外,还需要在h5平台携带跨域凭证,使问题变得更加地复杂,无法满足项目级开发要求。
luch-request是基于Promise开发的uni-app跨平台请求库,它解决了使用uni.request的诸多问题,易用、简单、高度自定义,是一个特别用在项目级别的请求库。
在脚手架中如何安装配置luch-request呢?
1.使用npm安装
npm i luch-request -S
2.在【vue.config.js】文件中,增加以下内容
// vue.config.js
module.exports = {
transpileDependencies: ['luch-request']
}
至此,安装完成,如何体现它的诸多优点呢?
1.在【src】目录下新建【utils】文件夹
2.在【utils】文件夹下新增promisify.js、token.js
分别写入以下代码
// promisify.js
// 普通函数转promise
module.exports = fn => {
return function(obj = {}) {
return new Promise((resolve, reject) => {
fn({ ...obj, success(res) { resolve(res); }, fail(res) { reject(res); } });
});
};
};
// token.js
import promisify from './promisify.js';
import { http } from '@/plugins/luch-request/config.js';
/**
* 获取token
*/
const getToken = () => {
const login = promisify(uni.login);
// #ifndef H5
return login().then(resCode => {
return http.post(feConfig.token, {
data: {
grant_type: 'wx_login',
username: feConfig.appid,
password: resCode.code
},
header: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: 'Basic ' + feConfig.client_base64
}
});
});
// #endif
};
module.exports = {
getToken
};
3.util.js是常用工具函数库,可以放一些常用函数在全局引用
// vue.config.js
...
...
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
Util: path.resolve('.', './src/utils/util') // 全局注入Util
})
]
}
4.在【src】目录下新建【plugins】文件夹
5.在【plugins】下新建【luch-request】目录,并在【luch-request】下新建【config.js】文件
6.在【config.js】文件写入以下内容
/**
* 文档: https://www.quanzhan.co/luch-request/
* github: https://github.com/lei-mu/luch-request
* DCloud: http://ext.dcloud.net.cn/plugin?id=392
*/
import Request from 'luch-request';
import Token from '../../utils/token.js';
const http = new Request();
/**
* 全局默认配置
* @param {Object} config 发送请求的配置数据
*/
http.setConfig(config => {
config.baseURL = feConfig.api.base; // 根路径
config.header = { // 请求头
// 'X-Auth-Token': 'xxxx',
// contentType: "application/x-www-form-urlencoded"
'Content-Type': 'application/json'
};
config.custom = { // 自定义参数,如果局部custom与全局custom有同名属性,则后面的属性会覆盖前面的属性,相当于Object.assign(全局,局部)
loading: true // 默认全局请求开启loading
};
config.withCredentials = true; // 跨域请求时携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+)
return config;
});
/**
* 请求拦截器
* @param {Object} config 发送请求的配置数据
*/
http.interceptors.request.use(config => {
config.custom.loading && uni.showLoading({ title: '加载中', mask: true }); // 请求配置中的custom自定义参数中loading为true则显示loading
getToken() && (config.header.token = getToken()); // 有token则在请求头中携带token
getCookie() && (config.header.cookie = getCookie()); // 有cookie则在请求头中携带cookie,h5中浏览器默认携带cookie,此方法不生效,小程序中需手动携带cookie
return config;
}, err => {
showToast(err);
uni.hideLoading();
return Promise.reject(err);
});
/**
* 响应拦截器
* @param {Object} res 请求返回的数据
*/
http.interceptors.response.use(async res => {
let data = res.hasOwnProperty('data') ? res.data : res.hasOwnProperty('Data') ? res.Data : null; // eslint-disable-line
let code = data.hasOwnProperty('code') ? data.code : data.hasOwnProperty('Code') ? data.Code : null; // eslint-disable-line
saveCookie(res.header['set-cookie'] || res.header['Set-Cookie']); // 手动种cookie,h5中浏览器自动种cookie,小程序中需手动中cookie
try {
return await handleCode({ data, code, res });
} catch (err) {
uni.hideLoading();
return Promise.reject(err);
}
}, err => {
return Promise.reject(err);
});
/**
* 处理 http状态码
* @param {object} o
* @param {object} o.data 请求返回的数据
* @param {string|number} o.code http状态码
* @param {object} o.res 本次请求的配置和返回数据
* @return {object|Promise<reject>}
*/
function handleCode({ data, code, res }) {
const STATUS = {
'0'() { // 请求成功
return data;
},
'1000'() { // token过期,重新获取token
return getApiToken().then(saveToken).then(() => http.request(res.config));
}
};
uni.hideLoading();
return STATUS[code] ? STATUS[code]() : Promise.reject(data, res); // 有状态码但不在这个封装的配置里,就直接进入 `fail`
}
/**
* 获取 `localStorage` 中的 `cookie`
* @return {string} cookie字符串
*/
function getCookie() {
return uni.getStorageSync('cookie');
}
/**
* 保存 `cookie` 到 `localStorage`
* @param {string} cookie cookie字符串
* @return {void}
*/
function saveCookie(cookie) {
cookie && uni.setStorageSync('cookie', cookie);
}
/**
* 重新请求更新获取 `token`
* @return {Promise}
*/
function getApiToken() {
return Token.getToken().then((res) => {
return res.token;
});
}
/**
* 获取 `localStorage` 中的 `token`
* @return {string} token字符串
*/
function getToken() {
return uni.getStorageSync('token');
}
/**
* 保存 `token` 到 `localStorage`
* @param {string} token token字符串
* @return {void}
*/
function saveToken(token) {
uni.setStorageSync('token', token);
}
/**
* 显示消息提示框
* @param {String} msg
* @return {void}
*/
function showToast(msg) {
uni.showToast({
title: msg,
icon: 'none',
duration: 2000
});
}
export { http };
7.在【src】下【main.js】中增加以下内容
// main.js
import { http } from '@/plugins/luch-request/config.js';
Vue.prototype.$http = http;
8.在项目中使用
this.$http.post('/v1/token').then(res => {
console.log('%c 🍏 res: ', 'font-size:20px;background-color: #F5CE50;color:#fff;', res);
}).catch(err => {
console.log('%c 🥜 err: ', 'font-size:20px;background-color: #33A5FF;color:#fff;', err);
});
10.uCharts
开发小程序的痛点之一就是图表,wx-charts配色差、适用性差,echarts小程序版,体积大、bug多,F2上手难度大、体积大,在uni-app的生态中,UCharts是一个出色的跨端图表库。
在脚手架中如何安装配置UCharts呢?
1.在【src】目录下新建【components】文件夹
2.下载UCharts代码,放入【components】的UCharts目录中
3.在项目中使用
import uCharts from '../../components/u-charts/u-charts.js';
11.contants
在项目开发中,会有一些常量,可以放在【contants】目录
如枚举值可以新建一个【enum.js】存放
在【vue.config.js】文件中注入全局依赖Enums,然后就可以在全局使用
// 注入全局依赖,根据环境加载不同的文件,区分不同的运行环境
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
Enums: path.resolve('.', './src/contants/enum')
})
]
}
12.参考文档
uni-app快速上手:https://uniapp.dcloud.io/quickstart?id=_2-%e9%80%9a%e8%bf%87vue-cli%e5%91%bd%e4%bb%a4%e8%a1%8c
uView:https://uviewui.com
luch-request:https://www.quanzhan.co/luch-request
uCharts:http://doc.ucharts.cn/1073940
13.结语
按文档配置只是入门,想要有更深入的了解,需要思考为什么使用uView、luch-request、uCharts,有没有更好的组件插件,这些组件插件为什么这样配置,目录结构为什么是这样的,可不可以换一种方式,等等,凡事多问一个为什么,看其表象,究其本质。
当然,初次学习可以按部就班按照文档一步步学习,虽然不明所以,但是多次尝试后自然就会明白其中奥秘与精髓。
水平有限,仓促书写,难免错漏,欢迎指正。