使用一个组件或模块之前,应当知道它能解决的问题是什么,不能解决的问题是什么。使用的最佳实践是什么?
react-spread-props
专门解决日常开发中传递 props
的同时代理绑定事件的需求。
例如开发一个检测用户点击后递增计数的组件:
import React , { Component } from "react"
class GeneralButton extends Component {
constructor (props) {
super(props)
const self = this
self.state = {
count: 0
}
}
render() {
const self = this
return (
<button
{...self.props}
onClick={(e) => {
if (self.props.onClick) {
self.props.onClick(e)
}
self.setState({
count: self.state.count + 1
}, function () {
if (self.state.count > 3) {
if (self.props.onGreaterThree) {
self.props.onGreaterThree()
}
}
})
}}
>{self.state.count}</button>
)
}
}
export default GeneralButton
使用计数按钮
import ReactDOM from "react-dom"
import GeneralButton from "./GeneralButton.js"
ReactDOM.render(
(
<div>
<GeneralButton style={{border: '1px solid red'}} />
传递样式
<hr/>
<GeneralButton onClick={(e) => {
console.log('既可以触发递增,也可以触发用户绑定的 onClick')
}} />
绑定 onClick
<hr/>
<GeneralButton onGreaterThree={() => {
console.log('大于3')
}} />
大于3时回调
</div>
),
document.getElementById('intro-genneral-button-node')
)
观察控制台会看见报错
Warning: Unknown event handler property `onGreaterThree`. It will be ignored.
因为传递 props
的同时代理用户绑定事件的实现代码是:
{...self.props}
onClick={(e) => {
if (self.props.onClick) {
self.props.onClick(e)
}
self.setState({
count: self.state.count + 1
}, function () {
if (self.state.count > 3) {
if (self.props.onGreaterThree) {
self.props.onGreaterThree()
}
}
})
}}
因为 {...self.props}
传递了 onGreaterThree
所以会报错。想要不传递 onGreaterThree
就要过滤 onGreaterThree
var spreadProps = Object.assign({}, self.props.props)
var ignoreProps = ['onGreaterThree']
Object.keys(spreadProps).filter(function (key) {
return ignoreProps.includes(key)
})
// 然后传递 spreadProps
{...spreadProps}
至此实现了传递 props
的同时代理绑定事件的需求。
因为开发组件过程中需要做 react spread props 的操作太多了,所以将实现过程封装成函数能提高开发效率。
import React , { Component } from "react"
import spreadProps from "react-spread-props"
class Button extends Component {
constructor (props) {
super(props)
const self = this
self.state = {
count: 0
}
}
handleClickButton = (e) => {
self.setState({
count: self.state.count + 1
}, function () {
if (self.state.count > 3) {
if (self.props.onGreaterThree) {
self.props.onGreaterThree()
}
}
})
}
render() {
const self = this
let domProps = spreadProps(
self.props,
{ onClick: handleClickButton }
)
return (
<button {...domProps} >{self.state.count}</button>
)
}
}
export default Button
语法: spreadProps(props, proxyProps)
实现功能与 <GeneralButton />
但代码更少更易读。(因为 onGreaterThree
不属于 DOM 事件,所以会被自动过滤)
props.style
和 props.className
将与 proxyProps.style
和 proxyProps.className
自动合并。
你还可以在 proxyProps.onClick
中控制 props.onClick
触发条件。
let domProps = spreadProps(
self.props,
{
onClick: function (){
// do somethings
this.stopTrigger()
}
}
)
<Button onClick={() => {
console.log('因为 this.stopTrigger 用户绑定的 onClick 将不会被触发')
}} />
万一 react-spread-props
错误的将一些新的 DOM 属性过滤了请及时通知我们
你也可以先通过单独传递的方式解决这种意外情况。
<button
{...domProps}
futureAttr="Future unpredictable dom attributes"
>
</button>