React——第一階段

根據胡子大哈的文章學習,感謝大胡分享
胡子大哈-react.js第一階段

2017.6.19更新完畢
2017.6.18更新至state


正文開始

畢設搞定,工作搞定,終于。。。其實也不是沒有時間,而是心里不靜,不想寫。

公司要用react,所以,先復習下,開始

一、什么是組件化?

總的來說,各種框架只是為了解決一個問題——開發效率。組件化是一種解決方案。
前端說起來也就三部分——結構,樣式,交互。將某一功能的這三部分抽象出來,提升復用性、可維護性、代碼效率。

那么問題的關鍵是——如何抽象

  1. 較廣泛的屬性——>較特殊的屬性
  2. 輸入不同——>輸出不同

直白點就是類、函數。很明顯,對于前端也就是,用js生成想要的結構,并為其添加功能和樣式

具體分析

用js生成頁面,再直白點就是——一個字符串形式的dom結構,用js解析、加入功能,然后插入到頁面。

1.結構
那么首先要有一個render函數,返回這個字符串形式的dom結構。(也就是最開始的輸入)

class oneComponent{
  render() {
    this.el = this.createDOM(`字符串dom結構`);
    return this.el;
  }
  createDOM(str) {
    const div = document.createElement('div');
    div.innerHTML = str;
    return div;
  }
}

結構有了,但顯然不夠,還要有交互

2.交互
一個思想——狀態機。
用一些變量來表示狀態,不同的狀態,對應不同的頁面展示。
首先要有一個狀態池,頁面的展示由多個狀態決定,當狀態改變時候,自動重新渲染所有dom。

上邊的思路明顯有一個問題,自動渲染所有dom開銷太大,雖然避免了手工操作dom的各種弊端。解決方案是虛擬dom,其技術細節還有待研究。

首先是狀態池:

class oneComponent{
  constructor() {
    this.state = {};
  }
  setState (state) {
    this.state = state;
    this.render();
  }
  render () {
    this.el = this.createDOM(str);
    return this.el;
  }
  
  // 功能函數
  createDOM(str) {
    const div = document.createElement('div');
    div.innerHTML = str;
    return div;
  }
}

有了狀態池,功能就很好做了。比如一個點擊切換內容功能(實際情況的肯定比較復雜了)

class oneComponent{
  constructor() {
    this.state = {
      isShowOK: true;
    };
  }
  setState (state) {
    this.state = state;
    this.render();
  }
  render () {
    this.el = this.createDOM(`<span>${this.state.isShowOK ? 'ok' : '不ok'}</span>`);
    this.el.addEventListener('click', this.clickChangeContent.bind(this), false);
    return this.el;
  }

  // 交互功能
  clickChangeContent () {
    this.setState ({
      isShowOK: !this.state.isShowOK
    })
  }
  
  // 功能函數
  createDOM(str) {
    const div = document.createElement('div');
    div.innerHTML = str;
    return div;
  }
}

3.插入頁面
這一部分其實是在使用組件,有兩個階段:

  • 第一次使用
    第一次使用組件顯然不是自己的事情,而是父組件的事情。
  • 狀態改變
    每次狀態改變,組件自身都要做到自我更新。
class oneComponent{
  constructor() {
    this.state = {
      isShowOK: true;
    };
  }
  setState (state) {
    let oldEl = this.el;
    this.state = state;
    this.render();
    if (this.onStateChange) {
      // 留下處理改變的接口
      this.onStateChange(oldEl, this.el);
    }
  }
  render () {
    this.el = this.createDOM(`<span>${this.state.isShowOK ? 'ok' : '不ok'}</span>`);
    this.el.addEventListener('click', this.clickChangeContent.bind(this), false);
    return this.el;
  }

  // 交互功能
  clickChangeContent () {
    this.setState ({
      isShowOK: !this.state.isShowOK
    })
  }
  
  // 以下功能函數

