React(1)之——React入門

  React 是一個聲明式,高效且靈活的用於構建用戶界面的 JavaScript 庫。使用 React 能夠將一些簡短、獨立的代碼片斷組合成複雜的 UI 界面,這些代碼片斷被稱做「組件」。html

建立react項目

  1. npm install -g create-react-app下載官方的腳手架工具create-react-app。
  2. create-react-app react01建立一個新的名爲react01的項目。
  3. 建立好的react項目目錄結構以下:


  同Vue很類似,項目有一個入口文件,入口文件中的根組件會渲染到DOM樹的根結點root下。

React和ReactDOM

  React和ReactDOM是開發React項目必不可少的兩個包。React負責邏輯控制,它用JSX來描述虛擬DOM以及用它的Component類來建立一個組件;而ReactDOM主要負責渲染,將構建好的虛擬DOM渲染成真實DOM到頁面上。
  來自官方的示例:這裏面還涉及到另外一個問題,JSX是什麼?vue

class HelloMessage extends React.Component {
  render() {
    return React.createElement(
      "div",
      null,
      "Hello ",
      this.props.name
    );
  }
}

ReactDOM.render(React.createElement(HelloMessage, { name: "Taylor" }), document.getElementById('hello-example'));
複製代碼

  至關於react

class HelloMessage extends React.Component {
  render() {
    return (
      <div> Hello {this.props.name} </div>
    )
  }
}

ReactDOM.render(
  <HelloMessage name="Taylor" />, document.getElementById('hello-example') ) 複製代碼

JSX

  JSX形如js和html的混合體,它在react代替常規的js語法。它的優勢:1)執行更快,提升執行效率。2)使用咱們更熟悉的html來描述UI,JSX在react轉換爲js的寫法形如:React.createElement("div",null,"Hello ",this.props.name);,寫起來很繁瑣。3)它是類型安全的,在編譯過程當中就能發現錯誤。
  JSX就是html加上表達式,下面介紹一下一些表達式的寫法:npm

import src from './static/img'
sayHi(){
    return 'hello, react'
}
render(){
    const name = 'zhunny'
    const jsx = '<p>jsx</p>'
    return(
        <div>
        {/*註釋語法*/}
        {/*表達式*/}
        <h1>{name}</h1>
        <h1>{this.seyHi()}</h1>
        {/*屬性的寫法*/}
        <img src={src} style={{width:"200px"}}>
        {/*jsx也能夠直接當成是表達式*/}
        {jsx}
        {/*只要是js表達式均可以放在{}裏面*/}
        <div>
    )
}
複製代碼

建立組件的兩種形式

  一種是函數類型組件,一種是基於類的組件。數組

//rfc 比較簡潔,直接至關於render函數,但hooks的出現使得它們之間沒有太大區別
import React from 'react'

export default function CompType() {
  return (
    <div> </div>
  )
}
//rcc 能夠在類中使用各類生命週期鉤子,在constructor構造函數中初始化state和props
import React, { Component } from 'react'

export default class CompType extends Component {
  render() {
    return (
      <div> </div>
    )
  }
}
複製代碼

state和setState

state

  使用組件時,可能會出現一些特別的狀態,它們可能會改變所以影響視圖的變化,所以咱們須要去維護這些狀態。凡是數據與視圖有交互的時候,就須要將這些數據維護到狀態state中去。state通常在構造函數constructor中初始化。安全

constructor(props) {
    super(props)
    this.state = {
      count:1
    }
 }
複製代碼
setState

  而setState是官方提供給咱們用來修改state值的方法,千萬不能直接修改state,會報錯。使用setState修改state有兩種方法,直接修改state對象setState(obj,cb),或者傳入一個修改函數setState(fn,cb)。由於state和setState是批量執行的,這樣能夠提高更新的性能,可是同時它會認爲連續相同的操做形如setState(obj,cb)是同樣的,只會執行最後一次。這個時候就須要使用第二種修改state的方法。app

componentDidMount () {
  this.setState({
    count: this.state.count + 1
  })
}
複製代碼
componentDidMount () {
  this.setState(preState => ({
    count:preState.count + 1
  }))
  this.setState(preState => ({
    count:preState.count + 1
  }))
}

複製代碼

props屬性傳遞

  這是一種父組件向子組件傳遞屬性的一種方式,父->子通訊的方法。兩種不一樣類型的組件在調用props時有差異。函數

//在父組件中 
import { Welcome1, Welcome2 } from './components/CompType'
export default class App extends Component {
    render () {
        return (
            <Welcome1 name="zhunnyWang" />
            <Welcome2 name="zhunnyWang" />
        )
    }
}
複製代碼
//在子組件中 
//props傳值,兩種方式有區別,props是隻讀的
//單向綁定,嚴格的單向數據流
export function Welcome1 (props) {
  return (
    <div> Welcome1,{props.name} </div>
  )
}

export class Welcome2 extends React.Component {
  constructor(props){
    super(props)
  }
  render () {
    return (
      <div>Welcome2,{this.props.name}</div>
    )
  }
}
複製代碼

