react比vue難?vuer10分鐘速覽react

我是死肥宅發表於2018-12-01

@bebal/preset-react

  1. create-react-app腳手架預設配置了@bebal/preset-react依賴
  2. 該babel外掛可以將jsx轉為React.createElement函式(有點像vue中的render函式)
  3. 然後呼叫react-dom庫中的render方法就可以將元素渲染至指定的DOM節點(有點像vue中的$mount方法)
// jsx

<div className={red} style={customStyle}>
  <div>i am a child</div>
</div>
複製程式碼
// @babel/preset-react 轉譯後

"use strict";

React.createElement(
  "div",
  { className: red, style: customStyle },
  React.createElement(
    "div",
    null,
    "i am a child"
  )
);

複製程式碼

元件

特點:方便複用和管理;

  • react中函式可以是元件(元件名大寫),和jsx元素、react元素來進行區分;

元件型別

  1. 函式型元件
  • 函式型元件沒有this指向
  • 函式型元件沒有生命週期
  • 函式型元件沒有狀態
  • 函式型元件有可以接收props物件
import React from 'react';
import reactDOM from 'react-dom';

function CustomElement(props) {
  const data = {
    name: 'function'
  }
  return(
    <>
      <h1>function component</h1>
      <p>I have a somethings: {data.name}</p>
      <span>I get somethings from my parent: {props.data}</span>
    </>
  )
}

reactDOM.render(<CustomElement data='data from parent'></CustomElement>, window.root);
複製程式碼
  1. 型別元件
  • 型別元件必須有render方法,返回一個jsx元素
import React from 'react';
import reactDOM from 'react-dom';

class CustomElement extends React.Component {
  state = {
    name: 'class'
  }
  render() {
    return (
      // 必須有一個根元素對所有元素進行包裹
      <>
        <h1>class component</h1>
        <p>I have a somethings: {this.state.name}</p>
        <span>I get somethings from my parent: {this.props.data}</span>
      </>
    )
  }
}

reactDOM.render(<CustomElement data='data from parent'></CustomElement>, window.root);
複製程式碼

常見繫結樣式方法

  1. class
import './custom.css'
class CustomButton extends Component {
	render() {
		return (
            <button className='custom'>click</button>
		);
	}
}
複製程式碼
  1. style
const customStyle = {
  color: 'red'
}
class CustomButton extends Component {
	render() {
		return (
            <button style={customStyle}>click</button>
		);
	}
}
複製程式碼

常見的繫結事件方法

  1. bind
class CustomButton extends Component {
  say() {
    console.log(this);
  }
	render() {
		return (
            <button onClick={this.say.bind(this)}>click</button>
		);
	}
}
複製程式碼
  1. 箭頭函式
class CustomButton extends Component {
  say() {
    console.log(this);
  }
	render() {
		return (
            <button onClick={() => this.say}>click</button>
		);
	}
}
複製程式碼
  1. es2016繫結方式
class CustomButton extends Component {
  say = () => {
    console.log(this);
  }
	render() {
		return (
            <button onClick={this.say}>click</button>
		);
	}
}
複製程式碼

受控元件

受控元件可以實時校驗

class CustomElement extends React.Component {
  state = {
    username: 'neo',
    password: '123456'
  }
  handle = (e) => {
    this.setState({
      [e.target.name]: e.target.value
    })
  }
  handleSubmit = (e) => {
    e.preventDefault();
    console.log(JSON.stringify(this.state));
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="text" name="username" value={this.state.username} onChange={this.handle} />
        <input type="text" name="password" value={this.state.password} onChange={this.handle} />
        <button>submit</button>
      </form>
    )
  }
}
複製程式碼

非受控元件

  • 如果不需要實時取值,優先使用非受控元件,容易配合第三方庫使用
  • 通過createRef方法或者ref屬性可以拿到元件的值(推薦使用createRef方法)
class CustomElement extends React.Component {
  password = React.createRef();
  handleSubmit = (e) => {
    e.preventDefault();
    console.log(this.username.value);
    console.log(this.password.current.value);
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="text" name="username" ref={(dom) => {this.username = dom}} />
        <input type="text" name="password" ref={this.password} />
        <button>submit</button>
      </form>
    )
  }
}
複製程式碼

元件間資料傳輸共享

我們寫一個小栗子,建立三個元件,在三個元件中傳輸資料。

使用creat-react-app腳手架初始化一個專案,刪掉src資料夾中的所有檔案,建立下面的檔案結構,如圖:

檔案結構

我們要實現的需求:

  • Display元件顯示點贊數
  • Like元件點選增加點贊數

效果如圖(這圖有BUG,大家假裝看到的是每次資料改變按鈕都是有點選的):

效果圖

  1. 通過父元件共享資料

把共享資料放在父元件中,實現了兄弟元件的資料共享;

// index.jsx
import React from 'react';
import reactDOM from 'react-dom';
import Like from './Like';
import Display from './Display';

class CustomElement extends React.Component {
  state = {
    countNum: 0
  }
  increament = () => {
    this.setState({
      countNum: this.state.countNum + 1
    })
  }
  render() {
    return (
      <div>
        <Like increament = {this.increament} />
        <Display countNum = {this.state.countNum} />
      </div>
    )
  }
}

reactDOM.render(<CustomElement/>, window.root);

複製程式碼
// Like.jsx
import React from 'react';

export default class like extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.props.increament}>點贊</button>
      </div>
    )
  }
}

複製程式碼
// Display.jsx

import React from 'react';

export default class Count extends React.Component {
  render() {
    return (
      <div>
        點贊數總數: {this.props.countNum}
      </div>
    )
  }
}

複製程式碼
  1. 通過react中的context API跨元件傳值
// index.jsx
import React from 'react';
import reactDOM from 'react-dom';
import { Provider } from './Context';
import Like from './Like';
import Display from './Display';

class CustomElement extends React.Component {
  state = {
    countNum: 0
  }
  increament = () => {
    this.setState({
      countNum: this.state.countNum + 1
    })
  }
  render() {
    return (
      <Provider value={{ countNum: this.state.countNum, increament: this.increament }}>
        <div>
          <Like />
          <Display />
        </div>
      </Provider>
    )
  }
}

reactDOM.render(<CustomElement/>, window.root);

複製程式碼
// like.jsx
import React from 'react';
import { Consumer } from './Context';

export default class like extends React.Component {
  render() {
    return (
      <Consumer >
        {
          ({increament}) => (
            <div>
              <button onClick={increament}>點贊</button>
              <button>取消</button>
            </div>
          )
        }
      </Consumer>
    )
  }
}
複製程式碼
// Display.jsx
import React from 'react';
import { Consumer } from './Context';

export default class Count extends React.Component {
  render() {
    return (
      <Consumer>
        {
          ({ countNum }) => (
            <div>
              點贊數總數: {countNum}
            </div>
          )
        }
      </Consumer>
    )
  }
}

複製程式碼
// Context.js
import React from 'react';

const { Provider, Consumer } = React.createContext();

export { Provider, Consumer }

複製程式碼

元件傳值tips:

  • 父傳子可以靠props屬性
  • 平級可以靠共同的父元件
  • 跨級可以靠context api
  1. 通過react-redux在元件中傳值

這是個有很長故事的庫,大家可以看一下官方文件,這裡我就不詳述了:

react-redux官網

最後balalala

個人平時使用vue,花了幾天時間學習了一下react。覺得react和vue都是很優秀的框架,我都喜歡。但是為什麼我要取這個標題呢?因為我就是傳說中的標題黨啊:)

相關文章