React 技術分享

1. react 介紹 和 想法

  • A declarative, efficient, and flexible JavaScript library for building user interfaces
  • react是一個專一於UI的庫
  • 狀態機 輸入 => 組件 => 輸出
  • 組件化 react組件映射 爲原生android組件 原生ios 組件 react vr

2. jsx 語法

JSX就是Javascript和XML結合的一種格式,要使用須要在babelrc裏配置, Babel 轉譯器會把 JSX 轉換成一個名爲 React.createElement() 的方法調用react

// 最外層必須有一個元素包裹  
<div>hello world!</div>
  
// 屬性都要駝峯 
<div className="haha" ></div>

// 樣式 
<div style={{ marginTop: '10px'}}></div>

// 變量 
<div> {user.name }</div>

// 事件 
<button onClick={}> click me </button>

// 遍歷 
<ul>
  {
    list.map(
      ({name, value}) => <li key={name} value={value}>{name}</li>
    )
  }
</ul>

// 展開對象 
const props = {name: "tom" }

<div {...props}></div>

3 虛擬DOM 和 diff 算法

a. 虛擬DOM(Virtual DOM)機制:對於每個組件,React會在內存中構建一個相對應的DOM樹,基於React開發時全部的DOM構造都是經過虛擬DOM進行,每當組件的狀態發生變化時,React都會從新構建整個DOM數據,而後將當前的整個DOM樹和上一次的DOM樹進行對比,得出DOM結構變化的部分(Patchs),而後將這些Patchs 再更新到真實DOM中
b. 兩個不一樣類型的元素會產生不一樣的樹(根元素不一樣結構樹必定不一樣)
c. 開發者能夠經過key屬性指定不一樣樹中沒有發生改變的子元素
d. diff算法的核心就是同級比較android

4. state 和 props

  • react 數據是單向流動的 數據自頂向下流動 ,
  • props是傳遞來的參數,從父級組件向子組件傳遞的數據, 是隻讀的
  • state是本身的內部狀態
  • 在react更新生命週期setState會致使死循環
// 默認參數
Main.defaultProps = {
  list: [ ]
}

// setState 是異步的
this.setState( (prevState,props) => ({
  text: prev.text + "-ha"
}))

5. 生命週期

Note: 父子組件的掛載順序,更新順序ios

6 函數式編程

  • 函數式編程,函數做爲一等公民,而不是類和對象
  • 純函數 一個函數的返回結果只依賴於它的參數,而且在執行過程裏面沒有反作用,咱們就把這個函數叫作純函數
  • 高階函數 函數的參數能夠是函數,返回值也能夠是函數 , 如數組的

forEach map filter some reduce ,setTimeout setInterval等算法

  • 柯里化是指這樣一個函數(假設叫作createCurry),他接收函數A做爲參數,運行後可以返回一個新的函數。而且這個新的函數可以處理函數A的剩餘參數

6 無狀態組件

顧名思義,它沒有state,接收props,它是一種只負責展現的純組件 使用函數式的方式聲明,會使得代碼的可讀性更好,並能大大減小代碼量,多寫無狀態組件編程

function HelloComponent(props) {
  return <div>Hello {props.name}</div>
}

ReactDOM.render(<HelloComponent name="marlon" />, mountNode)

7 使用 fragment 碎片
Jsx 要求返回的元素,必須有東西包裹,使用碎片能夠減小一層DOM數組

<React.Fragment>
  <td>Hello</td>
  <td>World</td>
</React.Fragment>
// 能夠簡寫爲 
<>
<td>Hello</td>
<td>World</td>
</>

8 使用context

Context 經過組件樹提供了一個傳遞數據的方法,從而避免了在每個層級手動的傳遞 props 屬性,React.createContext 建立一個context,一個context包含provider(數據提供者), comsumer(數據消費者), Provider 有一個value參數,用來覆蓋建立時的默認值babel

// 建立一個 theme Context,  默認 theme 的值爲 light
const ThemeContext = React.createContext ('light');

