移动app的UI在设计的时候一般采用750px的宽度设计,而开发的时候一般要适应几种分辨率的设备。可以采用多种布局方式,我这边使用rem来布局--通过修改html节点的fontSize来缩放整个页面。
- 设置缩放的页面最大的宽度以及基准的字体大小
// 设置字体
let docEl = document.documentElement
// let dpr = window.devicePixelRatio
let width = docEl.clientWidth >= 750 ? 750 : docEl.clientWidth
let fontSize = width / 10
let defaultUIWidth = 750
let fontScale = width / defaultUIWidth
// debugger
document.querySelector('html').style.fontSize = fontSize + 'px'
document.querySelector('body').style.fontSize = 20 * fontScale + 'px'
- 开发时需要把对应的px转换成rem,可以使用stylus-px2rem自动完成,具体的语法参考Stylus
Stylus比起less,sass之类的更加灵活,Stylus是基于js的,如果碰到问题可以自己修改源码,提供的一些内置函数。比如
image-size(img)
,可以获取图片的宽高可以用来自动缩放图片。
Api的处理方式
因为现在大部分Api的处理过程都比较类似,而且代码重复。添加新的api就是复制修改,所以抽象成了工厂函数。
/**
* 自动生成Api
* @param {api配置文件} config
*/
function _apiGenerator (config /* map */) {
let apiNames = Object.keys(config)
for (let name of apiNames) {
let apiRoute = config[name]
// console.log(`==> generate api ${name}`)
let realName = `fetch${name}`
let actions = ['do', 'Update', 'Save', 'Add']
for (let action of actions) {
if (name.indexOf(action) !== -1) {
realName = name
}
}
apiMap[realName] = (formData, extra) => {
// console.log(`==> api url : ${apiRoute.url} \n`)
// 添加时间戳
formData = {...formData, ...{t: new Date().getTime()}}
let url = ''
if (Config.isApp) {
url = `${Config.host}${apiRoute.url}`
} else {
url = apiRoute.url
}
let params
if (apiRoute.type === 'form') {
params = Object.assign(apiRoute.params, formData)
params = _serialize(params)
} else if (apiRoute.type === 'json') {
params = Object.assign(apiRoute.params, formData)
if (params.hasOwnProperty('pageNum')) {
url += params.pageNum
delete params.pageNum
}
params = JSON.stringify(params, null, 2)
} else if (apiRoute.type === 'mix') {
params = Object.assign(apiRoute.params, formData)
params = _serialize(params)
url += '?' + params
params = JSON.stringify({ ...apiRoute.extra, ...extra }, null, 2)
} else {
// if (apiRoute.type === 'url') {
params = Object.assign(apiRoute.params || {}, formData)
if (params.hasOwnProperty('pageNum')) {
url += params.pageNum
delete params.pageNum
}
params = _serialize(params)
url += '?' + params
params = null
}
return fetch(url, {
method: apiRoute.method,
body: params,
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
credentials: 'same-origin'
}).then(checkStatus)
}
}
}
结合Vuex使用时发现有些接口是用来修改数据的,并不需要绑定数据到Vuex,所以我就在定义Api方法的时候添加了几个action(save, do, update, add)。这些接口直接返回数据,进行异步处理。
也是用工厂函数来生成对应的Vuex的Actions:
function _factory (ApiMap /* ApiMap */) {
for (let api in ApiMap) {
actions[api] = ({commit}, params) => {
return Api[api](params).then(data => {
return _checkData(data).then(data => {
commit(api, { ...data, ...params })
return data
}).catch(data => {
commit(api, {...data, ...params})
return data
})
}).catch(err => {
// 网络问题
console.log('Network error ' + err.message)
})
}
}
}
在不需要绑定数据的接口有两种使用方法:
- 直接使用接口
Api.SaveName(params).then(data => {
// TODO
})
或者
this.$store.dispatch('SaveName', params).then(data => {
// TODO
})
UI使用的是滴滴出品Cube-UI
提供了基本组件和扩展方法。