# 概述
为统一项目前端部分的代码组织风格,做一些探讨。这里讨论 请求接口写法和vuex的使用。因为请求回来的数据往往有可能要放到vuex中。(这里默认项目要使用vuex)
## 请求接口
先看一些老项目的代码<br>
1 vue-resource<br>
除了共用的用户信息和权限放在vuex外其他的都是每个页面自己组织组件的数据,写法如下:
ApiUtils.httpGet('/main/api/addressbook/role/list/flat', {}, ({ data }) => {
self.roles = data.roleFlats.filter(r => r.roleStatus === 1);
}, msg => self.$message.error(msg))
特点:路径 参数 成功的回调 失败的回调 都是在一起的,每个接口都是这样的一个逻辑模板。以后的项目不再使用vue-resource<br>
2 axios
// 定义
export function saveSub (sub) {
return request({
url: '/sub',
method: sub.id === 0 ? 'post' : 'put',
data: sub
})
}
// 使用
import { saveSub } from 'path'
saveSub(parameter)
.then(res => {
console.log('getRoleList', res)
})
.catch(err => {
console.log(err)
})
特点:统一定义,按需导入使用,调用时只传参数,可以结合es7 await async 语法简化操作。<br>
## 结合vuex的使用
//定义
const request = (method, url, data = {}) => {
return conn.request({
method,
url,
data
}).then(data => ({
data
})).catch(err => ({
err
}))
}
// 导出定义
export function getUserInfo: params => request('get', `/main/auth/api/userInfo`, params)
// vuex里
import { getUserInfo } from '' “
actions = {
async getUserInfo({commit}) {
const {data} = await api.getUserInfo({});
if (data) {
await commit('updateUser', data.data);
}
},
mutations = {
updateUser(state, value) {
state.user = value.userInfo.member;
state.resources = value.userInfo.resources.filter(({service}) => service === __SYMBOL);
},
}
state = {
user: {},
resources: []
}
// 页面调用
import { mapActions } from 'vuex'
methods: {
...mapActions({
getUserInfo: 'auth/getUserInfo'
}),
mounted() {
this.getUserInfo();
}
特点:定义好请求方法后在vuex里的action再调用,mutation也相应定义,数据存在state中,页面调用vuex的方法就可以了,这样的写法页面部分代码会比较少。<br>
关于vuex:vuex源码有1200行,核心原理是,使用了Vue.mixin(),可以使用vue的钩子函数,和把store里的数据传到vue的data中实现响应式。再一个递归把store对象挂在每一个组件上实现共享。<br>
编程上来说,就是一种面向对象的编程思想,vuex可以看作一个全局对象,里面可以放数据 方法,然后面向vuex对象按需取用。最大特点就是数据状态共享,方法共享。可以统一管理,方便拓展<br>
问了不少同行,对使用vuex的看法大概都是,复杂的,多组件共享的数据才放到vuex,单页面的数据还是放在自己的页面中。<br>
不过多使用vuex的理由:增加一个全局对象(堆内存),数据过多就会太重,写法也复杂。<br>
## 总结:
统一定义调用api接口的方法,export 导出,然后要使用时按需导入即可,尽量使用async await语法简化成同步的写法,这里的统一不是一个文件的意思,可按实际情况分文件。全局共享的数据(如:用户信息,权限信息)等放在vuex中,多个组件要共享的数据采用动态注册模块的方式放到vuex中(也就是在要使用它的时候再挂载),这样在开始加载时vuex对象就不会那么大了(这样的方式要独立建一个文件和选择合适的生命周期函数去动态挂载)。<br>
注意:<br>
1.如果请求回来的数据要经过前端做复杂的算法处理之后再展示的话,复杂的处理函数不要写在vuex中(vuex的责任不是承载复杂的数据处理函数),可以单独写然后引入使用。在页面的话,要复用的就写成工具函数方便复用。单个页面使用就可以定义在最开始的地方,后面调用。
<br>
2.单个.vue文件代码最好不要超过700行,template多可以拆分成组件,js多就分一个.js文件,css多分.css文件。
<br>
3.同一页面中 父子组件传值使用最简单的props和$emit/on监听事件的方式,兄弟组件复杂的可以借助vuex,简单还是使用中心事件的方式较好(或者vue提供的其他方式,如:$parent/$childer,注入等方式)
<br>
使用vuex全局注册数据的写法使用vue的前端如果不会就先不要出来工作了。下面展示一个多组件共享数据动态注册到vuex的参考写法<br>
//单独文件定义 模块vuex
const state = {...}
const action = {...}
const mutations = {...}
const getters = {...}
export default {
state,
action,
mutations,
getters
}
// 按实际情况选择一个合适的组件进行动态注册vuex模块(所谓合适就是你要用到的vuex共享数据的组件,也可以采用分路由 建一个index.vue文件的方式)
import vuex from './vuex'
import {modulesMap} from '@/components/index/global/store'
export default {
created() {
const moduleName = 'user'
// 如果modulesMap里面没有此模块名,说明是第一次加载,那么注册vuex的模块
if (!modulesMap[moduleName]) {
modulesMap[moduleName] = true
this.$store.registerModule(moduleName, vuex)
}
// 热重载
if (module.hot) {
module.hot.accept(['./vuex'], () => {
this.$store.hotUpdate({
modules: {[moduleName]: vuex}
})
})
}
}
}
### api写法示例(不写在vuex中的方式)
//集中定义
const request = (method, url, data = {}) => {
return conn.request({
method,
url,
data
}).then(data => data
).catch(err => ({
err
}))
}
// 登陆
export function login (params){ return request('post', '/login/auth', params)}
// 页面使用
import { login } from '@/api/request'
async usernameLogin() {
let self = this
const data = await login({ username: self.username, password: self.password, type: 1})
console.log('log', data)
if(data.errcode === 0){
location.href = 'index.html'
}else {
self.loading = false
self.$message.error(data.errmsg)
} },