覺得比較重要的幾個(gè)點(diǎn)簡單做下筆記方便以后查
1.幾種創(chuàng)建組件的方式
- 組件生命周期相關(guān)的鉤子
- 父子組件通訊
- 高階組件的使用和定義 HOC
組件創(chuàng)建方式
- React.createClass // 已經(jīng)棄用(console直接把React對象打印出來可以加深對API的理解)
const Nav = React.createClass({
render: function() {
return (
<ul>
<li>首頁</li>
<li>我的</li>
</ul>
)
}
});
// React 16.5對外暴露的方法
{
Children: {map: ?, forEach: ?, count: ?, toArray: ?, only: ?}
Component: ? Component(props, context, updater)
Fragment: Symbol(react.fragment)
PureComponent: ? PureComponent(props, context, updater)
StrictMode: Symbol(react.strict_mode)
cloneElement: ? cloneElementWithValidation(element, props, children)
createContext: ? createContext(defaultValue, calculateChangedBits)
createElement: ? createElementWithValidation(type, props, children)
createFactory: ? createFactoryWithValidation(type)
createRef: ? createRef()
forwardRef: ? forwardRef(render)
isValidElement: ? isValidElement(object)
unstable_AsyncMode: Symbol(react.async_mode)
unstable_Profiler: Symbol(react.profiler)
version: "16.5.2"
}
- class Nav extends React.Component 通過繼承Component對象
class Nav extends Component{ };
class Nav extends React.Component{}
兩種方法一樣與模塊導(dǎo)入方式有關(guān)
import * as React from "React"; // 導(dǎo)入全部對象屬性和方法 只能使用第一種默勾,通過React.Component才能繼承
import React,{Component} from 'React' //可以使用以上任意方式繼承方法屬性
import { ObjOne, ObjTwo} from 'Obj' 可以引入多個(gè)方法
- function Nav (){} 通過函數(shù)定義無狀態(tài)組件
無狀態(tài)組件:適合用來聲明沒有組件生命周期方法并且沒有內(nèi)部狀態(tài)的組件位谋。
function Nav({ list }) {
return (
<div> {map(list, (item) => <div>{item.name}</div>)} </div>
);
}
組件通訊
父組件(Teacher) ---> 子組件(Tim) props
class Tim extends Component {
constructor(props) {
super(props)
}
render() {
return (
<div>{this.props.notice}</div>
)
}
}
class Teacher extends Component {
render() {
return (
<Tim notice="明天來上課"></Tim>
)
}
}
子組件(Tim) ---> 父組件(Teacher) 函數(shù)回調(diào)
場景: 操作DOM觸發(fā)
class Tim extends Component {
constructor(props) {
super(props)
}
render() {
return (
<div><input onChange={this.props.handleEmail}/></div>
)
}
}
class Teacher extends Component {
handleEmail(event){
console.log(event.target.value)
}
render() {
return (
<Tim handleEmail={this.handleEmail.bind(this)}></Tim>
)
}
}
場景: 在函數(shù)回調(diào)觸發(fā)
class Tim extends Component {
constructor(props) {
super(props)
}
handleClick(){
this.props.handleEmail('他們已經(jīng)干我了!')
}
render() {
return (
<div>
<div onClick={this.handleClick.bind(this)} > 快來干我褒颈!</div>
</div>
)
}
}
class Teacher extends Component {
handleEmail(event){
console.log(event)
}
render() {
return (
<Tim handleEmail={this.handleEmail.bind(this)}></Tim>
)
}
}
子組件(Tim) ---> 父組件(Teacher) --->爺爺組件(Boss) 函數(shù)回調(diào)
class Tim extends Component {
constructor(props) {
super(props)
}
handleClick() {
this.props.handleEmail('我爸是局長盾鳞!')
}
render() {
return (
<div>
<div onClick={this.handleClick.bind(this)} > 快來干我意系!</div>
</div>
)
}
}
class Teacher extends Component {
handleEmail(event) {
this.props.handleText(event)
console.log("Teacher" + event)
}
render() {
return (
<Tim handleEmail={this.handleEmail.bind(this)}></Tim>
)
}
}
class Boss extends Component {
handleText(event) {
console.log("Boss" + event)
}
render() {
return (
<Teacher handleText={this.handleText.bind(this)}></Teacher>
)
}
}
兄弟組件通訊
Redux || 子組件(Tim) ----> (函數(shù)回調(diào)) 父組件(Teacher) ----> (props) 子組件(Jerry)
//子組件
class Tim extends Component {
constructor(props) {
super(props)
}
handleClick() {
this.props.handleEmail('Jerry你是我最好的朋友父叙!')
}
render() {
return (
<div>
<div onClick={this.handleClick.bind(this)} > 快來點(diǎn)我吧几莽!</div>
</div>
)
}
}
//父組件
class Teacher extends Component {
constructor() {
super()
this.state = {
notice: ""
}
}
handleEmail(val) {
this.setState({
notice: val
})
console.log(val)
}
render() {
return (
<div>
<Tim handleEmail={this.handleEmail.bind(this)}></Tim>
<Jerry notice = {this.state.notice} > </Jerry>
</div>
)
}
}
// 子組件
class Jerry extends Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<div>{this.props.notice}</div>
</div>
)
}
}
生命周期
初始化
- getDefaultProps()
設(shè)置默認(rèn)的props迅办,也可以用dufaultProps設(shè)置組件的默認(rèn)屬性.
- getInitialState()
在使用es6的class語法時(shí)是沒有這個(gè)鉤子函數(shù)的,可以直接在constructor中定義this.state章蚣。此時(shí)可以訪問this.props
- componentWillMount()
組件初始化時(shí)只調(diào)用站欺,以后組件更新不調(diào)用,整個(gè)生命周期只調(diào)用一次,此時(shí)可以修改state矾策。
- render()
react最重要的步驟磷账,創(chuàng)建虛擬dom,進(jìn)行diff算法贾虽,更新dom樹都在此進(jìn)行逃糟。此時(shí)就不能更改state了。
更新
- componentDidMount() * 常用
組件渲染之后調(diào)用蓬豁,只調(diào)用一次绰咽。此時(shí)可進(jìn)行請求數(shù)據(jù),返回?cái)?shù)據(jù)setState后組件會重新渲染 庆尘。此時(shí)this.getDOMNode()訪問真實(shí)的DOM元素剃诅。此時(shí)可以使用其它類庫操作DOM。
- componentWillReceiveProps(nextProps) * 常用
組件初始化時(shí)不調(diào)用驶忌,組件接受父組件改變后的props時(shí)調(diào)用矛辕。
- shouldComponentUpdate(nextProps, nextState)
唯一用于控制組件重新渲染的生命周期,react性能優(yōu)化非常重要的一環(huán)付魔。 組件接受新的state或者props時(shí)調(diào)用聊品,我們可以設(shè)置在此對比前后兩個(gè)props和state是否相同,如果相同則返回false阻止更新几苍,因?yàn)橄嗤膶傩誀顟B(tài)一定會生成相同的dom樹翻屈,這樣就不需要創(chuàng)造新的dom樹和舊的dom樹進(jìn)行diff算法對比,節(jié)省大量性能妻坝,尤其是在dom結(jié)構(gòu)復(fù)雜的時(shí)候
- componentWillUpdata(nextProps, nextState)
組件初始化時(shí)不調(diào)用伸眶,只有在組件將要更新時(shí)才調(diào)用, 此時(shí)可以修改state 刽宪?
- componentDidUpdate()
組件更新完畢后厘贼,組件初始化時(shí)不調(diào)用,組件更新完成后調(diào)用圣拄,此時(shí)可以獲取dom節(jié)點(diǎn)嘴秸。
卸載
- componentWillUnmount()
組件將要卸載時(shí)調(diào)用,一些事件監(jiān)聽和定時(shí)器需要在此時(shí)清除庇谆。
高階組件的使用和定義 (HOC)
概念
- 高階組件通過包裹被傳入的React組件岳掐,經(jīng)過一系列處理,最終返回一個(gè)相對增強(qiáng)的 React 組件饭耳,供其他組件調(diào)用串述。一個(gè)高階組件只是一個(gè)包裝了另外一個(gè) React 組件的 React 組件。
- 屬性代理(Props Proxy)( 高階組件操控傳遞給 WrappedComponent 的 props哥攘,)
使用
- 操作props (對需要傳入的props進(jìn)行攔截剖煌,添加材鹦、刪除逝淹、修改)
// 封裝
const HOC = (WrappedComponent) =>
class WrapperComponent extends Component {
render() {
const msg = {
...this.props,
Sex: 'Male'
}
return <WrappedComponent
{...Sex}
/>;
}
}
// 使用
const Container = HOC(PageIndex);
<Container name="zhang"/>
// PageIndex print
{
Sex: "Male"
name: "Zhang"
}
- 提升state
把被包裹組件(WrappedComponent)中的狀態(tài)提到包裹組件中 通過props把事件傳遞耕姊,然后通過回調(diào)把被包裹組件中state傳出來
class WrappedComponent extends Component {
render() {
return <div className="u-box" {...this.props.name} ></div>;
}
}
const HOC = (WrappedComponent) =>
class extends Component {
constructor(props) {
super(props);
this.state = {
name: '',
};
this.onNameChange = this.onNameChange.bind(this);
}
onNameChange(event) {
console.log(event)
}
render() {
const newProps = {
name: {
onClick: this.onNameChange,
},
}
return <WrappedComponent {...newProps} />;
}
}
const Container = HOC(WrappedComponent)
- 反向繼承(高階組件繼承(extends)WrappedComponent)
//對所有頁面增加Loading(反向繼承方式可以獲取父組件得props、state栅葡。實(shí)用性比較強(qiáng)茉兰,避免很多重復(fù)的勞動)
const HOC = (WrappedComponent) =>
class HOC extends WrappedComponent {
constructor(props) {
super(props);
console.log(props)
}
render() {
if (!this.state.isLoading) {
// 反向繼承
return super.render()
} else {
return <Loading/>
}
}
}
// 使用
const Container = HOC(PageIndex);
Vue中實(shí)現(xiàn)則需要通過插槽的方式把所有頁面插入到該組件中,通過子組件watch父組件傳入的值實(shí)現(xiàn)顯示隱藏欣簇。