React 筆記

第一個(gè)例子

<!-- 準(zhǔn)備好一個(gè)“容器” -->
<div id="test"></div>

<!-- 引入react核心庫(kù) -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于將jsx轉(zhuǎn)為js -->
<script type="text/javascript" src="../js/babel.min.js"></script>

<script type="text/babel" > /* 此處一定要寫babel */
  //1.創(chuàng)建虛擬DOM
  const VDOM = <h1>Hello,React</h1> /* 此處一定不要寫引號(hào),因?yàn)椴皇亲址?*/
  //2.渲染虛擬DOM到頁(yè)面
  ReactDOM.render(VDOM,document.getElementById('test'))
</script>

虛擬DOM的兩種創(chuàng)建方式

使用jsx創(chuàng)建虛擬DOM

//1.創(chuàng)建虛擬DOM
const VDOM = (    /* 此處一定不要寫引號(hào),因?yàn)椴皇亲址?*/
  <h1 id="title">
    <span>Hello,React</span>
  </h1>
)
//2.渲染虛擬DOM到頁(yè)面
ReactDOM.render(VDOM,document.getElementById('test'))

使用js創(chuàng)建虛擬DOM

//1.創(chuàng)建虛擬DOM
const VDOM = React.createElement('h1',{id:'title'},
  React.createElement('span',{},'Hello,React'))
//2.渲染虛擬DOM到頁(yè)面
ReactDOM.render(VDOM,document.getElementById('test'))

關(guān)于虛擬DOM

  1. 本質(zhì)是Object類型的對(duì)象(一般對(duì)象)
  2. 虛擬DOM比較“輕”,真實(shí)DOM比較“重”,因?yàn)樘摂MDOM是React內(nèi)部在用,無需真實(shí)DOM上那么多的屬性。
  3. 虛擬DOM最終會(huì)被React轉(zhuǎn)化為真實(shí)DOM,呈現(xiàn)在頁(yè)面上。

jsx語(yǔ)法規(guī)則:

  1. 定義虛擬DOM時(shí),不要寫引號(hào)。
  2. 標(biāo)簽中混入JS表達(dá)式時(shí)要用{}。(不能寫非表達(dá)式的JS語(yǔ)句,如 for(){ } )
  3. 樣式的類名指定不要用class,要用className。
  4. 內(nèi)聯(lián)樣式,要用style={{key:value}}的形式去寫。
  5. 只有一個(gè)根標(biāo)簽
  6. 標(biāo)簽必須閉合
  7. 標(biāo)簽首字母
    (1). 若小寫字母開頭,則將該標(biāo)簽轉(zhuǎn)為html中同名元素,若html中無該標(biāo)簽對(duì)應(yīng)的同名元素,則報(bào)錯(cuò)。
    (2). 若大寫字母開頭,react就去渲染對(duì)應(yīng)的組件,若組件沒有定義,則報(bào)錯(cuò)。

react中定義組件

函數(shù)式組件

//1.創(chuàng)建函數(shù)式組件
function MyComponent(){
  console.log(this);   //此處的this是undefined,因?yàn)閎abel編譯后開啟了嚴(yán)格模式
  return <h2>我是用函數(shù)定義的組件(適用于【簡(jiǎn)單組件】的定義)</h2>
}
//2.渲染組件到頁(yè)面
ReactDOM.render(<MyComponent/>,document.getElementById('test'))

MyComponent中的this是undefined,因?yàn)閎abel編譯后開啟了嚴(yán)格模式。
執(zhí)行了ReactDOM.render(<MyComponent/>.......)之后,發(fā)生了什么?
1.React解析組件標(biāo)簽,找到了MyComponent組件。
2.發(fā)現(xiàn)組件是使用函數(shù)定義的,隨后調(diào)用該函數(shù),將返回的虛擬DOM轉(zhuǎn)為真實(shí)DOM,隨后呈現(xiàn)在頁(yè)面中。

類式組件

//1.創(chuàng)建類式組件
class MyComponent extends React.Component {
  render(){
    //render是放在哪里的?—— MyComponent的原型對(duì)象上,供實(shí)例使用。
    //render中的this是誰(shuí)?—— MyComponent的實(shí)例對(duì)象 <=> MyComponent組件實(shí)例對(duì)象。
    console.log('render中的this:',this);
    return <h2>我是用類定義的組件(適用于【復(fù)雜組件】的定義)</h2>
  }
}
//2.渲染組件到頁(yè)面
ReactDOM.render(<MyComponent/>,document.getElementById('test'))

