0%

[小程序] 小程序项目的结构设计

在工作中也做了好几个小程序项目了,正好抽空将小程序开发的一些知识重新整理一下~

结构组成

其中小程序是由.wxml.wxss.js.json四种类型构成(下文将简称为四类文件)。其开发方式跟传统网页开发是十分类似的。

  • .wxml模板文件对应为传统网页开发的.html文件,是一个页面(组件)的骨架。只不过它里面采用的语法跟传统的HTML语法有些差异, 比如标签的名称是微信自己在底层封装的组件。
  • .wxss样式文件则对应CSS样式文件,具有大部分CSS的特性(比如css3的某些伪类特性就没有,但常见的css3属性倒是可以用),除此之外还在此基础上做了新的扩展。
  • js一直都是作为跟页面交互角色,在小程序开发中也不例外。
    js中,可以使用微信提供的API。如常见的Page(构造器)和Component,还有微信给出的一些特定权限的API.
  • json则是配置文件,一般是页面或者组件内那一级的配置文件。

(这里有个小细节可以区分wxmlwxss区别,这两者都是以wx(微信)为开头,后面的小尾巴是区别是样式文件还是模板文件)。

具体的更多细节可以去看官网文档。本文的重心还是在讨论项目结构如何安排会比较整洁合理。

项目结构设计思路

每个小程序项目的根目录会有一个project.config.json的项目配置文件,可以设置miniprogramRoot属性指定小程序源码的目录, 默认为根目录(/)。意思是说把源代码放在/src/下的目录也没有问题,笔者采用的是源码在根目录方式。

首先,小程序规定:一个小程序主体部分由三个文件组成,同时必须放在项目的根目录。

  • app.js 需要在里面调用App()函数,注册一个小程序。
  • app.json 小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。
  • app.wxss 全局样式,作用于每一个页面。但注意的是app.wxss写的全局样式不会影响组件内的样式。
1
2
3
4
├── app.js
├── app.json
├── app.wxss
└── project.config.json

页面

小程序是由许多页面组成的,因此我们需要一个目录来存放页面, 我们通常把这个文件夹命名为/pages/app.jsonpages是一个数组,数组的每一项是用来指定页面的路径,框架会根据路径自动去寻找相对位置的四类文件(小程序的代码构成)。数组第一项为小程序入口页面。

每个页面为单独的一个目录, 页面的四类文件使用统一的名称。这里我们跟官方同步,四类文件跟随目录的名称走:

1
2
3
4
5
6
7
8
9
10
11
├── pages
│ │── home
│ │ ├── home.wxml
│ │ ├── home.js
│ │ ├── home.json
│ │ └── home.wxss
│ └── user
│ ├── user.wxml
│ └── user.js
├── ...
└── project.config.json

除此之外,在开发小程序时,页面是会分主要页面和次要页面(子页),子页通常是一些列表页详情页的东西。理论上只会有一个入口能跳的过去那种二级页面。如果这样的子页一多,然后全都放在了/pages/目录下,就会导致目录列表变得庞大,会比较难找…

这时可以考虑换一种方式储存,在页面文件夹里再加一个文件夹, 名为subpage。把子页放在这个文件夹内,这样层级关系就清晰了,缺点就是不适合套太深。或者说一个产品也不应该把页面藏得太深让用户找不到…

1
2
3
4
5
6
7
8
9
10
├── pages
│ └── home
│ ├── subpage
│ │ └── detail
│ │ ├── index.wxml
│ │ └── ...
│ ├── home.wxml
│ └── ...
├── ...
└── project.config.json

至于项目简单一些的话前者会好一点(子页命名参照master-description的格式),页面太过复杂的话可能会比较推荐使用后者的方式。

图片

既然有了页面,那么页面必不可免会需要引用到图片。图片大致可以分为业务类公共类。一些可以复用的图片我们可以放在同一个地方统一管理。而业务类则放在对应的页面目录下, 命名格式推荐为dir@description:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
├── iamges (公共图片)
│ │── icon
│ │ ├── icon@download.png
│ │ └── icon@cancel.png
| └── ...
├── pages
│ └── index
│ ├── images
│ | └── index@bg.png
│ | └── index@video.png
│ ├── index.wxml
│ ├── index.js
│ ├── index.json
│ └── index.wxss
├── ...
└── project.config.json

但值得注意的是,在js中使用import引入图片时不能通过根目录进行查找,而wxml则没有这种限制。

1
2
3
4
5
<!-- 绝对路径 -->
<images src="/images/icon@download.png" />

<!-- 相对路径 -->
<images src="./images/index@video.png" />
1
2
3
4
// 会报错
import iconDownload from '/images/icon@download.png'
// 只能使用相对路径
import iconDownload from '/../../icon@download.png'

样式