  // 組件初始化
  init() {
    this.render();
  }
  // 生成dom str->dom
  createDOM(str) {
    const div = document.createElement('div');
    div.innerHTML = str;
    return div;
  }
  // 使用子組件 這個過程發生在解析父組件自身dom的過程中。遇到了組件的語法,就調用這個函數,并傳入對應組件的實例。
  useChildComponent(childComponent) {
    let el  = childComponent.init();
    功能:將el插入到對應的位置。
  }

  // 自身更新
  onStateChange (oldEl, newEl) {
    功能:對比前后的dom,哪變化了,就更新哪。
  }
}

稍微抽象下

輸入輸出上抽象,組件大概就是上邊這樣,當然有的功能太復雜,就用文字直接簡要說明了下。
雖然看起來還不錯,但是明顯,組件本身也是可以再抽象一下基類。
為了更靈活,可以對基類子類加入props為組件進行配置。這樣可定制性更高了。

class Component {
  constructor (props = {}) {
    this.props = props;
  }
  setState (state) {
    let oldEl = this.el;
    this.state = state;
    this.renderDOM();
    if (this.onStateChange) {
      // 留下處理改變的接口
      this.onStateChange(oldEl, this.el);
    }
  }

  renderDOM () {
    this.el = this.createDOM(this.render());
    此處在解析dom過程中添加事件。類似下邊注釋里邊的。
    // this.el.addEventListener('click', this.clickChangeContent.bind(this), false);
    return this.el;
  }

  // 組件初始化
  init() {
    this.renderDOM();
  }

  // 生成dom str->dom
  createDOM(str) {
    const div = document.createElement('div');
    div.innerHTML = str;
    return div;
  }

  // 使用子組件 這個過程發生在解析父組件自身dom的過程中。遇到了組件的語法,就調用這個函數,并傳入對應組件的實例。
  useChildComponent(childComponent) {
    let el  = childComponent.init();
    功能:將el插入到對應的位置。
  }

  // 自身更新
  onStateChange (oldEl, newEl) {
    功能:對比前后的dom,哪變化了,就更新哪。
  }
}

class oneComponent extends Component{
  constructor() {
    super(props);
    this.state = {
      isShowOK: true;
    };
  }

  render () {
    return `<span>${this.state.isShowOK ? 'ok' : '不ok'}</span>`;
  }

  // 交互功能
  clickChangeContent () {
    this.setState ({
      isShowOK: !this.state.isShowOK
    })
  }
}

組件化的概念結束,接下來是基礎知識復習

總結一下

組件化設計需要:

  • 像上邊這樣的組件類
  • 特殊的語法分析器
  • 虛擬dom

二、基礎知識

1.雜項

  • 項目生成
    使用create-react-app

  • 組件要引入react、{ Component }react-dom

  • JSX
    將js文件中的類似html的語法結構解析成js對象
    JSX-->(babel+React.js)-->js對象-->(ReactDOM.render)-->DOM-->插入頁面

  • 為什么react和react-dom要分離開

    • 構造出的js對象不一定非要渲染成dom,還有可能渲染到canvas上,或者手機app上。
    • 方便更新組件,使用算法操作這個對象,然后整體更新,減少重排,比較快。

2.組件render方法
寫react就是寫組件,每個組件都必須有一個render方法,返回一個JSX元素
注意

  • 返回中,最外層只要一個元素
  • 在JSX中,class要用className,for要用htmlFor
  • JSX中用{}插入表達式
    • 表達式可以是循環,條件,函數,等等
    • 表達式中的變量來自組件作用域

3.事件監聽
在JSX中的原生HTML標簽(注意:對組件沒用),為對應的事件接口添加回調即可。
比如onClick,onKeyDown
react事件列表

  • event對象

react封裝的對象,屬性與瀏覽器自己的event對象基本一致,保證了瀏覽器兼容性,對外api符合w3c標準。

  • 回調中的this

