[React-05] 組件的數(shù)據(jù)掛載方式

屬性(props)

props是正常是外部傳入的畜份,組件內部也可以通過一些方式來初始化的設置,屬性不能被組件自己更改拜秧,但是你可以通過父組件主動重新渲染的方式來傳入新的 props

屬性是描述性質少漆、特點的厅须,組件自己不能隨意更改。

之前的組件代碼里面有props的簡單使用危尿,總的來說呐萌,在使用一個組件的時候,可以把參數(shù)放在標簽的屬性當中谊娇,所有的屬性都會作為組件 props 對象的鍵值肺孤。通過箭頭函數(shù)創(chuàng)建的組件,需要通過函數(shù)的參數(shù)來接收props:

import React, { Component, Fragment } from 'react'
import ReactDOM from 'react-dom'

class Title extends Component {
  render () {
    return (
        <h1>歡迎學習{this.props.name}</h1>
    )
  }
}

const Content = (props) => {
  return (
    <p>{props.name}是一個構建UI的庫</p>
  )
}

class App extends Component {
  render () {
    return (
        <Fragment>
        <Title name="React" />
        <Content name="React.js" />
      </Fragment>
    )
  }
}

ReactDOM.render(
    <App/>,
  document.getElementById('root')
)

設置組件的默認props

import React, { Component, Fragment } from 'react'
import ReactDOM from 'react-dom'

class Title extends Component {
  // 使用類創(chuàng)建的組件邮绿,直接在這里寫static方法渠旁,創(chuàng)建defaultProps
  static defaultProps = {
    name: 'React'
  }
  render () {
    return (
        <h1>歡迎學習{this.props.name}</h1>
    )
  }
}

const Content = (props) => {
  return (
    <p>{props.name}是一個構建UI的庫</p>
  )
}

// 使用箭頭函數(shù)創(chuàng)建的組件,需要在這個組件上直接寫defaultProps屬性
Content.defaultProps = {
  name: 'React.js'
}

class App extends Component {
  render () {
    return (
        <Fragment>
        {/* 由于設置了defaultProps船逮, 不傳props也能正常運行顾腊,如果傳遞了就會覆蓋defaultProps的值 */}
        <Title />
        <Content />
      </Fragment>
    )
  }
}

ReactDOM.render(
    <App/>,
  document.getElementById('root')
)

props.children

我們知道使用組件的時候,可以嵌套挖胃。要在自定義組件的使用嵌套結構杂靶,就需要使用 props.children 梆惯。在實際的工作當中,我們幾乎每天都需要用這種方式來編寫組件吗垮。

import React, { Component, Fragment } from 'react'
import ReactDOM from 'react-dom'

class Title extends Component {
  render () {
    return (
        <h1>歡迎學習{this.props.children}</h1>
    )
  }
}

const Content = (props) => {
  return (
    <p>{props.children}</p>
  )
}

class App extends Component {
  render () {
    return (
        <Fragment>
        <Title>React</Title>
        <Content><i>React.js</i>是一個構建UI的庫</Content>
      </Fragment>
    )
  }
}

ReactDOM.render(
    <App/>,
  document.getElementById('root')
)

使用prop-types檢查props

React其實是為了構建大型應用程序而生, 在一個大型應用中垛吗,根本不知道別人使用你寫的組件的時候會傳入什么樣的參數(shù),有可能會造成應用程序運行不了烁登,但是不報錯怯屉。為了解決這個問題,React提供了一種機制饵沧,讓寫組件的人可以給組件的props設定參數(shù)檢查锨络,需要安裝和使用prop-types:

$ npm i prop-types -S

狀態(tài)(state)

狀態(tài)就是組件描述某種顯示情況的數(shù)據(jù),由組件自己設置和更改狼牺,也就是說由組件自己維護羡儿,使用狀態(tài)的目的就是為了在不同的狀態(tài)下使組件的顯示不同(自己管理)

定義state

第一種方式

import React, { Component } from 'react'
import ReactDOM from 'react-dom'

class App extends Component {
  state = {
    name: 'React',
    isLiked: false
  }
  render () {
    return (
      <div>
        <h1>歡迎學習{this.state.name}</h1>
        <button>
          {
            this.state.isLiked ? '??取消' : '??收藏'
          }
        </button>
      </div>
    )
  }
}
ReactDOM.render(
    <App/>,
  document.getElementById('root')
)

另一種方式(推薦)

import React, { Component } from 'react'
import ReactDOM from 'react-dom'

class App extends Component {
  constructor() {
    super()
    this.state = {
      name: 'React',
      isLiked: false
    }
  }
  render () {
    return (
        <div>
        <h1>歡迎學習{this.state.name}</h1>
        <button>
          {
            this.state.isLiked ? '??取消' : '??收藏'
          }
        </button>
      </div>
    )
  }
}
ReactDOM.render(
  <App/>,
  document.getElementById('root')
)