條件渲染和列表渲染

  這是在react使用最頻繁的兩種表達式寫法。條件渲染有兩種實現方式,一種是使用三元表達式,一種是使用短路邏輯。父組件向子組件傳遞了一個props爲title='goodlist'。列表渲染就是循環的將一個數組中的元素顯示在視圖上。工具

export class GoodsList extends React.Component {
  constructor(props){
    super(props)
    this.state = {
        goods:[
         {id:1,name:'《你不知道的Javascript》'}
         {id:2,name:'《CSS世界》'}
        ]
    }
  }
  render () {
    const title = this.props.title ? <h1>{this.props.title}</h1> : null
    return (
      <div> {/*條件渲染的第一種方式,三元表達式*/} {title} {/*條件渲染的第二種方式,短路邏輯*/} {this.props.title && <h1>this.props.title</h1>} {/*列表渲染*/} <ul> {this.state.goods.map(good => (<li key={good.id}>{good.name}</li>))} </ul> </div>
    )
  }
}
複製代碼

事件處理

  react的事件處理與原生js形似,形如onClick={this.fn}。事件處理函數的聲明有兩種方式,一種是經過箭頭函數,一種是普通函數可是須要在構造函數中綁定this。性能

export class GoodsList extends React.Component {
  constructor(props){
    super(props)
    this.state = {
        goods:[
         {id:1,name:'《你不知道的Javascript》'}
         {id:2,name:'《CSS世界》'}
        ],
        text: ''
    }
    //不用箭頭函數就得綁定this
    this.addGood = this.addGood.bind(this)
  }
  textChange = (e) => {
    this.setState({
      text: e.target.value
    })
  }
  addGood () {
    /** * react官方但願這是一個純函數 * 更新的數據不是以前的數據,而是一個全新的數據 */
    this.setState(prevState => {
      return {
        goods: [
          ...prevState.goods,
          {
            id: prevState.goods.length + 1,
            name: prevState.text
          }
        ]
      }
    })
  }
  render () {
    return (
      <div> {/*react嚴格遵循單向數據流,沒有數據的雙向綁定,所以須要本身來實現*/} <input type="text" text={this.state.text} onChange={this.textChange} /> <button onClick={this.addGood}>添加商品</button> {/*須要在聲明的事件處理函數中傳入參數時,也須要借用箭頭函數來傳參*/} <button onClick={() => {this.addToCart(good)}}>添加商品</button> </div> ) } } 複製代碼

組件的通訊

  父傳子可使用props來傳遞,上述章節已經給出示例。子傳父也須要藉助props傳遞一個回調函數,經過回調函數來觸發父組件中的方法,用父組件中的函數來修改子組件中的值。這與vue有很大的差別,react但願子組件是一個很是單純的組件,它只有展現功能,全部的操做在父組件中完成。

//父組件 
export class Counter extends React.Component {
  constructor(props){
    super(props)
    this.state = {
        count:1
    }
  }
  add = (value) => {
    this.setState(prevState => {
        count: preState.count + value 
    })
  }
  render () {
    return (
      <div> <Add count={this.state.count} add={this.add}></Add> </div>
    )
  }
}
//子組件
export function Add ({ count, add }) {
    return(
        <div> {count} <button onClick={add(10)}></button> </div>
    )
}
複製代碼
狀態提高

  摘自官方文檔的一段話,當你遇到須要同時獲取多個子組件數據,或者兩個組件之間須要相互通信的狀況時,須要把子組件的 state 數據提高至其共同的父組件當中保存。以後父組件能夠經過 props 將狀態數據傳遞到子組件當中。這樣應用當中全部組件的狀態數據就可以更方便地同步共享了。
  這就是上述所說的子組件是很是單純的,父組件操做,只將結果傳遞給子組件,子組件將結果最終展現到視圖上。

不變性

  通常來講,有兩種修改數據的方式,第一種是直接修改變量的值,第二種是將新的數據直接替換舊的數據。在React中,官方推薦咱們在修改狀態值時使用全新的數據替換舊數據,維持不變性。
第一種:直接修改變量的值:

const name = { firstName:'wang', secondName:'zhunny' }
name.firstName = 'zhou'
複製代碼

第二種:全新的數據替換舊的數據:

const name = { firstName:'wang', secondName:'zhunny' }
const newName = {...name, firstName:'zhou'}  
複製代碼

  在React中維持不變性有如下幾點好處:

  1. 簡化複雜的功能。
  2. 跟蹤數據的改變,跟蹤不可變數據的變化相對來講就容易多了。若是發現對象變成了一個新對象,那麼咱們就能夠說對象發生改變了。
  3. 肯定在 React 中什麼時候從新渲染,不可變性最主要的優點在於它能夠幫助咱們在 React 中建立 pure components。咱們能夠很輕鬆的肯定不可變數據是否發生了改變,從而肯定什麼時候對組件進行從新渲染。在生命週期鉤子函數 shouldComponentUpdate() 中會構建 pure components 的內容。
  4. 對於數組和對象這樣的引用類型,改變它的指向才能觸發render函數,對組件從新渲染。
相關文章
相關標籤/搜索