代码规范
命名
变量
- 数值后缀使用 Value,xxxValue
- 字符后缀使用 Str,xxxStr
- 数组后缀使用 List,xxxList
- 对象后缀使用 Data,xxxData
- 布尔表示开关后缀使用 Switch,xxxSwitch
- 布尔表示有无前缀使用 is,isXxxx
TIP
一些常见的单词已经具有可读性即可不遵循以上命名方式,例如 color、name、title、text、label....
js
let modeValue = 0;
let contentStr = "内容";
let logList = [{ time: 1764124998000, value: 0 }];
let userData = { name: "黎明花", age: 18, hobby: "唱跳rap" };
let powerSwitch = false;
let isFlag = false;let modeValue = 0;
let contentStr = "内容";
let logList = [{ time: 1764124998000, value: 0 }];
let userData = { name: "黎明花", age: 18, hobby: "唱跳rap" };
let powerSwitch = false;
let isFlag = false;常量
- 使用以上变量方式命名,字母全大写下划线分割,XXX_VALUE
- 映射关系使用首字母大写后缀使用 Map,XxxMap
js
const PRIMARY_COLOR = "#FFFFFF";
const ModeTextMap = { 1: "低", 2: "中", 3: "高" };const PRIMARY_COLOR = "#FFFFFF";
const ModeTextMap = { 1: "低", 2: "中", 3: "高" };方法
- 事件处理时前缀使用 handle,handleXxx()
- 渲染 UI 时前缀使用 render,renderXxx()
- 仅内部使用时,前缀使用_,_xxx(),例如工具函数、渲染函数
js
// Event
handlePowerSwitch() {}
// Render
_renderModeCard() {}
// Utils
_formatterLabel() {}// Event
handlePowerSwitch() {}
// Render
_renderModeCard() {}
// Utils
_formatterLabel() {}代码提交
提交规范
- feat:新增功能
- fix:修复 Bug
- docs: 用于修改文档,例如修改 README 文件、API 文档等;
- style: 用于修改代码的样式,例如调整缩进、空格、空行等;
- text: 用于修改文案,例如中英文翻译等;
- refactor: 用于重构代码,例如修改代码结构、变量名、函数名等但不修改功能逻辑;
- perf: 用于优化性能,例如提升代码的性能、减少内存占用等;
- build: 用于修改项目构建系统,例如修改依赖库、外部接口或者升级 Node 版本等;
- chore: 用于对非业务性代码进行修改,例如修改构建流程或者工具配置等;
- ci: 用于修改持续集成流程,例如修改 Travis、Jenkins 等工作流配置;
- test: 用于修改测试用例,例如添加、删除、修改代码的测试用例等。

TIP
除了项目初期开发,之后尽量单个问题单次提交,无论修改范围多小,也不能将两个不同问题的修改一块提交。因为不同问题一块提交,在查看提交记录时,会不清楚哪个问题修改对应哪个文件。
分支
- 新功能 feat/xxx
- 修改 bug fix/xxx
- 修改上线后 bug hotfix/xxx
同品类项目分支
- 主分支 master 管理公版功能
- 其他企业组分支:产品名拼音(首字母大写)/上游分支,例如:Yanmi/master
- 其他企业组分支新功能、修改提交,例如:fix: 炎米-修复 xxxx