this.propsthis.state是純js對象,在vue中,data屬性是利用Object.defineProperty處理過的是钥,更改?data的數(shù)據(jù)的時候會觸發(fā)數(shù)據(jù)的gettersetter掠归,但是React中沒有做這樣的處理,如果直接更改的話悄泥,react是無法得知的虏冻,所以,需要使用特殊的更改狀態(tài)的方法setState码泞。

setState

isLiked 存放在實例的 state 對象當中兄旬,組件的 render 函數(shù)內,會根據(jù)組件的 state 的中的isLiked不同顯示“取消”或“收藏”內容余寥。下面給 button 加上了點擊的事件監(jiān)聽。

import React, { Component } from 'react'
import ReactDOM from 'react-dom'

class App extends Component {
  constructor() {
    super()
    this.state = {
      name: 'React',
      isLiked: false
    }
  }
  handleBtnClick = () => {
    this.setState({
      isLiked: !this.state.isLiked
    })
  }
  render () {
    return (
      <div>
        <h1>歡迎學習{this.state.name}</h1>
        <button onClick={this.handleBtnClick}>
          {
            this.state.isLiked ? '??取消' : '??收藏'
          }
        </button>
      </div>
    )
  }
}
ReactDOM.render(
    <App/>,
  document.getElementById('root')
)

setState有兩個參數(shù)

第一個參數(shù)可以是對象悯森,也可以是方法return一個對象宋舷,我們把這個參數(shù)叫做updater

  • 參數(shù)是對象

    this.setState({
      isLiked: !this.state.isLiked
    })
    
  • 參數(shù)是方法

    this.setState((prevState, props) => {
      return {
        isLiked: !prevState.isLiked
      }
    })
    

    注意的是這個方法接收兩個參數(shù),第一個是上一次的state, 第二個是props

setState是異步的瓢姻,所以想要獲取到最新的state祝蝠,沒有辦法獲取,就有了第二個參數(shù)幻碱,這是一個可選的回調函數(shù)

this.setState((prevState, props) => {
  return {
    isLiked: !prevState.isLiked
  }
}, () => {
  console.log('回調里的',this.state.isLiked)
})
console.log('setState外部的',this.state.isLiked)

屬性vs狀態(tài)

相似點:都是純js對象绎狭,都會觸發(fā)render更新,都具有確定性(狀態(tài)/屬性相同褥傍,結果相同)

不同點:

  1. 屬性能從父組件獲取儡嘶,狀態(tài)不能
  2. 屬性可以由父組件修改,狀態(tài)不能
  3. 屬性能在內部設置默認值恍风,狀態(tài)也可以
  4. 屬性不在組件內部修改蹦狂,狀態(tài)要改
  5. 屬性能設置子組件初始值誓篱,狀態(tài)不可以
  6. 屬性可以修改子組件的值,狀態(tài)不可以

state 的主要作用是用于組件保存凯楔、控制窜骄、修改自己的可變狀態(tài)。state 在組件內部初始化摆屯,可以被組件自身修改邻遏,而外部不能訪問也不能修改。你可以認為 state 是一個局部的虐骑、只能被組件自身控制的數(shù)據(jù)源党远。state 中狀態(tài)可以通過 this.setState方法進行更新,setState 會導致組件的重新渲染富弦。

props 的主要作用是讓使用該組件的父組件可以傳入?yún)?shù)來配置該組件沟娱。它是外部傳進來的配置參數(shù),組件內部無法控制也無法修改腕柜。除非外部組件主動傳入新的 props济似,否則組件的 props 永遠保持不變。

如果搞不清 stateprops 的使用場景盏缤,記住一個簡單的規(guī)則:盡量少地用 state砰蠢,多用 props

沒有 state 的組件叫無狀態(tài)組件(stateless component)唉铜,設置了 state 的叫做有狀態(tài)組件(stateful component)台舱。因為狀態(tài)會帶來管理的復雜性,我們盡量多地寫無狀態(tài)組件潭流,盡量少地寫有狀態(tài)的組件竞惋。這樣會降低代碼維護的難度,也會在一定程度上增強組件的可復用性灰嫉。

狀態(tài)提升

如果有多個組件共享一個數(shù)據(jù)拆宛,把這個數(shù)據(jù)放到共同的父級組件中來管理

受控組件與非受控組件

React組件的數(shù)據(jù)渲染是否被調用者傳遞的props完全控制,控制則為受控組件讼撒,否則非受控組件浑厚。

渲染數(shù)據(jù)

  • 條件渲染
 {
   condition ? '??取消' : '??收藏'
 }
  • 列表渲染
