第一個(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
- 本質(zhì)是Object類型的對(duì)象(一般對(duì)象)
- 虛擬DOM比較“輕”,真實(shí)DOM比較“重”,因?yàn)樘摂MDOM是React內(nèi)部在用,無需真實(shí)DOM上那么多的屬性。
- 虛擬DOM最終會(huì)被React轉(zhuǎn)化為真實(shí)DOM,呈現(xiàn)在頁(yè)面上。
jsx語(yǔ)法規(guī)則:
- 定義虛擬DOM時(shí),不要寫引號(hào)。
- 標(biāo)簽中混入JS表達(dá)式時(shí)要用{}。(不能寫非表達(dá)式的JS語(yǔ)句,如 for(){ } )
- 樣式的類名指定不要用class,要用className。
- 內(nèi)聯(lián)樣式,要用style={{key:value}}的形式去寫。
- 只有一個(gè)根標(biāo)簽
- 標(biāo)簽必須閉合
- 標(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é)
- 組件中 render 方法中的 this 為組件實(shí)例對(duì)象。
- 組件自定義的方法中 this 為 undefined,如何解決?
a) 強(qiáng)制綁定 this: 通過函數(shù)對(duì)象的 bind()
b) 箭頭函數(shù) - 狀態(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)