移动Web端
通用
HTML部分
- style放样式表里, 在头部(head)引入
 - Javascript在尾部(body结束前)引入
 添加必要的mate标签,利于SEO
<meta name="keywords" content=""><meta name="description" content="不超过150个字符">...
尽量减少标签数量,减少不必要的嵌套
- 结构清晰,对于流量型项目要尽量使用语义化标签
<h1>标题</h1><p>段落</p><a>超链接</a><ul><li>1.有序列表</li><li>2.有序列表</li><li>3.有序列表</li></ul>...
 
Javascript部分
变量采用驼峰命名发
let doctorId = null;
私有变量以”_”开头
let _price = 0.00;
常量全部大写
const ADMIN_ROLE = 16;
函数功能保证单一,减少耦合性,同时注释说明 ```javascript 单行注释 // xxxx
多行注释 /**
- xxx
 - xxx */
 
函数注释 /**
- 以星号开头,紧跟一个空格,第一行为函数说明
 - @param {类型} 参数 单独类型的参数
 - @param {[类型|类型|类型]} 参数 多种类型的参数
 - @param {类型} [可选参数] 参数 可选参数用[]包起来
 - @return {类型} 说明
 - @author 作者 创建时间 修改时间(短日期)改别人代码要留名
 - @example 举例(如果需要) */ ```
 
