前段时间 React license 的问题闹的沸沸扬扬,搞得 React 社区人心惶惶,好在最终 React 团队听取了社区意见把 license 换成了 MIT。无论 React license 如何,React 都是一个值得好好学习的优秀视图库。javascript
本项目算不上什么大型项目,但依然按照大型项目的标准采用前端流行的最佳实践来打造一个有良好代码质量,高性能,高可维护性,模块化的应用。本项目是基于 react, redux 构建的 2048,此外也使用了近两年优秀的开源工具来提升代码质量,包括 eslint,stylelint,prettier 等等,以及 travis,codecov 等持续集成,持续部署等服务来保障代码质量和提升开发效率。css
项目地址,喜欢的话 github 点个 star 支持下吧😘html
自适应桌面和移动平台不一样分辨率和尺寸,支持移动平台浏览器触控操做。下面的动图模拟了不一样分辨率下的显示效果。实现方式主要是把 css 单位从 px 换成了 vw 和 rem ,各元素的尺寸是按照分辨率来进行缩放的。css 媒体查询到移动浏览器的话,调整部分组件的位置,隐藏部分不重要的组件,使页面更加紧凑。前端
网页应用最怕断电和离线,第一个问题经过 store.subscribe
订阅 redux 状态更新,把状态序列化到 localStorage
储存,即便刷新,断电,程序奔溃再次打开仍然是最新的状态,第二个问题借助 chrome 的 PWA 技术,即便断开网络仍然能够访问缓存的资源文件。java
redux 是一个可预测的 JS 状态管理容器,结合 Redux DevTools extension 扩展能够很方便的进行应用状态穿梭,对辅助开发和debug大有裨益。不只能够查看 redux 保存的状态,还能够随时回到到过去某个时刻的状态就像时间穿梭机同样,也看获得 redux 每次 action 的触发,以及每次触发形成的状态改动。node
借助 github issue api,使用 github 帐号登陆以后以回复 issue 的方式留言。留言支持 markdown 格式,和 github issue 体验相似。react
在支持 PWA 技术的浏览器上(好比较新的 chrome)打开页面会自动询问你添加到屏幕,添加过程就像原生应用的安装同样。应用添加以后就能够像原生应用同样离线操做,也能够卸载应用。下图演示了 PWA 在 chrome 上面的添加过程,添加完成以后桌面会出现添加的应用,即使关闭全部网络仍然能够像原生应用同样正常操做。webpack
应用支持多语言,且自动适配浏览器语言设置。目前检测到浏览器支持中文优先使用中文,不然默认使用英文显示。须要更多语言支持,编辑 src/utils/i18n.js
的 data
对象,添加对应语言文字便可。git
尽可能使用无状态(Stateless)组件,也就是若是只是写一个单纯展现的组件,不须要组件保存本身的状态,不须要生命周期方法或者 refs 来操做 DOM 的组件则优先使用无状态组件,采用函数的形式。以项目 Tips 组件示例:es6
import React from "react";
import PropTypes from "prop-types";
import styles from "./tips.scss";
export default function Tips({ title, content }) {
return (
<div className={styles.tips}> <p className={styles.title}>{title}</p> <p className={styles.content}>{content}</p> </div>
);
}
Tips.propTypes = {
title: PropTypes.string.isRequired,
content: PropTypes.string.isRequired
};复制代码
和上面相反,若是你须要组件生命周期方法优化组件性能(典型应用,重写 shouldComponentUpdate
方法),须要组件保存本身的状态,或者用 refs 操做 DOM,你就须要一个有状态组件,采用 es6 class 继承 React.Component 的写法。组件示例:
import React from "react";
import PropTypes from "prop-types";
import classnames from "classnames";
import styles from "./cell.scss";
import { isObjEqual } from "../../utils/helpers";
export default class Cell extends React.Component {
static propTypes = {
value: PropTypes.number.isRequired
};
shouldComponentUpdate(nextProps, nextState) {
return (
!isObjEqual(nextProps, this.props) || !isObjEqual(nextState, this.state)
);
}
render() {
const { props: { value } } = this;
const color = `color-${value}`;
return (
<td> <div className={classnames([styles.cell, { [styles[color]]: !!value }])} > <div className={styles.number}>{value || null}</div> </div> </td>
);
}
}复制代码
事件绑定 this 方法。在构造函数里面绑定一次 this 以后后面就能够正常使用。以 ControlPanel 组件部分代码示例:
constructor(...args) {
super(...args);
this.handleMoveUp = this.handleMoveUp.bind(this);
this.handleMoveDown = this.handleMoveDown.bind(this);
this.handleMoveLeft = this.handleMoveLeft.bind(this);
this.handleMoveRight = this.handleMoveRight.bind(this);
this.handleKeyUp = this.handleKeyUp.bind(this);
this.handleSpeakerClick = this.handleSpeakerClick.bind(this);
this.handleUndo = this.handleUndo.bind(this);
}复制代码
使用 propTypes 属性进行传入 prop 的校验。能够校验 prop 的类型和是否必需,非必需的 prop 还必需填写 defaultProps 默认值。以无状态组件 Button 的部分代码示例:
Button.propTypes = {
children: PropTypes.oneOfType([PropTypes.node]),
onClick: PropTypes.func,
size: PropTypes.oneOf(["lg", "md", "sm", "xs"]),
type: PropTypes.oneOf([
"default",
"primary",
"warn",
"danger",
"success",
"royal"
]).isRequired
};
Button.defaultProps = {
children: "",
onClick() {},
size: "md",
};复制代码
shouldComponentUpdate
方法;以组件 Row 示例:// 若是该行没有格子须要刷新也没有组件本身的状态刷新,
// 则该组件不执行 render 方法,
// 避免每次别的行数据刷新也跟着从新渲染。
shouldComponentUpdate(nextProps, nextState) {
return (
!isObjEqual(nextProps, this.props) || !isObjEqual(nextState, this.state)
);
}复制代码
本项目是基于 Facebook 官方出品的 create-react-app 脚手架搭建的,reject 后作了适当修改以适配项目需求。
sass-loader
到 scss 规则下面最下面便可。配置代码import
该包时直接从全局变量获取。剥离后打包的 js 文件大小从 278kb 减少到 164 kb。index.js
里面,同时该目录包含该组件用到样式的 scss 文件,尽可能一个目录包含该组件所需的全部代码避免污染其余代码,提升组件复用性。components
相似,但由于是 smart 组件,因此这里的组件能够操做 redux 的数据,不用太考虑复用性。store.subscribe
订阅应用状态更新,序列化状态存到 localStorage
。由于配置文件用了 es6+ 语法因此要求 node 的版本大于 6.10,同时建议使用 yarn 来管理依赖包。fork 项目以后能够按以下命令操做。
npm i -g yarn # 安装 yarn
git clone git@github.com:<你的名字>/React-2048-game.git
cd React-2048-game
yarn # 安装依赖包
yarn start # 开启调试模式,启动后自动打开浏览器 http://localhost:3000
yarn test # 自动测试
yarn build # 打包代码复制代码
package.json
的 stylelint.rules
。