React元件複用
React元件複用的方式有兩種:
1.render Props模式
2.高階元件HOC
上面說的這兩種方式並不是新的APi。
而是利用Raect自身的編碼特點,演化而來的固定編碼寫法。
什麼是render Props模式
1.把prop是一個函式並且要告訴元件要渲染什麼內容的技術,叫做render Props模式。
2.注意的是:並不是該模式叫做render Props就必須使用名為render的props,
實際上可以使用任意的props。
對上面者一句話的詳細說明:
子元件向父元件丟擲資料的時候使用的是:
this.props.render(資料)中render可以是其他名,如果GiveFather.
render Props的簡單使用
現在我們有一個有的需求。
游標放在螢幕上,時時獲取當前座標的位置。
請封裝為一個元件。
MoveCom.js 時時獲取當前座標的位置
import React from 'react';
class MoveCom extends React.Component{
// 提供位置資料
state = {
x: 0,
y:0,
}
// 獲取滑鼠的當前座標
moveHandler = e => {
this.setState({
x: e.clientX,
y:e.clientY
})
}
// 監聽滑鼠的行為
componentDidMount() {
// DOM已經渲染完成了;可以進行DOM操作
window.addEventListener('mousemove',this.moveHandler)
}
render() {
// 將元件中的資料暴露出去this.props.render(資料)
return this.props.render(this.state)
}
}
export default MoveCom
父元件展示位置
import React from 'react';
import ReactDOM from 'react-dom';
import ClassCom from "./components/ClassCom"
import MoveCom from './components/MoveCom'
class Father extends React.Component{
render() {
return (
<div>
<h2> render Props的簡單使用</h2>
{ /* 接受子元件向上丟擲來的資料*/}
<MoveCom render={sonGiveData => {
return (
<p>當前滑鼠的座標橫座標: {sonGiveData.x } 縱座標: {sonGiveData.y }</p>
)
}}></MoveCom>
</div>
)
}
}
ReactDOM.render(
<Father></Father>,
document.getElementById('root')
)
總結
1. 如何將子元件中的資料丟擲去
render() {
return this.props.render(資料)
}
父元件接受資料
<MoveCom render={sonGiveData => {
return (
<!-- 渲染的html以及資料 -->
<p>當前滑鼠的座標橫座標: {sonGiveData } </p>
)
}}></MoveCom>
我們發現上面這個元件只實現了狀態。
並沒有實現UI結構的渲染。
UI結構的渲染是交給render函式來決定返回的內容。
小技巧:在React中 left,right,top,bottom是不需要加上px的。
<p style={{ position:'absolute', left:100, top:200 }}> 不需要加上px的 </p>
this.props.render(資料) 可以將資料傳遞出去
再次說明:上面這個render這個不一定非要叫做render。
只是這樣寫render了,你頁可以叫做Aa,接受的時候使用也用Aa接收。
其實推薦children去代替render。因為這樣更加語義化一些的。
在實際寫的過程中也是用children。
下面我們來將程式碼更改一下,children去代替render。
children去代替render語法上的變化
1.使用render子元件向上丟擲資料:
this.props.render(資料)
1.使用children子元件向上丟擲資料:
this.props.children(資料)
在向上丟擲資料的時候,只是render變為了children。
2.render接受資料:
<MoveCom render={sonGiveData => {
return (
<p>當前滑鼠的座標橫座標: {sonGiveData } </p>
)
}}></MoveCom>
2.children接收資料:
<MoveCom>
{
(data) => {
return (
<p style={{ position:'absolute', left:data.x, top:data.y }}>
橫座標: {data.x } 縱座標: {data.y }
</p>
)
}
}
</MoveCom>
render接收資料的時候,資料是寫在元件上
children接收的時候,將資料寫在了裡面。
render Props中使用 children去代替render
子元件
import React from 'react';
class MoveCom extends React.Component{
// 提供位置資料
state = {
x: 0,
y:0,
}
// 獲取滑鼠的當前座標
moveHandler = e => {
this.setState({
x: e.clientX,
y:e.clientY
})
}
// 監聽滑鼠的行為
componentDidMount() {
// DOM已經渲染完成了;可以進行DOM操作
window.addEventListener('mousemove',this.moveHandler)
}
render() {
// 將子元件中的資料暴露出去,render變為了children
return this.props.children(this.state)
}
}
export default MoveCom
父元件
import React from 'react';
import ReactDOM from 'react-dom';
import ClassCom from "./components/ClassCom"
import MoveCom from './components/MoveCom'
class Father extends React.Component{
render() {
return (
<div>
<h2> render Props的簡單使用</h2>
<MoveCom>
{
(data) => {
return (
<p style={{ position:'absolute', left:data.x, top:data.y }}>
橫座標: {data.x } 縱座標: {data.y }
</p>
)
}
}
</MoveCom>
</div>
)
}
}
ReactDOM.render(
<Father></Father>,
document.getElementById('root')
)
優化React中render Props模式
1.推薦給render Props新增一個校驗。
因為render Props接收的是一個函式並且是必須寫的。
// 規則校驗
MoveCom.propTypes = {
// 如果是使用的children
children: PropTypes.func.isRequired
// render: PropTypes.func.isRequired 如果使用使用的render
}
2.移出事件繫結
// 元件即將解除安裝的時候,移出事件監聽
componentWillUnmount() {
window.removeEventListener('mousemove',this.moveHandler)
}
3.這裡為什麼要移出事件繫結
而我們在頁面中用onClick繫結的事件不需要被移除呢?
因為onClick是借用react來完成的事件繫結,react會自動幫我們移除。
這裡我們不是借用React來完成的事件繫結,因此我們應該手動移除
子元件優化後的程式碼
import React from 'react';
import PropTypes from 'prop-types'
class MoveCom extends React.Component{
// 提供位置資料
state = {
x: 0,
y:0,
}
// 獲取滑鼠的當前座標
moveHandler = e => {
this.setState({
x: e.clientX,
y:e.clientY
})
}
// 監聽滑鼠的行為
componentDidMount() {
// DOM已經渲染完成了;可以進行DOM操作
window.addEventListener('mousemove',this.moveHandler)
}
// 元件即將解除安裝的時候,移出事件監聽-優化的地方
componentWillUnmount() {
window.removeEventListener('mousemove',this.moveHandler)
}
render() {
// 將子元件中的資料暴露出去,render變為了children
return this.props.children(this.state)
}
}
// 規則校驗-優化的地方
MoveCom.propTypes = {
// 如果是使用的children
children: PropTypes.func.isRequired
// render: PropTypes.func.isRequired 如果使用使用的render
}
export default MoveCom