React是Facebook公司研發的一款JS框架(MVC:Model View Controller) 通過資料的改變來影響檢視
1、React
腳手架
React是一款框架:具備自己開發的獨立思想 - 劃分元件開發
前端工程化開發:
- 基於框架的元件/模組化開發
- 基於webpack的自動部署
webpack來完成以上內容(自動化):
- 基於路由的spa單頁面開發
- 區分開發環境和生產環境
- 安裝babel完成ES6編寫程式碼(上線時,ES6編譯成ES5)
- 安裝css、style、file等處理器,處理合並壓縮的
- 編譯less,sass等預編譯語言
- 安裝webpack-dev-server ,可以在開發環境下,編譯後自動建立服務,開啟瀏覽器,當程式碼修改後,自動儲存編譯,頁面自動重新整理
- ....
腳手架 配置webpack相對複雜,我們需要安裝很多的包,還需要寫很多相對複雜的配置,這時候腳手架應運而生,用來提升我們開發的效率
vue:vue-cli react:create-react-app(應用)
二、安裝
1、npm install create-react-app -g
// 安裝到全域性能用命令
(npm root -g
檢視全域性npm安裝目錄)
2、create-react-app demo1
// 專案名稱demo1,名稱只能(/^[a-z0-9_-]$/)
腳手架生成目錄中的一些內容:
1、node_module 當前專案中依賴的包 .bin 本地專案中可執行的命令,在package.json的scripts中配置的對應的指令碼即可(還有一個是react-scripts命令) 2、public 存放當前專案的頁面(單頁面應用放index.html即可,多頁面根據自己需求放置需要的頁面)
在react中,所有的邏輯都是在JS中完成的(包括頁面機構的建立),如果想給當前的頁面匯入一些css樣式後者img圖片等內容,我們有兩種方式:
(1)、在JS中基於ES6 Module模組規範,使用import引入,這樣webpack在編譯合併JS的時候,會把匯入的資原始檔等插入到頁面的機構中(絕對不能在js管控的結構中通過相對目錄./ 或者../ 匯入資源,因為在webpack編譯的時候,地址就不在是之前的相對地址要用絕對地址)
(2)、如果不想在js中匯入(JS中匯入的資源最後都是基於webpack編譯),我們也可以把資源手動的在html中代入,但是html最後也要基於webpack編譯,匯入的地址也不建議寫相對地址,而是使用%PUBLIC_URL%
寫成絕對地址
<link rel="manifest" href="%PUBLIC_URL%/reset.min.css">
複製程式碼
3、src 專案結構中最主要的目錄,因為後期所有的JS、路由、元件等都是放到這裡面(包括需要編寫的css或者圖片等) index.js 是入口檔案 4、.gitignore git的忽略檔案 5、package.json 當前專案的配置清單
"dependencies": {
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-scripts": "1.1.4"
},
複製程式碼
基於腳手架生成工程目錄,自動幫我們安裝了三個模組:
- react 、
- react-dom、
- react-scripts(整合了webpack需要的內容babel,css處理,eslint, webpack....,注意:沒有less、sass)
package.json:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
複製程式碼
可執行的指令碼
npm run start
或者 yarn start
yarn start
:
- 建立一個預設埠號為3000 ,協議為http的web服務
- 按照webpack.config.dev.js把專案編譯
- 開啟瀏覽器預覽我們的專案
- 專案修改時候,自動重新編譯,瀏覽器頁面自動重新整理,展示最新的效果
yarn build:
- 基於webpack.config.prod.js 把專案進行編譯打包
- 生成一個build資料夾,存放最後打包的檔案>- 生成一個build資料夾,存放最後打包的檔案
- 部署上線的時候,只需要把build的內容釋出即可
三、React腳手架的深入剖析
create-react-app 腳手架為了讓結構目錄清晰,把安裝的webpack及配置檔案都整合在了react-scripts模組中,放到了node_modules中
但是真實專案中,我們需要在腳手架預設安裝的基礎上,額外安裝一些我們需要的模組,例如react-router-dom
、axios
、還有less
、less-loader
情況一:如果我們安裝其他的元件,但是安裝成功後不需要修改webpack的配置項,此時我們直接安裝,調取使用就行,比如react-router-dom 、axios等
情況二:我們安裝的外掛是基於webpack處理的,也就是需要把安裝的模組配置到webpack中(重新修改webpack配置項了) 1、首先需要把隱藏到node_module中的配置項暴露到專案中
yarn eject
首先會確定是否確認執行eject,這個操作不可逆轉,一旦暴露出來配置項,就無法再隱藏了 如果還有未提交到歷史區的內容,需要先提交,然後才能eject 2、再去修改對應的配置項 暴露後,專案目錄中多了兩個資料夾: config:存放的是webpack的配置檔案 (1)webpack.config.dev.js
開發環境下的配置項(yarn start) (2)webpack.config.prod.js
生產環境下的配置項(yarn build) scripts:存放的是可執行指令碼的JS檔案 (1)start.js:yarn start
執行的就是這個JS (2)build.js:yarn build
執行的就是這.個JS
我們預覽專案的時候,也是基於webpack編譯,把編譯後的內容放到瀏覽器中執行,所以如果專案中使用了less,我們需要修改webpack配置項,在配置項中加入less的編譯工作,這樣後期預覽專案,首先基於webpack把less編譯為css
set HTTPS=true && npm start
開啟HTTPS協議模式
set PORT=1111 && npm start
修改預設埠號
四、漸進式框架
一種漸進式框架設計思想,一般框架中都包含了很多內容,這樣導致框架的體積過於臃腫 拖慢載入的速度, 真實專案中,我們使用一個框架,不一定用到所有的功能,此時我們應該把框架的功能進行拆分,使用者想用什麼,讓其自己自由組合即可--"漸進式框架"
全家桶:漸進式框架N多部分的組合 vue全家桶:vue、vue-cli、vue-router、vuex、axios、vue-element 、vant、 react全家桶:react、react-react-app、react-dom、react-router、redux、react-redux、axios、ant、dva、saga、mobx
1、React
react的核心部分,提供了Component類可以進行元件開發,提供了鉤子函式(生命週期),所有的生命週期函式都是基於回撥函式完成的
2、React-dom:
raect獨有的,把JSX語法,渲染為真實DOM(能夠放到頁面中展示的機構都叫做真實的DOM)的元件
react框架都是在JS中進行的,然後通過webpack編譯,再放到瀏覽器中編譯
在index.js這個入口檔案:
import React from 'react';
import ReactDOM from 'react-dom';
// import ReactDOM,{render} from 'react-dom';
// 從react-dom中匯入一個reactDOM,逗號後面的內容是把ReactDOM這個物件進行結構
let data ='zufeng',
root = document.querySelector("#root");
ReactDOM.render(<div id="box">hello world!{data}</div>,root,()=>{
// 回撥,一般不用
let oBox = document.querySelector("#box");
console.log(oBox.innerHTML);
});
複製程式碼
2.1、JSX(也叫react元素):
JSX語法的渲染使用的是ReactDOM.render:
ReactDOM.render([jsx],[container],[callback]);
jsx:react獨有的語法, JavaScript+xml(HTML),和我們之前拼接的字串類似,都是把html結構程式碼和js程式碼或者資料混合在一起了,但是他不是字串 container:容器,我們想把元素放到頁面中的哪個容器中 callback:當把容器放到頁面中呈現觸發的回撥函式
jsx語法特點:
1、不建議我們 直接把jsx直接放到body中,而是放在自己建立一個容器中,一般我們都放在一個id為root的div中
ReactDOM.render(<section><h2>內容</h2></section>,root)
複製程式碼
2、把資料嵌入到jsx中
在JSX中出現的{}
是存放JS的,要求JS程式碼執行完成需要有返回結果(JS表示式),不能直接放一個物件資料型別的
let name = 'zhufeng' // 基本資料型別的值
ReactDOM.render(<section><h2{name}</h2></section>,root)
let xx = {name:'xxxx'}
ReactDOM.render(<section><h2{xx}</h2></section>,root) // 報錯
複製程式碼
- 不能直接放一個物件資料型別的值(物件((除了給style賦值)),陣列(如果只有基本值或者jsx除外),函式都不行)
ReactDOM.render(<ul>
{
data.map((item,index)=>{
return <li key={index}>{item.title}</li>
})
}
</ul>,root)
複製程式碼
- 可以是基本型別的值(布林型別什麼都不顯示,null,undefined也是jsx元素,代表的是空)
- 迴圈判斷語句都不行,但是支援三元運算子
3、迴圈陣列穿件jsx元素,需要給建立的元素設定唯一的key值(當前本次唯一即可) 4、只能出現一個根元素 5、給元素設定樣式類用的是className而不是class 6、style中不能直接寫樣式字串,需要基於一個樣式物件來遍歷賦值 7、可以給JSX元素設定屬性: => 屬性值對應大括號中,物件、函式都可以放(也可以放JS表示式) =>style屬性值必須是物件(不能是字串)
<li style={{color:'#fff'}}></li>
=>class 用className代替
ReactDOM.render(<h1 id={'box'} className="box" style={{color:'red'}}>我是標題</h1>);
複製程式碼
3、渲染原理(react的核心原理之一)
JSX虛擬DOM變為真實的DOM(react的核心原理之一)
let styleObj = {color:'red'};
ReactDOM.render(<h1 id="titleBox" className='title' style={styleObj.color}></h1>)
複製程式碼
JSX渲染機制:JSX->真實DOM
1、基於babel babel-loader babel-present-react-app把JSX語法編譯為
React.createElement([type],[props],[children])
結構 =>React.createElement中至少有兩引數, type:第一引數的標籤(字串) props:屬性物件(沒有就是null) 其他的:都是子元素內容(只要子元素是html,就會變成新的createElement)
var styleObj = { color: 'red' };
ReactDOM.render(React.createElement('h1', { id: 'titleBox', className: 'title', style: styleObj.color }));
複製程式碼
2、執行
React.createElement(....)
,建立一個物件(虛擬DOM)
=>key 和ref 都是createElement中的Prop提取出來的 =>props:{ chiledren:存放自己子元素的(沒有子元素就沒有這個屬性),如果有多個子元素,就以陣列的形式儲存資訊 } 3、
ReactDOM.render(JSX語法最後生成的物件,container,callback)
,基於render方法把生成的物件動態建立為DOM元素,插入到指定的容器中
4、元件
不管vue還是react框架,設計之初都是期望我們按照“元件 / 模組管理” 的方式來構建程式的,也就是一個程式劃分一個個的元件來單獨管理
src -> component
:這個資料夾下存放的就是開發用的元件 【優勢】 1、有助於多人協助開發 2、元件可以複用 ....
react 中建立元件有兩種方式:
1、函式式宣告元件
(1)函式返回結果是一個新的JSX(也就是當前元件的JSX結構) (2)props變數儲存的值是一個物件,包含了調取元件時候傳遞的屬性值,不傳遞的話是個空物件
知識點:
createElement遇到一個元件,返回的物件中:type就不是字串標籤名了,而是一個函式(類),但是屬性還是存在props中
render渲染的時候,我們需要做處理:
首先判斷type的型別, 如果是字串,就建立一個元素標籤, 如果函式或者類,就把函式執行,把props中的每一項(包含children)傳遞給函式 在執行的時候,把函式中return的JSX轉換為新的物件(通過createElement),把這個物件返回:緊接著
render
按照以往的渲染方式,建立DOM元素,插入到指定的容器中即可
單閉合和雙閉合元件的區別,雙閉合元件中可以放子孫元素
函式式宣告特點:
1、會把基於createElement解析出來的物件中的props作為引數傳遞給元件(可以完成多次調取元件傳遞不同的資訊) 2、一旦元件調取成功,返回的
jsx
就會渲染到頁面中,但是後期不通過重新調取元件或者獲取DOM元素操作的方式,很難再把渲染好元件中的內容更改 -->"靜態元件"
//Dialog.js
import React from 'react'; // 每個元件必須引入,因為需要基於它的create-element把JSX進行解析渲染
export default function Dialog(props) {
//props:調取元件的時候傳遞進來的屬性資訊(可能包含className、style、id、可能有children)
let {con, lx = 0, children,style={}} = props,
title = lx === 0 ? '系統提示' : '系統警告';
//children 可能有,可能沒有,可能是個值,也可能是個陣列,每一項可能是字串也可能是個物件等,都代表雙閉合元件的子孫元素
return <section style={style}>
<h2>{title}</h2>
<div>{con}</div>
{/*1、把屬性中的子元素,放到元件中的指定位置*/}
{/*{children}*/}
{/*2、也可以使用react中專門遍歷children的方法*/}
{children.map(item => item)}
{/*// {React.Children.map(children,item=>item)}*/}
</section>
}
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
// 公共css放index.js中,這樣在其他元件中也可以使用(webpack會把所有的元件最後都編譯到一起,index是主入口)
// import 'static/css/reset.min.css'
import 'bootstrap/dist/css/bootstrap.css' // 需要匯入未經過壓縮的檔案,否則報錯(真實專案中bootstrap已經是過去式了,後期用ant)
import Dialog from "./component/Dialog-bootstrap";
ReactDOM.render(<main>
<Dialog content ='馬少帥很帥'/>
<Dialog type ={2} content='系統錯誤了'/>
<Dialog type = '請登入' content={
'新的JSX語法'
}>
<div>
<input type="text" className='form-control' placeholder='請輸入使用者名稱'/><br/>
<input type="password" placeholder='請輸入密碼'/>
</div>
<br/>
<button className='btn btn-success'>登入</button>
<button className='btn btn-danger'>取消</button>
</Dialog>
</main>,root);
複製程式碼
2、繼承component類來建立元件
基於component把JSX轉換為一個物件,當render渲染這個物件的時候,遇到type是一個函式或者類,不是直接建立元素,而是把方法執行,
- 如果就是函式宣告的元件,就把它當做普通函式執行(方法中的this是undefined),把函式返回的JSX元素(也是解析後的物件)進行渲染
- 如果是類宣告式的元件,會把當前類new執行,建立類的一個例項(當前本次呼叫的元件就是它的例項)執行constuctor之後,會執行this.render(),把rende返回的JSX拿過來渲染,所以“類宣告式的元件,必須有一個render的方法,方法中需要返回一個JSX元素” 但是不管哪一種方式,最後都會把解析出來的props屬性物件作為實參傳遞給對應的函式或者類
特點: 1、調取元件相當於建立類的例項(this),把一些私有的屬性掛載到例項上了,這樣元件內容所有的方法中都可以基於例項獲取這些值(包括:傳遞的屬性和自己管理的狀態) 2、有自己的狀態管理,當狀態改變的時候,react會重新渲染檢視(差異更新:基於DOM-DIFF只把有差異的部分渲染)
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types' // facebook是公司開發的一個外掛,基於這個外掛我們可以給元件傳的屬性設定規則,設定的規則不會影響頁面的渲染,可以不加
// 但是會在控制檯丟擲警告錯誤
class Dialog extends React.Component{
// this.props只讀的,我們無法在方法中修改它的值,但是可以給其設定預設值或者設定一些規則(例如:設定是否是必須傳遞的以及傳遞的值的型別等)
static defaultProps ={
lx:"系統提示"
};
static propTypes = {
// 設定屬性規則,如果傳的不是這個規則的,不影響頁面的渲染,只是會在控制檯丟擲警告錯誤
// con: PropTypes.string 傳遞的內容必須是字串
con:PropTypes.string.isRequired // 傳遞的內容是字串,而且還必須是傳遞
};
constructor(props){ // props context updater
// props:當render渲染並且把當前類執行建立例項的時候,會把之前JSX解析出來的props物件中的資訊(可能有children)傳遞給引數props => "調取元件傳遞的屬性"
// props如果不傳,super也不傳,除了constructor中不能直接使用this.props,其他宣告周期函式中都可以使用(也就是執行完成constructor,
// react已經幫我們把傳遞的屬性接收,並且掛載到例項上了)
super(props); // extends繼承,一旦使用了constructor,第一行位置必須設定super執行,相當於React.Component.call(this),也就是call繼承,把父類私有的屬性繼承過來
// this.props:屬性集合
// this.refs:ref集合(非受控元件中用到)
// this.context:上下文
// - 如果super(props); 在繼承父類私有的時候,就把props掛載到this例項上了,這個this只是constructor中的this,不影響原型上的this,寫不寫都行
// - 如果只寫super() 雖然建立例項的時候把屬性傳遞過來了,但是並沒有傳遞父元件,也就是沒有把屬性掛載到例項上,使用this.props獲取的結果是undefined
// -
console.log(props);
// AA = 12; 設定私有屬性,但是不符合ES6語法,需要babel-preset-react編譯
// fn=()=>{} 設定一個箭頭函式,但是不符合ES6語法,需要babel-preset-react編譯
}
render(){
// render必須寫還必須有返回的東西
return <section>
<h3>系統提示</h3>
<div>
zhufeng
</div>
</section>
}
}
ReactDOM.render(<div>
<Dialog>
<span>d</span>
</Dialog>
</div>,root);
複製程式碼
元件中的屬性(this.props)是調取元件的時候(建立類例項的時候)傳遞給元件的資訊,這部分資訊是隻讀的(只能獲取不能修改)-> "元件的屬性是隻讀的"
Object.defineProperty(this.props,'cont',{
writable:true
});
複製程式碼
用這種方法也改不了
元件部分的總結
建立元件有兩種方式:一是“函式式”,一是“建立類式”
【函式式】
1、操作簡單 2、能實現的功能也很簡單,只是簡單的調取和返回
【建立類式】
1、操作相對複雜一點,但是也可以實現更為複雜的業務功能 2、能夠使用生命週期函式操作業務 3、函式式可以理解為靜態元件(元件中內容調取的時候,就已經固定了,很難再修改),而類這種方式,可以基於元件內部的狀態來動態更新渲染的內容:
所謂函式元件是靜態元件,和執行普通方法一樣,調取一次元件,就把元件中內容獲取到,如果不重新調取元件,顯示內容是不發生改變的
【需求】實現頁面上時間的走動
1、函式式的
import React from 'react';
import ReactDOM from 'react-dom';
function Clock() {
return <div>
<h3>當前北京時間為:</h3>
<div style={{color:'red',fontWeight:'bold'}}>{new Date().toLocaleString()}</div>
</div>
}
/*每隔一秒重新調取元件*/
setInterval(()=>{
ReactDOM.render(<Clock/>,root);
},1000)
//適用於元件內容不會再次發生改變的情況下
複製程式碼
2、建立類式
class Clock extends React.Component{
constructor(){
super();
// 初始化元件狀態(都是物件型別):要求我們在constructor中把後期需要使用的狀態資訊全部初始一下(約定俗稱的語法規範)
this.state = {
time:new Date().toLocaleString(),
}
}
componentDidMount(){
//react生命週期函式之一:第一次元件渲染完成後觸發(我們只需要間隔1000ms把state狀態中的time資料改變,這樣react會幫我們元件中的部門內容進行渲染)
setInterval(()=>{
// this.state.time = new Date().toLocaleString(); //雖然下面的定時器可以修改狀態,但是不會通知react重新渲染頁面,這樣不行
//修改元件的狀態
// 1、修改部分狀態:會用我們傳遞的物件和初始化的state進行匹配,只把我們傳遞的屬性進行修改,沒有傳遞的依然保留原始的狀態資訊(部分修改)
// 2、修改狀態修改完成,會通知react把元件進行重新渲染
this.setState({
time:new Date().toLocaleString(),
},()=>{
/*當通知react把需要重新渲染的JSX元素重新渲染完成後,執行的回撥操作(類似於生命週期中的componentDidUpdate)專案中一般使用鉤子函式*/
// 設定回撥的原因是:通知完就直接往下執行,render方法是個非同步操作
});
},1000)
}
render(){
return <div>
<h3>當前北京時間為:</h3>
<div style={{color:'red',fontWeight:'bold'}}>{this.state.time}</div>
</div>
}
}
ReactDOM.render(<Clock/>,root);
複製程式碼
React中的元件有兩個非常重要的概念:
1、元件的屬性:[只讀]調取元件的時候傳遞進來的資訊 2、元件的狀態:[讀寫]自己在元件中設定和規劃的(只有類宣告式元件才有狀態的管控你,函式式元件宣告不存在狀態的管理)
元件狀態類似於VUE中的資料驅動:
我們資料繫結的時候是基於狀態值繫結,當修改元件狀態後,對應的JSX元素也會跟著重新渲染(差異渲染:只把資料改變的部分重新渲染,基於
DOM-DIff
演算法完成)
當代前端框架最重要的核心思想就是:“資料操作檢視(檢視影響資料)”,讓我們告別JQ手動操作DOM的時代,我們以後只需要改變資料,框架會幫我們重新渲染檢視,從而減少直接操作DOM(提高效能,也有助於開發效率)
儘量少操作DOM
五、React的用法
在react當中: 1、基於資料驅動(修改狀態資料,react幫助我們重新渲染檢視)完成的元件叫做“受控元件(受資料管控的元件)” 2、基於ref操作DOM實現檢視更新,叫做“非受控元件” 真實專案中,建議多使用“受控元件”
VUE:MVVM 資料更改,檢視跟著改變,檢視更改,資料也跟著改變(雙向資料繫結) React:MVC 資料更改檢視跟著改變(原本是單向的,但是我們可以手動設定為雙向的)
render(){
let {text} = this.state;
return <section className='panel panel-default'>
<div className='panel-heading'>
<input type="text" className='form-control' value={text} onChange={ev=>{
// 在onChange中修改狀態資訊,實現的是檢視改變資料
this.setState({
text:ev.target.value
})
}}/>
</div>
<div className='panel-body'>
{text}
</div>
</section>
}
複製程式碼
六、生命週期
所謂生命週期函式(鉤子函式)描述一個函式或者元件從建立到銷燬的過程,我們可以在過程中間,基於鉤子函式完成自己的一些操作(例如:在第一次渲染完成做什麼,或者在第二次即將重新渲染之前做什麼等...)
1、基本流程
【基本流程】
constructor
: 建立一個元件componentWillMount
: 第一次渲染之前render
:第一次渲染componentDidMount
: 第一次渲染之後 【修改流程】 當元件的狀態資料發生改變(setState)或者傳遞的屬性發生改變(重新呼叫元件,傳遞不同的屬性)都會引發render重新執行渲染(渲染也是差異渲染)shouldComponentUpdate
是否允許元件重新渲染componentWillUpdate
重新渲染之前render
第二次及以後重新渲染componentDidUpdate
重新渲染之後
componentWillReceiveProps
父元件把傳遞給子元件的屬性發生改變後觸發的鉤子函式 屬性改變也會改變子元件重新渲染,觸發鉤子函式
【銷燬】 原有的渲染的不消失,以後不能基於資料改變檢視
componentWillUnmount
解除安裝元件之前(一般不用)
index.js:
import React from 'react';
import ReactDOM, {render} from 'react-dom';
import PropTypes from 'prop-types';
import 'bootstrap/dist/css/bootstrap.css'
class A extends React.Component {
static defaultProps = {}; // 第一個執行,屬性設定預設值
constructor() {
super();
console.log('1=constructor');
this.state = {
n: 1
}
}
componentWillMount() {
console.log('3=componentWillMount 第一次渲染前', this.refs.HH);
// 在這裡,如果直接setState修改資料(同步的),會把狀態資訊改變後,然後render和didMount,如果setState是放到一個非同步操作中完成(例如:定時器或者從伺服器獲取資料),也是先執行render和did
// 然後再執行這個非同步操作修改狀態,緊接著走修改的流程(這樣和放到didMount中沒啥區別),所以我們一般吧資料請求放到DID中處理
// 真實專案中的資料繫結,第一次元件渲染,我們都是繫結的預設屬性,第二次才是從伺服器獲取的資料,有些屬性,我們需要根據資料是否存在,判斷顯示隱藏
}
componentDidMount() {
console.log('4=componentWillMount 第一次渲染後', this.refs.HH);
//真實專案中,這個階段一般做如下處理:
// 1、控制狀態資訊更改的操作
// 2、從伺服器獲取資料,然後修改狀態資訊,完成資料繫結
setInterval(() => {
this.setState({
n: this.state.n + 1
})
}, 5000)
}
shouldComponentUpdate(nextProps, nextState) {
// this.state.n 更新之前的
console.log('5=shouldComponentUpdate 函式返回true(允許),false(不允許)');
// return true
/*在這個鉤子函式中,我們獲取的state不是最新修改的,而是上一次的state的值
例如:第一次載入完成後,5000ms後,我們基於setState把n修改為2,但是此處獲取的還是1呢
但是這個有兩個引數:
nextProps:最新修改的屬性
nextState:最新修改的狀態
*/
if (nextState.n > 3) {
return true
} else {
return false
}
}
componentWillUpdate(nextProps, nextState) {
// this.state.n 也是更新之前的,也有兩個引數儲存最新的資訊
console.log('6=componentWillUpdate');
}
componentDidUpdate() {
// this.state.n 更新之後的
// 先render
console.log('8=componentWillUpdate');
}
render() {
console.log('2=render');
return <section ref='HH'>
{this.state.n}
</section>
}
}
ReactDOM.render(<main>
<A></A>
</main>, root);
複製程式碼
七、複合元件的傳值
父元件傳子元件:
基於屬性傳即可(而且傳遞是單方向的:只能把資訊給兒子,兒子不能直接把資訊作為屬性傳遞給父親) 後期子元件中的資訊需要修改: 可以讓父元件傳給子元件的資訊發生變化(也就是子元件接收的屬性發生變化,子元件會重新渲染 =>
componentWillReceiveProps
鉤子函式)
子改父:
類似於這種子改父的操作,我們需要使用一下技巧: 1、把父元件中一個方法作為屬性傳遞給子元件 2、在子元件中,把基於屬性傳遞進來的方法,在合適的時候執行(相對於在執行父元件中的方法:而這個方法中完全可以操作父元件的資訊)