[sweep-it] 分享我學習和使用React的歷程

前言:幾天前我發了兩個沸點,是關於我學習和使用React,並建立的一個minesweeper遊戲。發現你們挺喜歡的,所以,我寫了這一篇文章,以此來記錄本身的歷程,也但願對你們有一點點幫助。html

static image

開始使用React並構建一個小項目

學習一門新的技術,最好的開始就是閱讀官方文檔,而後纔開始本身的實踐。所以,個人學習步驟能夠概括以下:前端

  1. 帶着一些思考去閱讀React官方文檔
  2. 理解React和周圍生態,分析create-react-app工程結構
  3. 開始構思一個小小的項目,可以讓本身在實踐中學習。寫項目過程當中遇到的問題,有幾個解決途徑
    • 社區生態:解決狀態管理、路由等問題,甚至好的插件(在深刻了解以前,建議先用React自己去構建基礎UI)。
    • 官方文檔:基礎概念加深印象。
    • StackOverflow:疑惑解析。
    • google一下(英文),每每有新發現。
  4. 參與社區,瞭解反饋。作遊戲運營或者策劃的同窗應該很清楚,若是作一件事按遊戲的心態去作,成就感會挺高的,而且在這個過程當中不斷獲得反饋,這種反饋又激勵你更大的求勝慾望。所以我在項目作得差很少的時候在掘金上發了一個沸點,發現你們挺喜歡這個項目,這也激勵我繼續寫下去。
  5. 源碼閱讀。這個是終極狀態,像Redux這種,代碼量少,寫得又很棒的庫,讀一讀,收穫挺大。好比有心人就會看到我倉庫裏面有個/test/compose.js,這個文件就是測試一下寫寫compose函數,想法來源也是Redux

首頁開始分析

特色

  • 聲明式:設計好UI,它就會按你設計得方式運行,react幫助您有效更新、正確渲染。
  • 組件化:一個組件封裝好UI和邏輯(基於JavaScript而非模板),能夠輕鬆地將組件進行組合,以構成更加複雜的頁面。
  • 一次學習 隨處編寫React社區活躍,內容豐富,一種技術知足你服務端渲染和Native應用的需求。

從官方特色介紹,至少能夠知道一些要點java

  • JavaScript:以js爲技術基礎來構建UI,若是js基礎比較紮實,應該能夠較快入門。
  • 組件化:組件化是目前前端開發的主流,瀏覽器甚至還在推廣Web Component技術,這就要求咱們思考問題的時候,要常常想想,一個事物是否足夠獨立?是否足夠小?是否可以知足大多數場景的須要?
  • 生態豐富:學習一門技術,能夠快速知足多種應用場景。
  • 狀態與DOM分離:前端界長提MVVM的概念,所謂ModelViewModel-ViewReact作到了數據(狀態)和視圖(DOM)分離。

所以,在學習React以前,我花了一些時間來複習JavaScriptDOM的一些基礎知識,後來的學習中證實這種角度是對的。react

概覽

  • 簡單組件:render函數會在頁面更新時,被React調用,用於生成一幀。是的我把它想象成一幀頁面(以時間長度來看,一次render是頁面生命週期的一幀)。至於爲何是一個render函數,由於咱們的React是一個functionorclass,使用一個函數來更新頁面會很方便區分和保留不一樣的狀態。(Vue裏面data聲明爲一個函數,原理也是同樣的。)
  • 有狀態組件:使用props來獲取從父組件傳遞來的狀態,完成父子組件通訊。須要注意的是,React上的DOM不是原生的DOM,而是由React封裝後的,包括事件(官方文檔有講解)。
  • 應用:在class組件的constructor中聲明this.state,能夠定義當前組件的內部狀態,而且可使用this.setState()方法來更新這個狀態,每次state被更新時,上面提到的render會被調用用於生成一個新的
  • 在組件中使用外部插件:因爲React基於js來構建,那些第三方插件,很容易被引用進來。

技術文檔

因爲技術文檔內容挺多的,我只挑選一些我以爲重要的概念,並加以個人理解進行闡述。webpack

核心概念

  • jsx:組件中的鬆散耦合。在一個文件中採用jsx的語法書寫DOMjs,這裏須要瞭解語法,並在使用的過程當中實踐。
  • props:讓你能夠從父組件傳遞消息到子組件內(包括事件/方法),消息通訊讓狀態傳遞成爲可能,並且使用的語法和寫html屬性差很少,挺友好的。
  • state:組件內部狀態(Model)。經過調用setState來更新state,並觸發render來獲得新的視圖(View)。
  • 事件處理:注意class組件須要bind事件的this。這就是我在本文開始提到的bonus,在js基礎中,搞清楚this的指向挺重要的。另外一個要點就是在React世界中,在DOM中直接觸發的事件每每須要手動調用e.preventDefault()來阻止事件冒泡。
  • key:能夠想象,在一組元素的對比和更新中,帶有key會下降對比的工做量,加快咱們更新的速度。React內部維護了一個Virtual DOM的概念,讓列表更新更快。
  • 狀態提高:在子組件中發送數據到父組件。學到這裏,基本的父子組件通訊就搞完了,原理就是調用props中獲得的事件。
  • 哲學:切割頁面,劃分最小的組件對象,明確數據流向,明確事件分發方式。

