2017 年 2 月 15 日
如何高效编写微信小程序?
笔者需要经常新建项目,每次都要重复“修改项目结构 -> 从老项目中复制粘贴文件 -> 删除一些老项目中代码”这样的过程,实在是…费心费力。
另一个痛点是:每次新建小程序页面要生成三个文件名相同的文件 ( .wxml、.wxss 和 .js ),命令行太长(据微信同事:也可以在 app.json 的 pages
字段下添加新页面的路径,保存后也会生成对应的文件)。
简易教程指路)。
我们现在有两个目标:
- 根据通用模板新建项目
- 一键新建页面目录以及在目录中的三个文件 :.wxml、 .wxss 和 .js也可以直接在 app.json 的
pages
字段创建页面,保存后生成这三个文件。笔者没有采用这个方法的缘由一个是开始时不知道有此功能,另一个是不合平时的操作习惯,再者想到 js 文件初始化后,需要引入常用库,要插入代码片段,所以保留了这个功能。
这两个需求其实很简单,不需要 GUI,所以我们可以做一个 npm 命令行工具。想象一下这个命令行用起来应该是什么样的呢:
~ npm install wxapp -g
~ wxapp -i myapp && cd myapp
~ wxapp -p list
用流程图示意就是:
正式开始之前,请先确认本地的开发环境,笔者的本地环境是:
~ npm -v
3.10.10
~ node -v
v6.9.4
我们把问题分解为三步:
- 实现命令行工具,可以在任意目录直接运行
- 通过输入不同的命令行参数,以执行不同的功能
- 考虑项目模板的存放位置,是集成到工具中,还是和工具分开呢
不用担心,都很容易解决,我们一个个看。
package.json 中有一个字段是 bin
:
{
...
"bin": {
"mywxapp": "./index.js"
}
}
~ mywxapp
等价于在 terminal 中执行:
~ /path/to/index.js
bin
字段更多信息请参考 npm 文档中 package.json 一节。执行 index.js 时,可以通过 process.argv
获取执行时的参数,但是要从参数数组中拆分出参数无疑很麻烦。不过,npm 发展至今,处理命令行参数的库肯定存在,就是 commander。简单好用易上手,那么第二个问题也解决啦。
项目模板的存放位置
考虑项目模板的存放位置,是集成到工具中,还是和工具分开呢?
笔者选择分开管理。 在一个单独的模板代码仓库中管理模板内容,方便我们维护。目前的模板还比较简单(详见下文“模板详解”),只有标准目录结构,预期后面会加上自动化的部分(比如 less -> wxss),所以未来会改动比较频繁。
download-git-repo 可以把给定地址的仓库内容拷贝到执行目录中。API 简单,所以就是它了。
问题都解决了,现在就让我们看看伪代码(注意:伪码中没有考虑出错情况):
const mkdirp = require(\'mkdirp\');
const download = require(\'download-git-repo\');
// 创建项目
function initProj(projName){
if(currentDir.exsits(projName))
console.warn(projName \'项目已经存在于当前目录中,请使用别的名字\');
else
download(\'path/to/tmpl\', currentDir \'/\' projName);
}
// 注册页面
function registerPage(pagesName) {
// 读配置文件
readFile(configFile, function(data){
// 将新建的所有页面都写入配置文件中
for(name in pagesName){
data.pages.push(\'pages/\' name \'/\' name);
}
writeFile(configFile);
});
}
// 创建页面
function createPage(pages) {
for(var index in pages) {
var page = pages[index];
mkdirp(pagePath, function(){
createFile(page \'.wxml\');
createFile(page \'.wxss\');
createFile(page \'.js\');
})
}
// 将页面注册到 app.json 中
registerPage(pages);
}
使用
在编写好了这个工具之后,只需要在本地全局使用的话:
npm install -g
在本地开发过程中,如果更新了开发版本的代码,需要更新同步到全局,这时候需要执行:
npm link
~/Documents/kmokidd/cli-build$ npm link
/usr/local/bin/wxapp -> /usr/local/lib/node_modules/@kmokidd/wxapp-generator/index.js
/usr/local/bin/node_modules/@kmokidd/wxapp-generator -> /Users/kmokidd/Documents/kmokidd/cli-build/index.js
使用起来是这样的:
模板和插件地址将附在参考资料一节中
如果和笔者一样,希望在多个机器上使用这个工具,可以选择发布到 npm 官网上。发布步骤非常简单,基本上就是:
npm login
npm publish
name
字段使用 @scopeName/wxapp-generator
这样的值。
如果你也有类似的想法,并且也是个 npm 免费用户,那么发布的时候要执行:
npm publish --access public
scope 对使用没有任何影响,但是安装的时候要记得带上 scope name 执行:
npm install @scopeName/wxapp-generator -g
一千个人中有一千种项目模板。根据业务/个人爱好不同,大家的项目模板可能也相去甚远。笔者自觉目前的模板用起来还不错,将在这一节介绍一下。以下是项目的文件结构:
wxapp
├── app.js
├── app.json
├── app.wxss
├── base-styles/
├── images/
├── pages/
│ ├── tmpl/
├── utils /
│ ├── view.js
│ ├── util.js
│ ├── polyfiil.js
└── └── Deferred.js
可能看到这里,读者会有些困惑,那让我们直接以「企鹅听书」为例,具象地看看笔者是怎么做的吧。听书的界面会出现变化的时以下两种场景:
- 一共有两种播放器:minibar 和 全屏的播放器,播放器的播放按钮有“播放”和“暂停”两种状态(图片)切换,这个可以通过
class
来控制。 - 当播放器进入全屏模式后,节目列表将被隐藏;点击箭头以后,节目列表将重新显示出来。
上文的文件结构中的 view.js 就是 UI 逻辑的代码。pages/ 目录中的 js 文件将通过 import
引用 view.js,view.js 中的接口分为“通用”和“页面使用”这两个类型:
module.exports = {
// 通用
general: {
hide: \'hide\', // 变量分离在此
show: \'show\'
},
// 播放器页面
playerView : {
class: {
listItemPlaying: \'playing\'
}
}
// 其他页面如果也有需要,以页面为单位添加...
}
pageView.id
。
举个超级简单的例子(如下),模拟工作流程:
- 在 wxss 中定义好控制不同样式的
class
- 将需要变化的
class
写到 view.js 中,并暴露接口 - 在 wxml 中的对应结构中绑定
event handler
- 在对应的 page.js 里实现
event handler
的具体内容,也就是切换class
的触发条件
老司机一看就知道是 MVVC 模式,这样分离也就是为了 UI 有独立的控制器,不至于和业务逻辑耦合严重,在页面开发的阶段就可以完成 UI 上的变化。从这个角度上看,小程序反而能给 UI 工程师更多控制 UI 逻辑的能力,确定好代码规范和接口。
初始化一个项目是开始编码的第一步,值得多花一些时间找到合适团队合适自己的项目模板。
npm 参考
- 笔者写的小程序项目模板以及小程序生成器
- 其他开发者写的工具:MeCKodo/wxapp-cli
- ES2015 & babel 实战:开发 NPM 模块
- Creating Your First Node.js Command-line Application
- Writing Command-Line Applications in NodeJS
- Building command line tools with Node.js
- npm-developers Developer Guide
- 如何使用NPM来管理你的Node.js依赖
小程序参考