單純指定回調,不綁定this的話,是無法在回調函數中通過this拿到組件實例的。
為什么?
很簡單,回調函數直接將引用傳遞出去,其真正執行階段的作用域是在全局作用域下,也就是說,這是一個在全局環境執行,但是沒有明確指出是window對象調用的函數。
es5規定,在嚴格模式下,不直接用window對象調用函數,其內部this為undefined。react當然用的嚴格模式。
所以,拿不到組件實例,也拿不到window,最后是一個undined。

解決方法:
method.bind(this, arg1, arg2, ...)

4.state
狀態池,就像上一部分說的。
注意:

  • 在組件的構造器中定義
  • state狀態自動更新要使用setState()方法,以便于自動觸發render
  • setState()參數
  • 對象——表示組件需要更新的狀態。
  • 函數
  • setState()的使用
  1. 更新對象放入更新隊列中,在本趟結束后更新。所以,前后數據改變存在邏輯關系的話,在同一個函數中,不能只傳入對象,解決方法如下。
  2. 使用函數參數解決上邊的問題,參數屬性為上一個setState的結果。這種情況下,react會把setState一趟更新隊列中的狀態合并,并一次渲染。
  3. 傳入第一個對象參數,并傳入第二個當狀態改變后的回調函數,封裝成一個promise,當成異步來處理。這種情況的話,顯然是更新了三次。

5.props
配置組件,組件是比較抽象的,實例化組件就是一個特殊化的過程,通過props來配置。

  • 父組件調用子組件時候,通過標簽特性傳入。所有的標簽特性都會對應到子組件的props字段上。

  • 可以傳遞任何類型的值。比如函數,對象。

  • props一旦傳入進來,就不能被改變。這是為了使得組件的形態/行為可以預測。

  • 只有通過父組件重新渲染,才能改變props。

  • 默認props(defaultProps)

static defaultProps = {
    likedText: '取消',
    unlikedText: '點贊'
  }

6.state與props
總結一下:

  • state組件自己控制自己的狀態池,組件外部不可改變。

  • props父組件對子組件的初始化狀態池,子組件內部不可改變。

  • 沒有state的組件,叫做無狀態組件,更利于組建維護。因為有了內部狀態,就意味著組件很復雜,復用性降低。

  • react.js鼓勵無狀態組件。甚至在后來版本引入了函數式組件——不能用state的組件。

const dog = (props) => {
  const say = (event) => alert('dog')
  return (
    <div onClick={say}>dog</div>
  )
}

7.渲染列表
渲染列表的一般步驟:
拿到數組-->map遍歷-->返回元素-->羅列渲染

  • 注意key值
    key,元素的標識,一般是后臺數據的id。

(完)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,283評論 6 530
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 97,947評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,094評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,485評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,268評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,817評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,906評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,039評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,551評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,502評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,662評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,188評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,907評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,304評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,563評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,255評論 3 389
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,637評論 2 370

推薦閱讀更多精彩內容

  • 原教程內容詳見精益 React 學習指南,這只是我在學習過程中的一些閱讀筆記,個人覺得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,848評論 1 18
  • 本筆記基于React官方文檔,當前React版本號為15.4.0。 1. 安裝 1.1 嘗試 開始之前可以先去co...
    Awey閱讀 7,756評論 14 128
  • 最近看了一本關于學習方法論的書,強調了記筆記和堅持的重要性。這幾天也剛好在學習React,所以我打算每天堅持一篇R...
    gaoer1938閱讀 1,699評論 0 5
  • 1. 永遠不要買一件你很喜歡但沒有你size的大衣 2. 永遠不要買一件只是款式好看但品質沒有達到你要求的大衣 3...
    陳清念閱讀 331評論 0 3
  • 很多人上大學以后發現并不喜歡自己的專業,就產生換專業的念頭,但是很多人在了解換專業的條件以后,很多都放棄了。 因為...
    毛哌專佳閱讀 743評論 0 0