CSS部分
使用css的缩写属性
padding: 20px 30px;✅padding-top: 20px;padding-left: 30px;padding-right: 30px;padding-bottom:20px;❎border: 1px solid #e2e2e2;✅border-width: 1px;border-style: solid;border-color:#e2e2e2;❎...
颜色书写完全
color: #ff99aa;✅color: #f9a;❎
命名规范
容器: container页头:header内容:content/container页面主体:main页尾:footer导航:nav侧栏:sidebar栏目:column页面外围控制整体佈局宽度:wrapper左右中:left right center导航:nav主导航:mainnav子导航:subnav顶导航:topnav边导航:sidebar左导航:leftsidebar右导航:rightsidebar菜单:menu子菜单:submenu标题: title摘要: summary标志:logo广告:banner登陆:login登录条:loginbar注册:register搜索:search功能区:shop标题:title加入:joinus状态:status按钮:btn滚动:scroll标籤页:tab文章列表:list提示信息:msg当前的: current小技巧:tips图标: icon注释:note指南:guild服务:service热点:hot新闻:news下载:download投票:vote合作伙伴:partner友情链接:link版权:copy...
移动端适配方式
常用的适配方式有rem、vw。
vw的特点是矢量不失真,原生支持使用简单,PC端同移动端。
rem的特点是移动PC同时支持,需要针对不同尺寸平台做媒体查询。
如何选择?
当项目仅一套样式且使用在移动端上建议vw,其他情况自行选择
React项目
脚手架的选择
脚手架的选择有umi、create-react-app。
umi的特点是功能齐全,包含了路由、状态管理、现成的构建等。
create-react-app的特点是轻量,可自定义强。
如何选择?
当使用antd(蚂蚁开源)生态技术时推荐使用umi,其他时候自行选择。
umi项目目录结构
├── README.md // 项目说明、注意事项等├── config // 项目配置│ └── config.ts├── dist // build目录├── mock // 模拟数据├── node_modules├── package.json├── public│ └── favicon.png├── src│ ├── app.ts // 入口文件│ ├── assets // 静态资源│ │ ├── fonts // 字体│ │ │ └── DIN-Bold.otf│ │ └── images // 图片│ │ ├── default│ │ ├── i_circle│ │ ├── i_login│ │ └── i_qa│ ├── components // 组件│ │ ├── userModal│ │ │ ├── userModal.less│ │ │ └── userModal.tsx│ │ └── videoItem│ │ ├── videoItem.less│ │ └── videoItem.tsx│ ├── global.less // 全局样式│ ├── locales // 国际化│ ├── models // 状态管理数据集│ │ ├── groupDisease.ts│ │ ├── groupIndexData.ts│ ├── pages // 页面│ │ ├── message│ │ │ ├── message.less│ │ │ └── message.tsx│ │ ├── my│ │ │ ├── my.less│ │ │ └── my.tsx│ └── utils // 工具箱│ ├── isWeichat.ts│ ├── request.ts│ ├── storage.ts│ ├── tools.ts│ └── type.d.ts├── .umirc.ts // 配置文件├── tsconfig.json├── typings.d.ts└── yarn.lock
umi项目配置
import { defineConfig } from 'umi';const { REACT_APP_ENV } = process.env;const proxy: any = {dev: {'/api/': {target: 'http://proxy.pule.com',changeOrigin: true,pathRewrite: { '^': '' },},},test: {'/api/': {target: 'https://yyk.pule.com',changeOrigin: true,pathRewrite: { '^': '' },},},pre: {'/api/': {target: 'your pre url',changeOrigin: true,pathRewrite: { '^': '' },},},};export default defineConfig({nodeModulesTransform: {type: 'none',},proxy: proxy[REACT_APP_ENV || 'dev'], // 依赖库: "cross-env": "^7.0.2"routes: [{ path: '/test', component: '@/pages/test/test' }, // 测试页{ path: '/', component: '@/pages/tabBar/tabBar' }, // tabbar{ path: '/login', component: '@/pages/login/login' }, // 登录页{ path: '/bindPhone', component: './bindPhone/bindPhone' }, // 绑定手机{ path: '/loginCode', component: './loginCode/loginCode' }, // 验证码登录{ component: '@/pages/404' },],dva: {},antd: {},externals: {TCPlayer: 'window.TCPlayer',},locale: {default: 'zh-CN',},metas: [{name: 'apple-mobile-web-app-capable',content: 'yes',},{name: 'fullscreen',content: 'yes',},{name: 'x5-fullscreen',content: 'true',},],styles: ['https://imgcache.qq.com/open/qcloud/video/tcplayer/tcplayer.css'],headScripts: ['https://res.wx.qq.com/open/js/jweixin-1.6.0.js','https://imgcache.qq.com/open/qcloud/video/tcplayer/libs/hls.min.0.13.2m.js','https://imgcache.qq.com/open/qcloud/video/tcplayer/tcplayer.v4.1.min.js',],theme: {'fill-grey': '#F9F9F9','color-text-base': '#4A4A4A', // 基本'color-text-strong': '#404C56', //加重'color-text-bold': '#3C5061', //粗体'color-text-secondary': '#666666', // 辅助色'color-text-caption': '#999999', // 辅助描述},});
其他
- 函数组件与类组件
 
当使用到一些特殊的钩子函数的时候使用函数组件,比方umi的useMode、useSelector, useDispatch等
当运用了异步修改状态推荐使用类组件
this.setState({...}, () => {// 执行异步操作});
- 页面之间传参方式(url传参与state传参)
 
当页面的入口有多个的时候,比如可分享的页面,建议使用url传参,通过从url读取参数,向后端请求数据
当参数较为简单,且入口固定可使用state传参
以umi的history举例
// url 传参history.push(`/askDoctorForm?gid=${props.gid}&did=${doctor.id}`);const params = history.location.query; // 获取参数// state 传参history.push(`/askDoctorForm`, {gid: props.gid,did: doctor.id,});const params = history.location.state; // 获取参数
- 持久状态、全局状态和局部状态的使用场景
 
持久状态:能够持久保存在浏览器中的数据,常用localStorage实现。使用场景:保存用户账户信息,登录态等数
全局状态:全局共享的常量数据,常用来保存一些配置、权限、类型枚举等信息
局部状态:单一组件或者部分组件用到的数据, 单一组件推荐使用react自有的state, 多组件推荐使用状态管理(redux等)
- 依赖的引入顺序
官方库>第三方库>自定义文件>自定义组件>样式
 
// 库import React, { useState, useEffect, useRef } from 'react';import moment from 'moment';import { history, useLocation, useParams } from 'umi';import { Toast } from 'antd-mobile';// 自定义文件import { rightConfig, WECHAT_MP } from '@/utils/configData';import { OrderCreateRespType } from '@/utils/type';import newRequest from '@/utils/request';import isWeichat from '@/utils/isWeichat';import global from '@/utils/global';// 自定义组件import NavBar from '@/components/navbar/navbar';import DoctorConsult from '@/components/doctorConsult/doctorConsult';import VideoItem, { EpisodeProp } from '@/components/videoItem/videoItem';// 样式import styles from './courseDetail.less';
- 类型检测(写接口)的必要性
 
建议使用接口(interface),使用接口有以下几个优点:
- 约束函数或者类的参数输入,提供了类型检测
 - IDE能为编写代码提供警告和快捷输入
 - 能够清晰明了的查到组件所需的数据以及类型
 - 提高代码的严谨性
 
interface UserProp {ownerAvatar?: string;ownerName?: string;ownerRole?: number;ownerIsDoctor?: boolean;createTime?: string;}interface TopicOwnerProp {hasOption?: boolean;hasZan?: boolean;hasAt?: boolean;sizeType?: string;user: UserProp;avatarClick?: () => void;optionClick?: (user: UserProp) => void;}export default (props: TopicOwnerProp) => {return <div>...</div>}
一些常用的文件命名
- 全局变量:global.ts
 - 工具集:utils.ts
 - 配置数据:config.ts
 - 公共请求:commonRequest.ts(图片上传、登录校验等)
 - 类型接口:type.d.ts
 
Vue项目(TODO)
原生项目(TODO)
App(flutter)端(TODO)
代码规范
- 包的导入顺序:dart: > package: > 项目相关
 - export 放在所有导入语句之后
 - 以驼峰命名,类名首字母大写, 私有变量以”_”开头
 - 使用///文档注释成员和类型
 - 避免缩写
 - 不要使用.length来判断集合为空(可以使用isEmpty)
 - 不要显示为参数设置null值
 - 推荐使用final关键字创建只读属性
 - 尽可能在定义变量的时候初始化变量值
 - 构造函数不要使用 new
 - async中需要存在有用效果
 - 使用Future
作为无法回值异步成员的返回类型  - 要注意var 和 const的使用时机
 - 方法名避免以”get”开头
 
切图规范
- 凡是不能确地页面高度的都使用可滑动组件(ListView, SingleChildScroll…)
 - 使用
materail主题都要考虑appbar返回键在Android和Ios的统一, 建议全部使用leading自定义返回图标, 并且注意返回图标与背景色区分开来 - 使用
TextField注意屏幕被撑起问题, 键盘类型, 是否自动更正等 - 明确设计主题色, 并分离出单独的配置文件
 - 图片占位符问题, 确保图片请求时图片区域视觉友好
 - UI块抽离成组件,避免多层嵌套造成阅读障碍
 