執(zhí)行了ReactDOM.render(<MyComponent/>.......之后,發(fā)生了什么?
1.React解析組件標(biāo)簽,找到了MyComponent組件。
2.發(fā)現(xiàn)組件是使用類定義的,隨后new出來該類的實(shí)例,并通過該實(shí)例調(diào)用到原型上的render方法。
3.將render返回的虛擬DOM轉(zhuǎn)為真實(shí)DOM,隨后呈現(xiàn)在頁(yè)面中。

組件實(shí)例屬性:state

//1.創(chuàng)建組件
class Weather extends React.Component{  
  //構(gòu)造器調(diào)用幾次? ———— 1次
  constructor(props){
    console.log('constructor');
    super(props)
    //初始化狀態(tài)
    this.state = {isHot:false,wind:'微風(fēng)'}
    //解決changeWeather中this指向問題
    this.changeWeather = this.changeWeather.bind(this)
  }

  //render調(diào)用幾次? ———— 1+n次 1是初始化的那次 n是狀態(tài)更新的次數(shù)
  render(){
    console.log('render');
    //讀取狀態(tài)
    const {isHot,wind} = this.state
    return <h1 onClick={this.changeWeather}>今天天氣很{isHot ? '炎熱' : '涼爽'},{wind}</h1>
  }

  //changeWeather調(diào)用幾次? ———— 點(diǎn)幾次調(diào)幾次
  changeWeather(){
    //changeWeather放在哪里? ———— Weather的原型對(duì)象上,供實(shí)例使用
    //由于changeWeather是作為onClick的回調(diào),所以不是通過實(shí)例調(diào)用的,是直接調(diào)用
    //類中的方法默認(rèn)開啟了局部的嚴(yán)格模式,所以changeWeather中的this為undefined
    
    console.log('changeWeather');
    //獲取原來的isHot值
    const isHot = this.state.isHot
    //嚴(yán)重注意:狀態(tài)必須通過setState進(jìn)行更新,且更新是一種合并,不是替換。
    this.setState({isHot:!isHot})
    console.log(this);

    //嚴(yán)重注意:狀態(tài)(state)不可直接更改,下面這行就是直接更改?。?!
    //this.state.isHot = !isHot //這是錯(cuò)誤的寫法
  }
}
//2.渲染組件到頁(yè)面
ReactDOM.render(<Weather/>,document.getElementById('test'))

由于changeWeather是作為onClick的回調(diào),所以不是通過實(shí)例調(diào)用的,是直接調(diào)用。(所以this不是實(shí)例)
類中的方法默認(rèn)開啟了局部的嚴(yán)格模式,所以changeWeather中的this為undefined。(所以this不是window)

state 的簡(jiǎn)寫方式

class Weather extends React.Component{
  //初始化狀態(tài)
  state = {isHot:false,wind:'微風(fēng)'}

  render(){
    const {isHot,wind} = this.state
    return <h1 onClick={this.changeWeather}>今天天氣很{isHot ? '炎熱' : '涼爽'},{wind}</h1>
  }

  //自定義方法————要用賦值語(yǔ)句的形式+箭頭函數(shù)
  changeWeather = () => {
    const isHot = this.state.isHot
    this.setState({isHot:!isHot})
  }
}
//2.渲染組件到頁(yè)面
ReactDOM.render(<Weather/>,document.getElementById('test'))

state總結(jié)

  1. 組件中 render 方法中的 this 為組件實(shí)例對(duì)象。
  2. 組件自定義的方法中 this 為 undefined,如何解決?
    a) 強(qiáng)制綁定 this: 通過函數(shù)對(duì)象的 bind()
    b) 箭頭函數(shù)
  3. 狀態(tài)數(shù)據(jù),不能直接修改或更新,需要使用 setState() 方法。

組件實(shí)例屬性:props

class Person extends React.Component{
  render(){
    // console.log(this);
    const {name,age,sex} = this.props
    return (
      <ul>
        <li>姓名:{name}</li>
        <li>性別:{sex}</li>
        <li>年齡:{age+1}</li>
      </ul>
    )
  }
}
//渲染組件到頁(yè)面
ReactDOM.render(<Person name="jerry" age={19} sex="男"/>,document.getElementById('test1'))
ReactDOM.render(<Person name="tom" age={18} sex="女"/>,document.getElementById('test2'))

const p = {name:'老劉',age:18,sex:'女'}
// console.log('@',...p);
// ReactDOM.render(<Person name={p.name} age={p.age} sex={p.sex}/>,document.getElementById('test3'))
ReactDOM.render(<Person {...p}/>,document.getElementById('test3'))

注意:
<Person {...p}/> 中的{...p}和JS中的...運(yùn)算符無關(guān),不符合JS語(yǔ)法。
展開運(yùn)算符不能展開對(duì)象,但構(gòu)造字面量對(duì)象時(shí)可以使用展開語(yǔ)法。代碼如下:

//構(gòu)造字面量對(duì)象時(shí)使用展開語(yǔ)法
let person = {name:'tom',age:18}
let person2 = {...person}
//console.log(...person); //報(bào)錯(cuò),展開運(yùn)算符不能展開對(duì)象

對(duì)props進(jìn)行限制

<!-- 引入prop-types,用于對(duì)組件標(biāo)簽屬性進(jìn)行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>

// 對(duì)標(biāo)簽屬性進(jìn)行類型、必要性的限制
Person.propTypes = {
  name:PropTypes.string.isRequired, //限制name必傳,且為字符串
  sex:PropTypes.string,//限制sex為字符串
  age:PropTypes.number,//限制age為數(shù)值
  speak:PropTypes.func,//限制speak為函數(shù)
}
//指定默認(rèn)標(biāo)簽屬性值
Person.defaultProps = {
  sex:'男',//sex默認(rèn)值為男
  age:18 //age默認(rèn)值為18
}

props的簡(jiǎn)寫方式

class Person extends React.Component{
  constructor(props){ }

  static propTypes = {
    
  }
  static defaultProps = {
   
  }
  
  render(){ }
}

類式組件中的構(gòu)造器

通常,在 React 中,構(gòu)造函數(shù)僅用于以下兩種情況:

  • 通過給 this.state 賦值對(duì)象來初始化 內(nèi)部 state。
  • 為 事件處理函數(shù) 綁定實(shí)例。

總結(jié):不寫也行,通過其它方式去做。

(視頻至25)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容