在Taro官方文档的基础上做了一些修改,以下只讲和官方默认配置不同的部分
一 核心库的选择
1.1 官方脚手架@tarojs/cli版本
2.x的RN端不支持样式表达式的语法,导致classnames库不能使用,动态样式的写法会异常繁琐。
2.x的RN端读取无法读取本地图片,因此放弃使用2.x,待上述bug解决后再升级。
目前工程以1.x最后一个版本,1.3.34为基础进行开发,对RN的兼容性最全面
1.2 状态管理框架选型
由于会员中台项目中大量使用了mobx框架,可供参考代码很多,而且mobx书写简约,学习成本低,因此选择mobx作为工程的状态管理框架
工程的所有mobx数据模型放置在src/store目录下
1.3 css预处理器选型
由于scss已在公司多个项目中有成熟的使用,因此继续选择scss作为css预处理器
1.4 图标库
统一使用阿里的iconfont图标库
引入方式:https://github.com/iconfont-cli/taro-iconfont-cli
1.5 网络请求库
尝试过接入taro-axios库,但是RN端在Android上无法加载bundle包,因此放弃,使用官方的request API即可
二 项目组织规范
入口文件 app.js 里面引入的样式就是全局样式,本地样式会覆盖全局样式
三 工程编译配置
3.1 配置SCSS代码编译
为了支持在 scss 中通过别名(@ 或 ~)引用需要指定路径,需要在编译插件中设置
//根据引入scss文件的方式的不同,获取对应文件的绝对地址
const sassImporter = function(url) {
if (url[0] === '~' && url[1] !== '/') {
return {
//引入以~/开头的地址,路径对应 ../node_modules/xxx
file: path.resolve(__dirname, '..', 'node_modules', url.substr(1))
}
}
//如果引入以@styles开头的地址,路径对应 ../styles/xxx,否则照原路径引入
const reg = /^@styles\/(.*)/
return {
file: reg.test(url) ? path.resolve(__dirname, '..', 'src/styles', url.match(reg)[1]) : url
}
}
//编译插件中配置scss文件的导入规则
plugins: {
sass: {
importer: sassImporter
}
}
3.2 关键目录配置别名
alias: {
'@pages': path.resolve(__dirname, '..', 'src/pages'),
'@utils': path.resolve(__dirname, '..', 'src/utils'),
'@store': path.resolve(__dirname, '..', 'src/store'),
'@assets': path.resolve(__dirname, '..', 'src/assets'),
'@styles': path.resolve(__dirname, '..', 'src/styles'),
'@constants': path.resolve(__dirname, '..', 'src/constants'),
'@components': path.resolve(__dirname, '..', 'src/components')
},
3.3 h5端开发时的跨域配置
h5: {
devServer: {
proxy: {
'/api':{
target: 'https://xxx.com',//后台接口地址
changeOrigin: true
}
}
}
}
3.4 自定义RN模块名称
rn: {
appJson: {
// NOTE taro-native-shell 中默认用的是 taroDemo,所以这里必须与之对应
name: 'taroDemo'
}
}
四 环境分离配置
4.1 分离配置文件
脚手架默认提供了两个环境,开发环境和生产环境,对应编译配置在config文件夹下
index为通用配置,其他两个为环境专属配置
4.2 定义全局变量
defineConstants: {
HOST:'"https://api.apiopen.top"' //必须是json字符串,注意写法
}
不同环境配置文件定义相同的全局变量时,系统会自动读取想对应的变量
全局变量在代码中不需要引入,直接使用
options.url = HOST + options.url
五 代码规范
5.1 命名规范
文件夹和文件的命名全部一律小写字母短杆连接 。
组件文件在类中被导入引用时,用Pascal 命名
import Item from '../item'
5.2 JS书写规范
根据官方文档摘录几条重要的必须遵守的规范:
不要在句末使用分号
字符串统一使用单引号
当前作用域不需要改变的变量使用 const,反之则使用 let
每个 const/let 关键字单独声明一个变量
对于变量和函数名统一使用驼峰命名法
检查 NaN 的正确姿势是使用 isNaN()
if (price === NaN) { } // ✗ 错误
if (isNaN(price)) { } // ✓ 正确
使用数组字面量而不是构造器
const nums = new Array(1, 2, 3) // ✗ 错误
const nums = [1, 2, 3] // ✓ 正确
不要扩展原生对象
Object.prototype.age = 21 // ✗ 错误
不要使用 eval()
eval( "var result = user." + propName ) // ✗ 错误
const result = user[propName] // ✓ 正确
嵌套的代码块中禁止再定义函数
if (authenticated) {
function setAuthUser () {} // ✗ 错误
}
禁止使用 Object 构造器
禁止使用 Function 构造器
不使用 Generator 函数语法,使用 Promise 或者 async functions 来实现异步编程
始终使用 === 替代 ==
三元运算符 ? 和 : 与他们所负责的代码处于同一行
5.3 组件及 JSX 书写规范
组件以类的形式进行创建,并且单个文件中只能存在单个组件
JSX 属性均使用单引号:
属性名称始终使用驼峰命名法
用括号包裹多行 JSX 标签
使用对象解构的方式来使用 state、props
const { isEnable } = this.props
const { myTime } = this.state
类成员变量书写顺序:
static 静态方法
constructor
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
点击回调或者事件回调 比如 onClickSubmit() 或者 onChangeDescription()
render
map 循环时请给元素加上 key 属性
不要在 componentDidMount 中调用 this.setState,会导致触发更新
不要在 componentWillUpdate/componentDidUpdate/render 中调用 this.setState,会导致循环更新
由于Taro 编译到小程序端后,每个组件的constructor首先会被调用一次(即使没有实例化),因此自定义组件必须定义 defaultProps,否则页面加载时小程序端会报属性undefined,在微信小程序端的自定义组件中,只有在 properties 中指定的属性,才能从父组件传入并接收
值为 true 的属性可以省略书写值
事件绑定均以 on 开头
子组件传入函数时属性名需要以 on 开头
5.4 Taro 自身限制规范
不能使用 Array#map 之外的方法操作 JSX 数组
解决方案:
for (let index = 0; index < array.length; index++) {
// do you thing with array
}
const element = array.map(item => {
return <View />
})