不能有子元素,所以我用role='checkbox'和aria-checked={isChecked}从div创建了另一个元素。然后,我处理了鼠标和键盘事件来切换检查状态。问题是:如何触发'change'事件?下面的代码在react 16中不起作用ref">
我用一个普通的div
/span
制作了a custom checkbox control
。
因为<input type='checkbox'.../>
不能有子元素,所以我用role='checkbox'
和aria-checked={isChecked}
从div
创建了另一个元素。
然后,我处理了鼠标和键盘事件来切换检查状态。
问题是:
如何触发'change'
事件?下面的代码在react 16中不起作用
refTarget?.current?.dispatchEvent(new Event('change', { bubbles: true, cancelable: false }))
另一个技巧是直接调用props.onChange
。
它可以工作,但事件不会冒泡到父<form onChange={(e) => console.log('changed!')}></form>
发布于 2021-07-14 22:01:29
你有两种方法可以做到这一点。
1.动态创建所有事件。
eventTarget.dispatchEvent
不能在React中工作。有关替代方法和有关这方面的更多信息,请查看this question。
2.从输入接收onChange事件
您可以接收保持真实的input
元素被不透明隐藏,并使其跨越您的元素的全宽/全高。那么你只需要在这个input
上监听onChange
就行了。
material-ui就是这样做的
示例
const { useCallback, useState, useRef } = React;
const MyCheckBox = React.forwardRef((props, ref) => {
const { onChange, onBlur, onFocus, ...otherProps } = props;
const [checked, setChecked] = useState(false);
const handleFocus = useCallback((e) => {
// do something,
// like add some className for effects
if (typeof onFocus === 'function')
onFocus(e)
}, [])
const handleBlur = useCallback((e) => {
// do something,
// like remove some className for effects
if (typeof onBlur === 'function')
onBlur(e)
}, [])
const handleChange = useCallback((e) => {
setChecked(e.target.checked);
if (typeof onChange=== 'function')
onChange(e)
}, []);
return <div onFocus={handleFocus} onBlur={handleBlur} className="checkbox-root">
{checked ? 'Checked' : 'Not checked'}
<input onChange={handleChange} ref={ref} type="checkbox" className="checkbox-input" {...otherProps} />
</div>
})
const App = (props) => {
return <div>
<MyCheckBox onChange={e => console.log('change', e.target.checked)} onFocus={e => console.log('focus')} onBlur={e => console.log('blur')} />
</div>;
}
ReactDOM.render(<App />, document.querySelector('#root'))
.checkbox-root {
position: relative;
height: 40px;
width: 40px;
border: 1px solid red;
}
.checkbox-input {
position: absolute;
opacity: 0.1;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
margin: 0;
}
.hidden-input {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@material-ui/core@latest/umd/material-ui.production.min.js"></script>
<div id="root"/>
https://stackoverflow.com/questions/68384512
复制