React筆記03:props、組件通信、非受控組件

非受控組件(瞭解)

  • 藉助於 ref 就能夠經過 非受控組件 的方式,來獲取到的表單元素的值。
  • ref 的做用:獲取DOM對象或組件。
import React from 'react';
import ReactDOM from 'react-dom';

class Hello extends React.Component{
  constructor(){
    super();
    //1.建立ref
    this.txtRef = React.createRef();
  }

  handleClick = ()=>{
      //3.經過this.txtRef.current使用
    console.log(this.txtRef.current.value);
  }

  render(){
    return (
      <div>
        {/* 2.綁定ref */}
        <input text="text" ref={this.txtRef}/>
        <button type="button" onClick={this.handleClick}>取值</button>
      </div>
    )
  }
}

ReactDOM.render(<Hello></Hello>,document.getElementById("root"));

props的使用

  • 做用:接收到傳遞給組件中的屬性
  • 在函數組件中如何獲取到 props? 經過函數的參數
  • 在 類組件 中如何獲取到 props? 經過 this.props 來獲取
  • props 是一個對象!!!
  • 特色:只讀!!!( 只能讀取 props 對象中的屬性,而不能修改 props 對象中的屬性 )
  • 能夠給組件傳遞任何類型的數據。
  • 注意:若是在 class 組件中,手動添加了 constructor ,那麼,就應該經過參數獲取到 props, 而後傳遞給 super,這樣,纔可以在 constructor 中,獲取到 props!!!
//函數組件
const Hello = props => {
  // props 就表示傳遞給組件的屬性
  console.log(props);
}

//給組件傳參數
<Hello name="jack" age={19} colors={['red','blue','green']} />


// 類組件:
class Hello extends React.Component {
  constructor(props) {
    super(props)

    // console.log('在構造函數中,獲取到 props ', this.props)
    console.log('在構造函數中,獲取到 props ', props)
  }

  render() {
    console.log('class組件中獲取到props:', this.props)
    return (
      <div>
        <h1>props:{this.props.age}</h1>
        {this.props.colors.map((item, index) => (
          <p key={index}>{item}</p>
        ))}
      </div>
    )
  }
}

組件通信

父到子

  • 1 父組件中提供狀態
  • 2 在子組件標籤上添加屬性,值爲 父組件中的狀態
  • 3 子組件中經過 props 來接收父組件中傳遞過來的數據
// 父組件:
class Parent extends React.Component {
  // 提供數據
  state = {
    lastName: '王'
  }

  render() {
    return (
      <div className="parent">
        <h1>父組件:</h1>
        {/* 1 經過屬性給子組件傳遞數據 */}
        <Child name={this.state.lastName} />
      </div>
    )
  }
}

// 子組件:
// 2 子組件中經過 props 接收數據
const Child = props => {
  return <p className="child">這是子組件:{props.name}</p>
}

子到父

  • 思路:父組件提供一個事件(函數),讓子組件調用;子組件調用的時候,將數據做爲參數的傳遞,父組件中經過事件(函數)的參數,就拿到子組件中的數據了。react

  • 1 父組件提供事件數組

  • 2 將事件經過props傳遞給子組件dom

  • 3 子組件中經過props接收到父組件中傳遞過來的事件ide

  • 4 子組件調用該事件,將數據做爲參數傳遞函數

  • 注意點:父組件提供的方法中 this 執行問題。ui

    • 爲何會有這個問題?由於這個方法不是父組件本身調用的,是由其餘組件調用的,因此,須要處理this指向。
// 1 提供事件(回調函數,)
//  事件是子組件調用的,所以,先要經過 props 傳遞給子組件
// 2 將事件傳遞給子組件
class Parent extends React.Component {
  state = {
    msg: ''
  }

  getChildMsg = data => {
    console.log('父組件中的方法調用了', data)
    this.setState({
      msg: data
    })
  }

  // 注意:this指向問題,由於這個方法是由子組件調用的,因此,應該提早處理好 this 指向!
  /* getChildMsg(data) {
    console.log('父組件中的方法調用了', data, this)
    this.setState({
      msg: data
    })
  } */

  render() {
    return (
      <div className="parent">
        <h1>父組件:{this.state.msg}</h1>
        <Child fn={this.getChildMsg} />
      </div>
    )
  }
}

// 子組件:
// 3 子組件中經過 props 接收到父組件中傳遞過來的事件
// 4 子組件中調用傳遞過來的事件, 將數據做爲事件的參數傳遞
const Child = props => {
  // console.log(props)
  const handleClick = () => {
    // 調用
    props.fn('撩漢子')
  }

  return (
    <p className="child">
      這是子組件:
      <button onClick={handleClick}>發送數據給父組件</button>
    </p>
  )
}

兄弟組件

  • 思路:狀態提高,也就是:將兩個兄弟組件之間的共享數據,放在父組件中。
  • 父組件的職責:1 提供共享數據(state) 2 提供修改狀態的方法
  • 例子:若是 子組件2 要傳遞數據給 子組件1
  • 子組件1:只要經過 props 接收到父組件中傳遞過來的數據(父 -> 子)
  • 子組件2:調用父組件中修改狀態的方法(子 -> 父)
    • 可是,須要先經過 props 獲取到父組件中傳遞過來的方法
