最近新写一个项目,记录下新建项目过程及坑处理。供新人查看~ 1 搭建脚手架 cnpm install @vue/cli -gvue create test 2 加入eslint 在 package.json 中加入rules,具体的rules配置从这里找(https://www.
最近新写一个项目,记录下新建项目过程及坑处理。供新人查看~
1 搭建脚手架cnpm install @vue/cli -g
vue create test
2 加入eslint
-
在
package.json
中加入rules,具体的rules配置从这里找(https://www.cnblogs.com/webhmy/p/14776124.html)适合自己项目的配置项
-
在
vue.config.js
中配置编译的时候lint代码
lintOnSave: true, // 编译的时候lint代码
3 加入tslint
vue项目中加入tslint
4 添加githooks因为多人开发,很多人不会carelint的错误,因此在提交前统一自动化执行lint
cnpm install yorkie --save-dev
cnpm install lint-staged --save-dev
在package.json中配置
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,vue}": [
"vue-cli-service lint",
"git add"
]
}
5 路由管理 vue-router
npm install vue-router
main.ts
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: (h) => h(App)
}).$mount('#app')
route -index.ts
import Vue from 'vue'
import VueRouter, { RouteConfig } from 'vue-router'
Vue.use(VueRouter)
const asyncFiles = require.context('./routeModules', true, /\.ts$/)
let permissionModules: Array<RouteConfig> = []
asyncFiles.keys().forEach((key) => {
permissionModules = permissionModules.concat(asyncFiles(key).default)
})
const routes: Array<RouteConfig> = [
{ path: '/', redirect: '/home' },
...permissionModules
]
const router = new VueRouter({
routes
});
export default router;
6 状态管理vuex
npm install vuex
main.ts
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: (h) => h(App)
}).$mount('#app')
store.ts
import Vue from 'vue'
import Vuex from 'vuex'
const states = {};
const contexts = require.context('./stateModules', true, /\.ts$/);
contexts.keys().forEach(key => {
let name = key.slice(2, -3);
states[name] = contexts(key).default || contexts(key);
})
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
...states
}
})
common.ts
const module = {
state: () => ({
count: 1
}),
mutations: {
increment(state) {
// 这里的 `state` 对象是模块的局部状态
state.count++
}
},
actions: {
batchincrement({commit}){
commit('someMutation') // -> 'foo/someMutation'
commit('someMutation', null, { root: true }) // -> 'someMutation'
}
}
}
export default module
模块中使用
this.$store.state.common.count
this.$store.commit('increment')
this.$store.dispatch('batchincrement')
7 加入iview-design
cnpm install view-design --save
main.ts
import 'view-design/dist/styles/iview.css'
/**
* 按需引入iview
* 常用的按需引入, 不常用的组件里单独引入
*/
import { Button, Table } from 'view-design';
Vue.component('Button', Button);
Vue.component('Table', Table);
借助插件 babel-plugin-import可以实现按需加载组件,减少文件体积。首先安装,并在文件 .babelrc 中配置:
npm install babel-plugin-import --save-dev
// .babelrc
{
"plugins": [["import", {
"libraryName": "view-design",
"libraryDirectory": "src/components"
}]]
}
8 配置axios
cnpm install axios --save
http index.ts
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import { Message } from 'view-design';
import store from '../store'
const $Message: any = Message;
class Interceptors {
public instance: any;
constructor(baseURL?: string) {
// 创建axios实例
this.instance = axios.create({
baseURL: baseURL ? baseURL : '/'
});
// 初始化拦截器
this.initInterceptors(baseURL);
}
public initInterceptors(baseURL?: string): void {
this.instance.defaults.withCredentials = true;
// 请求拦截器
this.instance.interceptors.request.use((config: AxiosRequestConfig): AxiosRequestConfig => {
const token = localStorage.userToken;
if (token) {
config.headers.Authorization = token;
}
return config;
}, (error: any) => {
// 关闭全局loading
$Message.success(error.desc);
return Promise.reject(error)
});
// 响应拦截器
this.instance.interceptors.response.use((Response: AxiosResponse<any>) => {
const { data } = Response;
const { retcode, desc } = data;
if ((retcode === '000000' || retcode === undefined) || (Response.config as any).isBolb) {
return Promise.resolve(Response.data);
} else if (retcode === '401' || retcode === '200008') {
$Message.error('无权限,请重新登录!');
} else {
// ainote token失效
if (data === 'Not Authorized') {
$Message.error(data);
window.open('/')
} else {
if (desc) $Message.error(desc);
return Promise.reject(Response.data);
}
}
})
}
public getInterceptors() {
return this.instance;
}
}
interface ResponseOptions {
config: object;
data: {
retcode: string;
desc: string;
[propName: string]: any;
};
status: number;
headers: object;
[propName: string]: object | number | string | [];
}
interface ApiOptions {
url: string; // 请求链接
params?: object; // 请求参数
method: string; // 请求方法
headers?: object; // 请求头
[keyName: string]: any;// 其他参数
}
export class HttpService {
public axios: any;
public baseURL: any;
constructor(baseURL?: string) {
this.baseURL = baseURL;
this.axios = new Interceptors(baseURL).getInterceptors();
}
/**
* 通用请求
* @param {ApiOptions} options 请求参数
*/
public fetch(options: ApiOptions): Promise<object> {
return new Promise((resolve, reject) => {
this.axios(options).then((res: ResponseOptions) => {
resolve(res);
}).catch((err: ResponseOptions) => {
// 请求出错处理todo
if (err && err.response) {
const data = (err.response as any).data || {};
switch ((err.response as any).status) {
case 401:
$Message.error('没有权限,请重新登录');
localStorage.clear();
break;
case 400:
$Message.error(data.message || data.desc || '请求出错');
break;
case 404:
$Message.error(data.message || '请求出错');
break;
case 503:
$Message.error(data.message || '服务器异常');
break;
default:
$Message.error(data.message || '服务器异常');
break;
}
}
reject(err);
})
})
}
}
引用
/**
* 首页接口请求
*/
import { HttpService } from '@/http';
const $HttpService: any = new HttpService('/');
// get 请求
export const getBusinessSceneList = (params) => {
return $HttpService.fetch({
url: '/api/business/scene/list',
method: 'get',
params
});
}
// post 请求
export const createBusinessScene = (data) => {
return $HttpService.fetch({
url: '/api/business/scene',
method: 'post',
data
});
}