preventDefault的一点妙用
众所周知,event.preventDefault() 用于阻止浏览器的默认行为。如 a 标签的点击事件,默认行为是跳转,但可以在 onClick 的处理函数中使用 e.preventDefault() 阻止跳转,如下:
<a href="http://www.baidu.com" id="baiduLink">去百度</a>
<script>
document.querySelector('#baiduLink').addEventListener('click', e => {
e.preventDefault() // 这里会阻止跳往百度
})
</script>
我们在组件设计上能否借用 preventDefault() 来干一些事情呢?
假设我们有一个 Task 组件,该组件用于展示任务名称,并提供一个删除按钮。点击删除将会删除该任务。
function Task(props: {
name: string,
id: string,
onDelete?: (id:string, e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void
}) {
function internalDelete (id:string, e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
props.onDelete?.(id, e);
console.log('开始执行内部删除逻辑')
}
return <p> {props.name} <button onClick={e => internalDelete(props.id, e)}>Del</button> </p>
}
如果我们想让用户控制是否允许删除任务可以怎么办呢?
方法 1:提供一个 showDeleteButton 的 prop, 如果返回 false 不显示删除按钮
方法 2: 给用户用户传入的 onDelete 方法的返回值赋予一些特殊含义,如果返回 false 则不允许删除
方法 3: 用户在 onDelete 方法里面使用 event.preventDefault() 来阻止组件的默认删除行为。
方法 3 的关键点在于event 有一个属性defaultPrevented
来判断事件在前面是否已经调用 preventDefault(); 在 react 的合成事件中有一个isDefaultPrevented()
方法跟原生的这个属性用处相同。
function Task(props: {
name: string,
id: string,
onDelete?: (id:string, e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void
}) {
function internalDelete (id:string, e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
props.onDelete?.(id, e);
// ⚠️⚠️ 这里可以判断是否用户想阻止删除
if (e.isDefaultPrevented()) {
console.log('用户想阻止删除')
return
}
console.log('开始执行内部删除逻辑')
}
return <p> {props.name} <button onClick={e => internalDelete(props.id, e)}>Del</button> </p>
}
export default () => {
function onDelete (id: string, event: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
if (id === '1') {
console.log(`id为1的任务不允许删除!`)
event.preventDefault();
} else {
console.log('其他的随便你删除吧')
}
}
return <Task id={'1'} name={'task name'} onDelete={onDelete}></Task>
}
event.preventDefault() 与 e.defaultPrevented 是否给你的组件设计提供了一种新思路呢?