原文连接: https://github.com/ant-move/T...
这是 Antmove 团队推出的小程序风格指南,该指南结合了微信小程序、支付宝小程序、百度小程序三大小程序框架特性沉淀而来的开发实践指南,旨在于创建一份适用于各小程序平台的开发规范,但愿对众多小程序开发者们有所帮助。css
下文中每一条规则的示例代码以支付宝小程序语法为例,其它小程序平台等同。
这些规则会帮你规避错误,因此学习并接受它们带来的所有代价吧。这里面可能存在例外,但应该很是少,且只有你同时精通 JavaScript 和 各小程序平台开发规范才能够这样作。html
这些规则可以在绝大多数工程中改善可读性和开发体验。即便你违反了,代码仍是能照常运行,但例外应该尽量少且有合理的理由。vue
当存在多个一样好的选项,选任意一个均可以确保一致性。在这些规则里,咱们描述了每一个选项并建议一个默认的选择。也就是说只要保持一致且理由充分,你能够随意在你的代码库中作出不一样的选择。请务必给出一个好的理由!经过接受社区的标准,你将会:git
有些小程序的特性的存在是为了照顾极端状况或帮助老代码的平稳迁移。当被过分使用时,这些特性会让你的代码难于维护甚至变成 bug 的来源。这些规则是为了给有潜在风险的特性敲个警钟,并说明它们何时不该该使用以及为何。github
这样能够避免和现有的以及将来的小程序基础组件相冲突,由于基础组件一版都是单个单词的。json
支付宝小程序平台组件命名不支持驼峰形式,横杠形式的命名是都支持的。小程序
"usingComponents": { "Todo": "../../dist/todo/index" }
"usingComponents": { "todo-item": "../../dist/todo/index" }
组件的 props
需定义类型和默认值。微信小程序
在支付宝小程序中,即便没有在 props
中声明的属性,组件也是能够接收到的,可是微信小程序和百度小程序是必须在组件中声明的属性才能接收到。微信
若是传值类型不一样组件也是接收不到的,因此请给一个明确的数据类型。框架
在组件上老是必须用 key 配合 v-for,以便维护内部组件及其子树的状态。
<view> <view a:for="{{ todos }}"> {{ todo.text }} </view> </view>
<view> <view a:for="{{ todos }}" a:key="item.id"> {{ item.text }} </view> </view>
请不要把 a:if 和 a:for 同时用在同一个元素上。
通常咱们在两种常见的状况下会倾向于这样作:
<view> <view a:for="{{ users }}" a:if="{{ item.isActive }}" a:key="{{ item.id }}" > {{ item.name }} </view> </view>
<view> <view a:for="{{ activeUsers }}" a:key="{{ item.id }}" > {{ item.name }} </view> </view>
对于应用来讲,顶级 App 组件和布局组件中的样式能够是全局的,可是其它全部组件都应该是有做用域的。
微信小程序默认是组件样式隔离的,但咱们推荐经过 CSS Modules,那是一个基于 class 的相似 BEM 的策略,固然你也可使用其它的库或约定。
这让覆写内部样式更容易:使用了常人可理解的 class 名称且没有过高的选择器优先级,并且不太会致使冲突。
支付宝小程序目前组件尚未做用域隔离功能,具笔者了解该功能即将发布。
变量的命名在 js 中是不能以关键词及保留字命名的,会直接报错,但在小程序中没有这个严格的限制,但在这里强烈建议不要以小程序的关键字命名。
小程序并无严格的规定不能以上述等关键字命名,但编码时应该避免,提高代码的可读性,当在组件中出现该类型的变量时,咱们能够有一个直观的理解。好比 this.data
就是获取组件内部数据的,gloabel.Data
就是获取应用数据的。
请给每个组件一个单独的目录,而不是将多个组件混杂在一个目录中。
components/ |- Todo.js |- Todo.acss |- Todo.axml |- Todo.json |- TodoItem.js |- TodoItem.acss |- TodoItem.axml |- TodoItem.json
components/ |- Todo |- Todo.js |- Todo.acss |- Todo.axml |- Todo.json |- TodoItem |- TodoItem.js |- TodoItem.acss |- TodoItem.axml |- TodoItem.json
组件文件命名推荐一下两种,请在项目中统一使用。
混用文件命名方式有的时候会致使大小写不敏感的文件系统的问题,因此更为横线链接命名。
components/ |- mycomponent.axml
components/ |- myComponent.axml
components/ |- Mycomponent.axml
components/ |- my-component.axml
应用特定样式和约定的基础组件 (也就是展现类的、无逻辑的或无状态的组件) 应该所有以一个特定的前缀开头,好比 Base。
components/ |- MyButton.axml |- VueTable.axml |- Icon.axml
components/ |- BaseButton.axml |- BaseTable.axml |- BaseIcon.axml
只应该拥有单个活跃实例的组件应该以 The 前缀命名,以示其惟一性。
这不意味着组件只可用于一个单页面,而是每一个页面只使用一次。这些组件永远不接受任何 prop,由于它们是为你的应用定制的,而不是它们在你的应用中的上下文。若是你发现有必要添加 props,那就代表这其实是一个可复用的组件,只是目前在每一个页面里只使用一次。
components/ |- Heading.axml |- MySidebar.axml
components/ |- TheHeading.axml |- TheSidebar.axml
和父组件紧密耦合的子组件应该以父组件名做为前缀命名。
若是一个组件只在某个父组件的场景下有意义,这层关系应该体如今其名字上。由于编辑器一般会按字母顺序组织文件,因此这样作能够把相关联的文件排在一块儿。
components/ |- TodoList |- index.axml |- TodoItem |- index.axml
components/ |- TodoList |- index.axml |- TodoListItem |- index.axml
组件名应该以高级别的 (一般是通常化描述的) 单词开头,以描述性的修饰词结尾。
components/ |- ClearSearchButton.axml |- RunSearchButton.axml
components/ |- SearchButtonClear.axml |- SearchButtonRun.axml
组件名应该倾向于完整单词而不是缩写。
编辑器中的自动补全已经让书写长命名的代价很是之低了,而其带来的明确性倒是很是宝贵的。不经常使用的缩写尤为应该避免。
components/ |- SdSettings.axml |- UProfOpts.axml
components/ |- StudentDashboardSettings.axml |- UserProfileOptions.axml
多个特性的元素应该分多行撰写,每一个属性一行。
在 JavaScript 中,用多行分隔对象的多个属性是很常见的最佳实践,由于这样更易读。
<my-component foo="a" bar="b" baz="c"/>
<my-component foo="a" bar="b" baz="c"/>
复杂表达式会让你的模板变得不那么声明式。咱们应该尽可能描述应该出现的是什么,而非如何计算那个值。并且计算函数和方法使得代码能够重用。
{{ fullName.split(' ').map(function (word) { return word[0].toUpperCase() + word.slice(1) }).join(' ') }}
<!-- 在模板中 --> {{ normalizedFullName }}
methods: { normalizedFullName: function () { let normalizedFullName = this.fullName.split(' ').map(function (word) { return word[0].toUpperCase() + word.slice(1) }).join(' ') this.setData({ normalizedFullName }) } }
小程序提供了组件间代码公用的机制,微信和百度小程序提供 behavior
的功能,支付宝小程序提供 mixin
的功能,这里建议给公用的代码加上做用域区分。
var myGreatMixin = { // ... methods: { update: function () { // ... } } }
var myGreatMixin = { // ... methods: { myGreatMixinUpdate: function () { // ... } } }
组件/实例的选项应该有统一的顺序.
这是咱们推荐的组件选项默认顺序。它们被划分为几大类,因此你也能知道从组件里添加的新属性应该放到哪里。
组合 (向选项里合并属性)
接口 (组件的接口)
本地状态
事件 (经过响应式事件触发的回调)
生命周期钩子
onInit
deriveDataFromProps
didMount
didUpdate
didUnmoun
非响应式的属性 (不依赖响应系统的实例属性)
应该优先经过 prop 和事件进行父子组件之间的通讯,而不是 this.$parent 调用。
一个理想的小程序应用是 prop 向下传递,事件向上传递的。遵循这一约定会让你的组件更易于理解。然而,在一些边界状况下经过获取父子组件的实例来进行变动可以简化两个深度耦合的组件。
问题在于,这种作法在不少简单的场景下可能会更方便。但请小心,不要为了一时方便 (少写代码) 而牺牲数据流向的简洁性 (易于理解)。
注: 微信小程序中可经过relation
功能获取父子组件,支付宝小程序可经过ref
来获取,请谨慎使用。
- version: 1.0.1
- 更新时间:2019-09-09