前段時間 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
。