TIP
一般有一个稳定版本再开分支,之后来一个开一条分支,不同产品可能会有同页面不同功能 or 同功能但配置不同,假如是不同功能则需要新建文件定义组件引入方式;不同配置就在源文件改,但需要前期将这些"变量"使用常量方式定义好。
拆分组件
根据页面拆分组件,例如: 每个卡片一个组件、每个带操作列表项一个组件
js
import React, { useEffect, useState } from "react";
import propTypes from "prop-types";
import { View, Text, StyleSheet, TouchableOpacity, Image } from "react-native";
import { Device, Service, Package } from "miot";
import { ListItem } from "miot/ui/ListItem";
import StringPicker from "../../../components/common/StringPicker";
import withConfig from "../../../components/common/hoc/withConfig";
/**
* @description: 电机速度档位列表项
*/
function MotorSpeedWithPicker(props) {
const { i18nStrings, isDisabled, defaultValue } = props;
const [dialogVis, setDialogVis] = useState(false);
const [dialogValue, setDialogValue] = useState(defaultValue);
const options = [
{ value: 3, label: i18nStrings["高"] },
{ value: 2, label: i18nStrings["中"] },
{ value: 1, label: i18nStrings["低"] }
];
useEffect(() => {
console.log("MotorSpeedWithPicker useEffect");
const dialogValue = options.find((e) => e.value == props.defaultValue)?.label ?? "";
setDialogValue(dialogValue);
}, [props.defaultValue]);
return (
<>
<ListItem
title={i18nStrings["电机速度"]}
showSeparator={false}
value={dialogValue}
onPress={() => {
setDialogVis(true);
}}
/>
<StringPicker
title={i18nStrings["电机速度"]}
options={options.map((e) => e.label)}
dialogVisible={dialogVis}
defaultValue={dialogValue}
unit={""}
onValueChange={(data) => {
console.log("onValueChange", data);
}}
onCancel={() => {
setDialogVis(false);
}}
onConfirm={(data) => {
const value = options.find((e) => e.label == data)?.value ?? options[0].value; // 找不到就默认第一个
data = options.find((e) => e.value == value)?.label ?? options[0]; // 找不到就默认第一个
// console.log(data);
// console.log(value);
setDialogValue(data);
setDialogVis(false);
props.onValueChange(value);
}}
></StringPicker>
</>
);
}
// 类型校验
MotorSpeedWithPicker.propTypes = {
// options: propTypes.array
};
// 默认值
MotorSpeedWithPicker.defaultProps = {
btConnect: false,
defaultValue: 0
};
export default withConfig(MotorSpeedWithPicker);import React, { useEffect, useState } from "react";
import propTypes from "prop-types";
import { View, Text, StyleSheet, TouchableOpacity, Image } from "react-native";
import { Device, Service, Package } from "miot";
import { ListItem } from "miot/ui/ListItem";
import StringPicker from "../../../components/common/StringPicker";
import withConfig from "../../../components/common/hoc/withConfig";
/**
* @description: 电机速度档位列表项
*/
function MotorSpeedWithPicker(props) {
const { i18nStrings, isDisabled, defaultValue } = props;
const [dialogVis, setDialogVis] = useState(false);
const [dialogValue, setDialogValue] = useState(defaultValue);
const options = [
{ value: 3, label: i18nStrings["高"] },
{ value: 2, label: i18nStrings["中"] },
{ value: 1, label: i18nStrings["低"] }
];
useEffect(() => {
console.log("MotorSpeedWithPicker useEffect");
const dialogValue = options.find((e) => e.value == props.defaultValue)?.label ?? "";
setDialogValue(dialogValue);
}, [props.defaultValue]);
return (
<>
<ListItem
title={i18nStrings["电机速度"]}
showSeparator={false}
value={dialogValue}
onPress={() => {
setDialogVis(true);
}}
/>
<StringPicker
title={i18nStrings["电机速度"]}
options={options.map((e) => e.label)}
dialogVisible={dialogVis}
defaultValue={dialogValue}
unit={""}
onValueChange={(data) => {
console.log("onValueChange", data);
}}
onCancel={() => {
setDialogVis(false);
}}
onConfirm={(data) => {
const value = options.find((e) => e.label == data)?.value ?? options[0].value; // 找不到就默认第一个
data = options.find((e) => e.value == value)?.label ?? options[0]; // 找不到就默认第一个
// console.log(data);
// console.log(value);
setDialogValue(data);
setDialogVis(false);
props.onValueChange(value);
}}
></StringPicker>
</>
);
}
// 类型校验
MotorSpeedWithPicker.propTypes = {
// options: propTypes.array
};
// 默认值
MotorSpeedWithPicker.defaultProps = {
btConnect: false,
defaultValue: 0
};
export default withConfig(MotorSpeedWithPicker);
LinQiang·Shen