function ThemedButton(props) {
  // ThemedButton 組件從 context 接收 theme
  return (
    <ThemeContext.Consumer>
    {theme => <Button {...props} theme={theme} />}
  </ThemeContext.Consumer>
);
}

// 中間組件
function Toolbar(props) {
  return (
    <div>
    <ThemedButton />
    </div>
);
}

class App extends React.Component {
  render() {
    return (
      <ThemeContext.Provider value="dark">
      <Toolbar />
      </ThemeContext.Provider>
  );
  }
}

9. mobx

推薦一個react模塊的目錄結構react-router

/states 狀態
/(widgets|components)各種組件、彈窗等
index.js
index.less
service 建議放在config裏,全局統一 

Computed用於生成計算數據,autorun相似用來監聽某一數據改變而做出反映 
import {action, observable ,autorun} from 'mobx';
import StateAdd from "./add"

class State {
  constructor(){
    this.$add = new StateAdd(this);
  }
  // 顯示
  @observable show = false;

  // query
  @observable query = {
    trade: null,
    type: 1
  }

  /**
   * @name  獲取列表
   */
  @action getList = () => {

  }

}

const instance = new State();

autorun(() => {
  if(instance.show){
    console.log("打開彈窗了")
  }
})


export default instance

10 高階組件

主要有兩種實現方式屬性proxy、繼承實現
一般使用裝飾器模式調用,常見的有mobx的 @observer, react-router的withRouter等less

------      屬性proxy 實現以下 
import React from "react"
export default class extends React.Component {
  render = () =>
    <div>
      <div>
         <Hoc1_text name={'Hoc1_text'}/>
      </div>
      <div>
         <Hoc2_text />
      </div>
    </div>
}




class Text1 extends React.Component {
  render = () =>
    <div>
      this is simple text <br/>
     {this.props.name}
    </div>
}

/**
 * @name 操做props
 */
function Hoc1(Component){
  return class extends React.Component {
    render = () =>
  <div className='hoc1'>
      <Component {...Object.assign({} , this.props, {gen : '111'})}/>
  </div>
}
}

const Hoc1_text = Hoc1(Text1);





class Text2 extends React.Component {
  render = () =>
<div>
<input type="text" value={this.props.value} onChange={this.props.change}/>
</div>
}

/**
 *@name 抽離state
 */
function Hoc2(Component){
  return class extends React.Component {
    state = {
      value: '11'
    }
    change = e => {
      this.setState({
        value: e.target.value
      })
    }
    render = () =>
  <div>
  <Component value={this.state.value} change={this.change}/>
  </div>
}
}

const Hoc2_text = Hoc2(Text2);


function Hoc3(Component){
  return class extends React.Component {
    getRef = _ref => {
      this.refs = _ref;
    }
    render = () =>
  <div>
  <Component ref={this.getRef}/>
  </div>
}
}

------      繼承組件 實現以下 -------
class Text extends React.Component {
  render(){
    return (
      <div>
        this is text
      </div>

    )
  }
}
// 生命週期能夠覆蓋掉 
const hoc2 = Component => {
  return class NewHoc extends Component {
    static displayName = `NewHoc-${Component.displayName || Component.name}`
    render(){
      const element= super.render();
      console.log(element)
      const style = {
        color: element.type === 'div' ? 'red' : 'green'
      }
      const newProps = {...this.props, style}
      return React.cloneElement(element, newProps, element.props.children)
    }
  }
}

const NewCom = hoc2(Text)

11 注意事項

  • React組件名字大寫
  • 不能直接修改state props
  • 更新函數裏不能作狀態操做(死循環)
  • 多用無狀態組件
  • 多用pureComponent React.PureComponent 經過prop和state的淺對比來實現 shouldComponentUpate()。
  • 代碼清晰,一目瞭然,註釋寫好
  • 過分封裝不如不封裝
  • 使用 ImmutableJS 處理數據提高性能
相關文章
相關標籤/搜索