高級指引

  • 語義化:這個每每被開發者忽視,實際上,讀這個能瞭解別人解決問題的思考,適合看一看。
  • 代碼分割:這個須要結合ES 6 Modulewebpack來看看,工程化的內容,待深刻。
  • Refs:因爲React是本身包的DOM元素,所以在父類要想拿到子類中的引用(一般這種狀況咱們須要從父類直接去調用子類的方法),就須要一個ref。被forwardRef以後實際是返回了一個高階組件,在這裏你可以拿到ref(被你從React.createRef()中建立的)。
  • 高階組件:由於咱們使用的React全是對象,那麼想提高對象的能力,很容易想到的就是給對象包一層外殼,在java裏面常常要分什麼do\dto\bo\ao\vo等等,在React,利用js的優點(函數乃第一公民),能夠很天然獲得高階組件這種概念。原理就是:一個純函數,處理一個組件,返回另外一個組件。
  • 性能優化:待深刻
  • 其餘:待深刻

高級指引裏面的內容,須要咱們在實踐中反覆地回看,所以,這裏就不贅述,每一個人對這些有本身的理解吧。git

開始一個項目

每一個人都有本身的starter項目,我選擇了minesweeper。這個遊戲出現得挺早,可是我到高中上電腦課才從同窗那知道它的玩兒法。個人想法是:規則挺簡單,不須要我寫不少遊戲邏輯,不須要路由,能夠拆分好幾個組件,須要一點點狀態管理和組件通訊,正符合我這種初學React的人。程序員

前期準備

前期我閱讀了幾篇文章,主要是這一篇,做者用react寫了一個minesweepergithub

react-minesweeper
經過閱讀別人的文章和代碼,基本瞭解了一個 做爲項目而存在的React是什麼個樣子,接下來就只須要去實踐它就好了。

接着我作了一些技術選型:web

  1. React固然是必選了。而且我選擇使用你們都普遍使用的create-react-app做爲cliredux

  2. Redux&React-redux:若是是一個小遊戲,本不須要狀態管理。我認爲項目的統一狀態管理應該出如今狀態多且複雜,並且須要衆多組件同時響應時。可是從小了說,任意組件的狀態可能都是有意義的(受到多個其餘組件引用、可能成爲全局狀態)。所以仍是選擇使用react-redux,這樣在我須要組件間通訊的時候,我能夠少寫不少跳轉,只須要專一於寫一個組件。

    簡單介紹一下,我是如何理解和使用react-redux的。

    1. 理解reducer。這個單詞直譯爲減小,在Array.prototype.reduce中,它減小了空間量,將先後空間量做用於一個reducer函數,使得array(多個數據)變成一個單一的數據。可是在redux概念裏,reducer須要放到生命週期裏來看,一個應用的生命週期中,reducer會被調用無數次,所以我理解爲它是把時間上的多個變量減小爲單一變量,可是由於時間沒有中止(時間中止,則應用也中止了,變量也不存在),所以每次咱們只能拿到最終量的某一個時刻的樣子,這就是reducer的產出被叫作nextState的緣由。
    2. 惟一數據中心store。這個很好理解,一個項目只須要一個大腦就好了,保持數據源一致。
    3. 映射(map)。無論是mapStateToProps仍是mapDispatchToProps,目的都是一個,把數據從store中取出來,掛載到UI組件上,以造成容器組件
    4. 容器(Container)。容器是一個高階組件,它把本身獲取到的StateDispatch轉換爲props掛載到UI組件上。使用時容器組件和被它包裹的UI組件是一個用法,區別是若是使用容器組件,咱們能夠從this.props中獲取到store內的state,也可以分發dispatch
    5. conbineReducer。能夠了解一下compose的概念和使用場景。
  3. rxjs:最開始是想使用rxjs的,可是在寫得過程當中發現不少事件都不必用,簡單地使用事件就能夠解決了,在這個項目中,rxjs帶來的提高並不明顯,所以放棄了。

  4. TypeScript:有網友問我爲何沒有用用TypeScript。由於,這個項目實在過小了,而我又須要快速完成它,若是我已經熟悉的語法和概念可讓我快速開發一個應用,那麼爲了一些ts帶來的小優點而放棄了我另外一個優點,那就得不償失了。所以沒有采用這個。

  5. redux-thunk:當我寫到遊戲狀態更新、動畫這一塊的時候,我確實須要一些異步dispatch的能力了,這時候我選擇引入redux-thunk。固然,知道這個庫,也是google,從社區中瞭解到的。

