1. 设置合理的目录结构
这应该是我最先想到的问题,怎么才能让项目各个模块比较有秩序呢?
项目大概包括了pages,components,resource,utils,env,还有就是需要用到的置于根目录下的一些脚本文件。如下图:
- 先来说下最关键的模块pages和components的组织方式,首先得根据具体的业务逻辑,拆分出不同功能模块,比如个人中心,课程,博客等。每一个模块设置一个文件夹。比如像下图这样
/pages/course
文件夹下面包含了课程模块的所有页面,以及一个/pages/course/components
文件夹(只存放用于课程模块的组件文件)。一些公共的组件,当然得放到最外层的/components
文件夹下面。
/utils
主要存放一些工具文件,比如常量文件,请求封装文件,参数加密方法封装文件,常用函数文件等等。如下图
/resource
顾名思义,是一些静态资源文件,比如一些图片,字体,音频等。/env
用来存放环境变量文件的文件夹,这个在第4小节会细讲,这里就不多赘述了。
小结: 到这里大概已经讲清楚了我的目录结构设置,顺便说下我期间的一些思考。
- 资源文件夹设置,本来有考虑在每个模块目录下设置一个资源文件夹,但是后来实际写代码的时候,发现这样做很不方便。比如到最后的时候我把所有的资源文件都做了压缩处理,想象下如果分散在不同功能目录下的话,那真的要裂开了。还好我意识到了这个问题,及时改过来了。当然
/resource
里面的目录结构也和/pages
相似。方便快速查找。 - 组件目录的设置,方案一每个模块下设置一个组件文件夹,方案二只在跟目录设置组件文件夹。首先方案一与上一条资源文件夹是一样的问题,而且考虑到很多组件在同一功能模块下是通用的,所以方案一不合适。方案二只在根目录设置组件文件夹,考虑到很多组件都是只在某个具体的功能模块才会被使用到,所以方案二也不合适。最终选择了中颗粒度方案,在每个功能模块下设置一个
components
文件夹。
2.登录功能的封装
具体的微信登录流程就不说了,主要说下登录模块的封装吧。大概有以下两种方式:
方式一 注册一个behavior
,然后在需要用到登录的地方引入这个behavior
。behavior
只解决了js代码的复用问题,而且要在需要登录的模块(甚至是父子组件)重复引入。而微信授权依赖原生button组件,所以就要在每个需要登录的组件都设置一个弹窗放置这个button,当然这样可以实现功能,但是很不优雅。
方式二 注册一个公共的登录页面。在所有需要登录的模块,在没有登录的情况下都navigateTo
到这个页面,在这个页面做用户信息授权,登录,存储token
等操作,再nagivateBack
到之前页面,当然之前页面的接口请求最好写在onShow
这个生命周期钩子里面。
小结: 最后当然选择了方案二咯,目前使用下来没有什么问题。想清楚了还是挺简单的,但当时确实花了点时间思考。
3.如何在微信开发者工具里使用scss
在vscode里用当然就很简单,安装一下Easy Sass,配置下setting.json就OK了。然后保存一下就可以在同目录生成.wxss
文件了。但能不能在微信开发者工具里也这么香呢,于是我就翻了文档,果然开发者工具早就支持扩展工具了。具体步骤如下,
1.vscode安装Easy Scss
2.找到扩展文件夹
其解包后的文件夹可以在 ~/.vscode/extensions
(macOS系统) 或 C:\Users\用户名\.vscode\extensions
(Windows系统) 下找到
3.复制扩展文件夹到开发者工具的扩展文件夹中(设置-扩展设置-编辑自定义扩展-打开扩展文件夹),下图所示
4.配置setting.json
小结: 到这里应该就可以在微信开发者工具里愉快的使用scss了。这里再说个小问题吧,就是在mac上不太好找具体的文件位置,所以我是先把vscode的扩展插件先cp到桌面然后再拖到开发者工具的扩展文件夹里面。听起来像是反向代理hhh。
4.如何设置环境变量的小技巧
微信小程序目前为止还没有提供API或者具体的配置方式,给我们设置环境变量,所以还得自己想办法。大概的想法就是设置一个配置文件(/utils/baseData.js
),在需要的地方引入,然后在不同的情况下用node处理配置文件。具体步骤如下:
- 设置一个baseData.js文件
- 在需要的地方引入
这样就完成了第一步,把配置文件引入到项目中
- 在根目录新建
/env
文件夹
在/env
文件夹下创建dev.json
和prod.json
两个json文件,分别用于存放开发环境和生产环境的常量。
- 在package.json的script下新增两条命令,用来启动不同的环境
根据命令行参数,选择/env
下的对应的配置文件
- 在根目录新建
switch.js
文件,利用node处理配置信息。
* 根据命令行运行参数,修改/config.js 里面的项目配置信息,
*/
const fs = require('fs')
const path = require('path')
//源文件
const sourceFiles = {
prefix: '/env/',
dev: 'dev.json',
prod: 'prod.json'
}
//目标文件
const targetFiles = [{
prefix: '/utils/',
filename: 'baseData.js'
}]
const preText = 'module.exports = '
// 获取命令行参数
const cliArgs = process.argv.splice(2)
const env = cliArgs[0]
// 判断是否是 prod 环境
const isProd = env.indexOf('prod') > -1 ? true : false
// 根据不同环境选择不同的源文件
const sourceFile = isProd ? sourceFiles.prod : sourceFiles.dev
// 根据不同环境处理数据
fs.readFile(__dirname + sourceFiles.prefix + sourceFile, (err, data) => {
if (err) {
throw new Error(`Error occurs when reading file ${sourceFile}.nError detail: ${err}`)
process.exit(1)
}
// 获取源文件中的内容
const targetConfig = JSON.parse(data)
// 将获取的内容写入到目标文件中
targetFiles.forEach(function(item, index) {
let result = null
if (item.filename === 'baseData.js') {
result = preText + JSON.stringify(targetConfig, null, 2)
}
console.log(result)
// 写入文件(这里只做简单的强制替换整个文件的内容)
fs.writeFile(__dirname + item.prefix + item.filename, result, 'utf8', (err) => {
if (err) {
throw new Error(`error occurs when reading file ${sourceFile}. Error detail: ${err}`)
process.exit(1)
}
})
})
})
当我们执行不同的命令时,switch.js
会动态的将相应的环境配置写入配置文件(/utils/baseData.js
)中。所以到这里基本完成我们的目标了。但每次切换环境都要运行npm脚本,也不是很方便。
- 所以最后一步很关键,就是配置我们的开发者工具,让它在预览和上传等操作前自动执行对应的npm脚本。
在开发者工具本地设置中,可以勾选启用自定义处理命令,如下图
小结: 这样之后,基本就实现了不同环境,使用不同的变量。每次只要更新对应环境的json
文件,可以说是很方便了。
5.选择合适的UI框架
这个就不具体展开了,参考文章很多 ?汇总9款优秀的开源小程序UI框架
我最后选的vant。因为我对vant比较熟,但是此vant非彼vant啊,和web版本比起来,简直就是丐中丐了,要啥没啥。唉,如果再给我一次机会,我想...
7.其它细节
7.1 页面初始化请求 onLoad or onShow
本来呢基于减少请求次数,减轻服务器压力的考虑。我准备把请求都写在onload里。但开发中发现有些接口数据依赖于登录状态和其它一些状态,比如vip状态,那这些时候呢,放在onshow里更合适些(主要考虑到这些状态会不定时的发生改变)。
7.2 修改数据不一定要setData
下面是开发文档中最佳实践部分摘抄的一段话:
所以有些时候修改数据?不必使用setData,比如分页参数page
,直接this.data.page++
就可以了。
7.3 网络请求的封装
微信提供了发起网络请求的api——wx.request()
,并且提供了各种回调函数。这很容易用着用着就回调地狱了。所以封装大概就有以下三点原因:
- promise化
- 设置统一的请求头
- 获得统一的接口回调处理能力
具体代码如下:
import baseData from './baseData'
// 请求封装
const baseUrl = baseData.apiBaseUrl
const timeout = 20000 ////请求超时时间
const header = {
'content-type': 'application/x-www-form-urlencoded'
}
function fetch(options) {
if (options.loading) {
wx.showLoading({
title: '加载中',
mask: true
})
}
return new Promise(function(resolve, reject) {
wx.request({
url: `${baseUrl}${options.url}`,
method: options.method || 'GET',
data: getParams(options.data),
header: header,
timeout: timeout,
success (res) {
if(res.data.return_code === '2003') { ///token失效
wx.removeStorageSync('accessToken')
}
resolve(res)
},
fail (err) {
reject(err)
},
complete () {
if (options.loading) {
wx.hideLoading()
}
}
})
})
}
export function post(url, params, loading=false) {
let options = {
method: 'POST',
url: url,
data: params,
}
return fetch(options)
}
总结:终于用了两天的碎片时间给胡言乱语完了。再结合开发文档,应该是可以进行流畅的开发了。水分我就不挤了,大哥们自己挑着看吧。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看活动详情
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!