// 數(shù)據(jù)
const people = [{
  id: 1,
  name: 'Leo',
  age: 35
}, {
  id: 2,
  name: 'XiaoMing',
  age: 16
}]
// 渲染列表
{
  people.map(person => {
    return (
      <dl key={person.id}>
        <dt>{person.name}</dt>
        <dd>age: {person.age}</dd>
      </dl>
    )
  })
}

React的高效依賴于所謂的 Virtual-DOM,盡量不碰 DOM根盒。對于列表元素來說會有一個問題:元素可能會在一個列表中改變位置钳幅。要實現(xiàn)這個操作,只需要交換一下 DOM 位置就行了炎滞,但是React并不知道其實我們只是改變了元素的位置敢艰,所以它會重新渲染后面兩個元素(再執(zhí)行 Virtual-DOM ),這樣會大大增加 DOM 操作厂榛。但如果給每個元素加上唯一的標識盖矫,React 就可以知道這兩個元素只是交換了位置丽惭,這個標識就是key,這個 key 必須是每個元素唯一的標識

  • dangerouslySetHTML

對于富文本創(chuàng)建的內容辈双,后臺拿到的數(shù)據(jù)是這樣的:

content = "<p>React.js是一個構建UI的庫</p>"

處于安全的原因责掏,React當中所有表達式的內容會被轉義,如果直接輸入湃望,標簽會被當成文本换衬。這時候就需要使用dangerouslySetHTML屬性,它允許我們動態(tài)設置innerHTML

import React, { Component } from 'react'
import ReactDOM from 'react-dom'

class App extends Component {
  constructor() {
    super()
    this.state = {
      content : "<p>React.js是一個構建UI的庫</p>"
    }
  }
  render () {
    return (
        <div
        // 注意這里是兩個下劃線 __html
        dangerouslySetInnerHTML={{__html: this.state.content}}
      />
    )
  }
}
ReactDOM.render(
    <App/>,
  document.getElementById('root')
)
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末证芭,一起剝皮案震驚了整個濱河市瞳浦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌废士,老刑警劉巖叫潦,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異官硝,居然都是意外死亡矗蕊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門氢架,熙熙樓的掌柜王于貴愁眉苦臉地迎上來傻咖,“玉大人,你說我怎么就攤上這事岖研∏洳伲” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵孙援,是天一觀的道長害淤。 經常有香客問我,道長赃磨,這世上最難降的妖魔是什么筝家? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮邻辉,結果婚禮上,老公的妹妹穿的比我還像新娘腮鞍。我一直安慰自己值骇,他們只是感情好,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布移国。 她就那樣靜靜地躺著吱瘩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪迹缀。 梳的紋絲不亂的頭發(fā)上使碾,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天蜜徽,我揣著相機與錄音,去河邊找鬼票摇。 笑死拘鞋,一個胖子當著我的面吹牛,可吹牛的內容都是我干的矢门。 我是一名探鬼主播盆色,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼祟剔!你這毒婦竟也來了隔躲?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤物延,失蹤者是張志新(化名)和其女友劉穎宣旱,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叛薯,經...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡浑吟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了案训。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片买置。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖强霎,靈堂內的尸體忽然破棺而出忿项,到底是詐尸還是另有隱情,我是刑警寧澤城舞,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布轩触,位于F島的核電站,受9級特大地震影響家夺,放射性物質發(fā)生泄漏脱柱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一拉馋、第九天 我趴在偏房一處隱蔽的房頂上張望榨为。 院中可真熱鬧,春花似錦煌茴、人聲如沸随闺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽矩乐。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間散罕,已是汗流浹背分歇。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留欧漱,地道東北人职抡。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像硫椰,于是被迫代替她去往敵國和親繁调。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內容

  • 作為一個合格的開發(fā)者靶草,不要只滿足于編寫了可以運行的代碼蹄胰。而要了解代碼背后的工作原理;不要只滿足于自己的程序...
    六個周閱讀 8,448評論 1 33
  • 前言 組件中的state具體是什么?怎么更改state的數(shù)據(jù)? setState函數(shù)分別接收對象以及函數(shù)有什么區(qū)別...
    itclanCoder閱讀 882評論 0 0
  • 40奕翔、React 什么是React裕寨?React 是一個用于構建用戶界面的框架(采用的是MVC模式):集中處理VIE...
    萌妹撒閱讀 1,016評論 0 1
  • 1、什么是react React.js 是一個幫助你構建頁面 UI 的庫派继。React.js 將幫助我們將界面分成了...
    谷子多閱讀 2,557評論 1 13
  • HTML模版 之后出現(xiàn)的React代碼嵌套入模版中宾袜。 1. Hello world 這段代碼將一個一級標題插入到指...
    ryanho84閱讀 6,237評論 0 9