// 父組件
// 1 提供狀態
// 2 提供操做狀態的方法
class Parent extends React.Component {
  state = {
    msg: '默認值'
  }

  updateMsg = data => {
    this.setState({
      msg: data
    })
  }

  render() {
    return (
      <div className="parent">
        這是父組件:
        <Child1 msg={this.state.msg} />
        <Child2 updateMsg={this.updateMsg} />
      </div>
    )
  }
}

// 子組件1
// 3 接收數據(數據由父組件提供)
class Child1 extends React.Component {
  render() {
    return <div className="child">這是子組件1:{this.props.msg}</div>
  }
}

// 子組件2:
// 4 在父組件中傳遞事件給子組件
// 5 給按鈕綁定單擊事件
// 6 調用父組件中的事件來更新數據
class Child2 extends React.Component {
  // 單擊事件
  handleClick = () => {
    // 調用父組件的事件
    this.props.updateMsg('子組件2222222222222222222222')
  }

  render() {
    return (
      <div className="child2">
        這是子組件2:
        <button onClick={this.handleClick}>傳遞數據給 Child1</button>
      </div>
    )
  }
}

評論列表案例

  • 分析:由於 CommentList 和 CommentForm 這兩個子組件中,都要用到 評論列表 數據,因此,就利用 狀態提高 的思想,將評論列表數據放在了 父組件Comment 中。this

    • 父組件的兩個職責:1 提供評論列表數據狀態(list) 2 提供修改狀態的方法(updateComment)
  • 功能1:渲染評論列表code

    • 利用 父->子 的通信,將父組件中的 list 傳遞給 子組件;子組件中經過 props 接收
// 父組件中渲染子組件:
<CommentList list={this.state.list} />

// 子組件中:
<ul>
  {props.list.map(item => (
    <li key={item.id}>
      <h3>評論人:{item.name}</h3>
      <p>評論內容:{item.content}</p>
    </li>
  ))}
</ul>
  • 功能2:添加評論
    • a. 經過受控組件的方式,來獲取到評論人和評論內容
    • b. 將用戶輸入的內容,添加到 list 中
      • 由於 list 是由父組件提供的,因此,由父組件提供修改狀態的方法(updateComment);經過 props 傳遞給子組件後,由子組件調用
// 父組件中渲染子組件:
<CommentForm updateComment={this.updateComment} />

// 子組件中:
// 發表評論
addComment = () => {
  const { name, content } = this.state
  // ...

  this.props.updateComment(name, content)

  // ...
}

Context(瞭解)

  • 使用場景:跨組件傳遞數據
  1. 若是兩個組件是遠方親戚(好比,嵌套多層)能夠使用Context實現組件通信
  2. Context提供了兩個組件:Provider 和 Consumer
  3. Provider組件:用來提供數據
  4. Consumer組件:用來消費數據
const { Provider, Consumer } = React.createContext()

<Provider value={this.state.msg}>
  <div className="parent">
    這是父組件:
    <Child1 />
  </div>
</Provider>

// Child1 -> Child2 -> Child3

// Child3
// data 就是 Provider 中提供的 value
<Consumer>{data => <p>接收到的數據爲:{data}</p>}</Consumer>

組件的 children 屬性

  • 做用:獲取組件標籤的子節點
  • 獲取方式: props.children
  • children 與普通的 props 屬性相同,能夠是任意值。
class Parent extends React.Component{
  render(){
    return (
        <div>
        	<Child>哈哈</Child>
         	<Child>{11}</Child>
            <Child>{["red","blue","green"]}</Child>
        </div>
    )
  }
}

class Child extends React.Component{
  render(){
    // 獲取children中的值
    console.log(this.props.children);
    return (
      <div>
        子節點
      </div>
    )
  }
}

props 校驗

  • 場景:給組件添加 props 校驗,來加強組件的健壯性。orm

    • 約定:封裝公共組件的時候,都添加 props 校驗
  • 1 安裝:yarn add prop-types對象

  • 2 導入 import PropTypes from 'prop-types'

  • 3 給組件名稱添加 propTypes 屬性,值是一個對象

  • 4 對象的鍵就是要校驗的 props 名稱,值是 PropTypes.array 等,從PropTypes中獲取到的校驗規則

const Parent = () => { ... }

// 2 給組件添加 props 校驗
Parent.propTypes = {
  // 規定 colors 屬性的類型爲:數組(array),若是未來使用組件的時候,傳入的 colors 屬性類型不是 array ,就會經過警告來告訴使用者。
  colors: PropTypes.array,

  gender: PropTypes.oneOf(['male', 'female']).isRequired
}

props 默認值

  • 能夠經過 組件名.defaultProps = {} 來給組件添加 props 的默認值。
const Parent = () => { ... }

// 添加 props 的默認值:
Parent.defaultProps = {
  gender: 'male'
}
相關文章
相關標籤/搜索