写完页面后自然需要给页面润色, 我们可以通过在页面的.wxss来写局部样式,这没问题。但在我们完成一个又一个页面后,这时你可能会发现有些页面的样式重复性太高了。

因为一个成熟的设计师,在设计每一个产品时,大多会有一套设计风格或者称之为主题的东西。这些元素大量重复在各个页面中,我们重复写这些样式实际上代码是有点冗余的。

这时有经验的开发者很自然就会想到将重复性的代码抽出来,所幸微信提供了@import语句可以导入外联样式表。而这些通用的样式可以放在/style/目录下

1
2
3
4
5
├── style
│ ├── button.wxss
│ └── ...
├── ...
└── project.config.json

直接在.wxss的顶层引入即可复用。

1
2
3
@improt '/style/button.wxss';

/* other code */

至于是为何不在app.json中设定全局样式而单独抽出来的原因也是前文所提及的问题————组件中默认情况下不受全局样式影响的,理论上组件也不该受到外部样式的”无意“的影响。
app.json中的样式只需要加载一次就全局可用,外部样式就不一定了(因为没有实际的调研过),而且还需要额外的去做引入的那一步。具体用哪一种方式还是要看具体情况来自己斟酌啦~

还有一些方法,比如使用scssless之类的预处理之类的方案,也是可以,只不过超出了本文的讨论范围,不展开讲。

组件

组件对于熟悉模块化开发的同学自然不陌生,小程序基础库版本 1.6.3 就开始支持自定义组件了,至今为止也不用担心兼容性的问题了。从笔者角度来看看法,小程序的组件可以分为全局组件和局部组件。

全局性是指那种封装了登录、弹框、动画组件等等之类的组件,局部的大多是减轻一个页面内的复杂度,通过模块”搭积木”的方式来组成一个页面。即使某个功能砍了也能对页面减少牵连。

我们习惯于将全局性的东西放在源码的根目录上,因此会在根目录上创建/components文件夹,里面存放全局性的组件。
其中全局性的组件有不少会有同等类型的组件,因为可以再进一步的分类,如动画类组件存放为一个文件夹内。
再利用编辑器的文件名排序的特性,可以加上@提前组件集合。

组件下的四类文件按照componment/index的方式命名与page区分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
├── componments (公共组件)
│ │── anima
│ │ ├── coin
│ | | ├── index.js
│ | | └── ...
│ │ └── liquid
│ | └── ...
| └── ...
├── pages
│ └── home
│ ├── componments
│ | └── goods
│ | ├── index.wxml
│ | └── ...
│ ├── home.wxml
│ ├── home.js
│ ├── home.json
│ └── home.wxss
├── ...
└── project.config.json

utils

在原生小程序开发中,一般在源码的根目录下,都会有一个utils文件夹,专门来干杂七杂八的脏话累活。其中包含工具类函数、API的管理、配置信息等。

1
2
3
4
5
6
7
8
├── utils (工具集)
│ │── api
│ │ └── ...
| ├── ... (其他工具类)
| ├── config.js
| └── local.config.js (本地配置,git忽略)
├── ...
└── project.config.json

分包

当小程序的资源大小超过了2M时,进行预览调试时就会报文件过大的错误,这时你可能就需要进行分包,将资源分开加载。小程序文档给出的目录结构是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
├── app.js
├── app.json
├── app.wxss
├── packageA
│ └── pages
│ ├── cat
│ └── dog
├── packageB
│ └── pages
│ ├── apple
│ └── banana
├── pages
│ ├── index
│ └── user
└── utils

但经过我们在项目中尝试,我们发现通过编辑器的字符串排序后,会破坏目录结构的清晰度,所以推荐将分包放置到一个文件夹内。

1
2
3
4
5
6
7
├── subpackages (分包)
│ │── news
│ │ └── ...
| └── store
│ └── ...
├── ...
└── project.config.json

结束

最后的一个小程序项目主体结构大致是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
├── components (公共组件目录)
│   ├── @anima (动画组件)
│ └── ...
├── images(公共图片)
│ └── icon
│ ├── icon@download.png
│ └── icon@cancel.png
├── pages(主包目录)
│ └── home (app.json 设置的入口页)
│ ├── home.wxml
│ ├── home.js
│ ├── home.json
│ └── home.wxss
├── style(公用样式目录)
├── subpackages(分包目录)
│ │── news
| └── store
├── utils(公共模块,工具类)
│ ├── config.js(项目配置)
│   └── local.config.js (本地配置,git忽略)
├── .editorconfig
├── .gitignore
├── app.js
├── app.json
├── app.wxss
├── project.config.json
└── README.md

以上是从原生小程序开发的角度来对项目结构的设计进行一个思路总结,没有过多的讲更深入的东西。下一期想整理一下关于API封装和管理,欢迎指导~

「请笔者喝杯奶茶鼓励一下」

欢迎关注我的其它发布渠道