完成技術選型,剩下的就是寫起來。

寫一個小項目

無論是小項目仍是大項目,寫的初衷有兩個:

  1. 學習基本的React,爲以後的工做作一些準備
  2. 反饋社區。本身從社區學習了不少優秀的思想,所以若是可以寫一點點東西,幫助到和我同樣的初學者,那再好不過了。
工程結構

我喜歡將一個項目各部分的職責劃分得清楚一些

  • test:放置測試代碼。單元測試,測試一些優秀的代碼等等。
  • assets:放置靜態資源。大可能是圖片。
  • components:放置組件。組件須要劃分各自的職責,按模塊/語義化名字來取。
  • constant:放置常量。字符串、數字等等。有點像java裏面的enum
  • utilorhelper:輔助函數。和個人ui無關、state無關的內容,放置到這裏。有些要是和業務強相關的話,可能會增長一個business目錄。
拆分組件

要說minesweeper,首先想到的是一個面板,加一點遊戲輔助信息。所以,我根據一個物件在頁面出現的位置,劃分了各個組件的職責。

  • Board:遊戲面板。用於放置地圖、輔助信息等。
    • 可能設計爲橫向佈局:輔助信息|地圖|描述信息
    • 也可能設計爲縱向佈局
    • 甚至你可讓輔助信息都在另外一個頁面,讓遊戲地圖單獨一個頁面
  • Cell:方塊。一個方塊有多種狀態,所以能夠這麼思考:
    • 翻開
      • 地雷
      • 數字
      • 空白
      • 多重圖案
    • 未翻開
      • 空白
      • 加點色彩
  • Clock:時鐘,這個可能會被全局用到,所以抽象爲一個組件。
    • 表現形式能夠多種多樣
    • 對外提供時間狀態到store
  • Description:用來寫一些遊戲描述信息
    • 遊戲簡介
    • 如何操做
  • Emoji:做爲一個基於程序員和用戶都喜歡的圖標--emoji--來建立的項目,抽象出一個Emoji組件是很天然的事。(一個項目多個部分都會用到)
  • Info:展現遊戲輔助信息,擴展性比較強
    • 能夠設計分數
    • 展現遊戲難度,甚至能夠定製遊戲方塊
    • 遊戲狀態顯示
    • 標記個數
    • 地雷總數
    • 時間顯示
    • 若是加入對戰,能夠顯示別人當前分數
    • 是否能夠加入背景圖像切換(背景不同,難度不同?)
    • 是否能夠加入音樂(音樂緊湊程度能夠反映了遊戲難度)
  • Matrix:方塊地圖,整個遊戲的互動區域
    • 若是是PC 這個Matrix就是遊戲渲染屏幕,遊戲地圖
    • 但我也能夠用來播放一些自定義的動畫
    • 動畫自己就是遊戲的一部分
  • Row:爲了更好地渲染Cell,在MatrixCell之間增長一層Row
重要部分
  1. 使用class語法:任什麼時候候都要明確你的this指向在哪裏。
  2. react-redux的靈活使用:在須要狀態和不須要狀態的情形下要作取捨;純函數更新;異步更新;有什麼好處。
  3. dispatch:分發鼠標事件到全局,用於更新store,並讓各個部分有機刷新。
  4. 生命週期:這個在個人項目中用的少,可是單獨提出來明確一下,你們使用一個技術時,必定要知道它各個部分會作些什麼事。
  5. 拆分和組合:這個你們應該懂,整個程序員生涯都脫離不了這兩個概念。
  6. 良好的分割
  7. 良好的UI

最後這兩點(6/7)爲啥很重要,我是這麼思考的:

  1. 良好的業務和代碼分割可以讓新接手項目的更快上手(若是別人但願基於你的項目作定製,會有一個良好的體驗)
  2. 多花一點時間去設計UI,可讓更多人喜歡上你的產品,由於你們都是從第一印象開始認識你的。

到這裏,基本上我貢獻了從開始閱讀React文檔到輸出一個minesweeper遊戲的全部思考。

  • 但願可以幫助到你們。
  • 但願能獲得更多反饋,可以一塊兒交流。

最後奉上項目地址,謝謝你們。

(以上文章僅來自做者(我)我的觀點)

相關文章
相關標籤/搜索