React中的事件冒泡

原文:Event Bubbling - Andrew H Farmer

概述

你有没有过不知道该把onChange事件放在什么位置的经历?是放在父组件中,还是子组件中?能两边都放一个处理函数吗?应该用属性传递处理函数吗?

如果你问过这字这类问题,这篇文章就是给你的。

DOM

让我们从没有React的一般DOM的事件冒泡开始谈起。

考虑一下一个普通的,非React的,JavaScript代码。

注意当你点击按钮时,’Button Click’会出现在’Parent Click’之前。这是一个事件起始于目标元素(按钮),然后冒泡到父级元素的例子。注意我们只是添加了一个单击处理函数到按钮和它的父级元素中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
<body>
<div id="parent">
<button id="button">
Click Me
</button>
</div>
<div id="log" style="white-space: pre-wrap;">Log:</div>
<script>
var button = document.getElementById('button');
var parent = document.getElementById('parent');
var log = document.getElementById('log');

button.addEventListener('click', function(event) {
log.appendChild(document.createTextNode("Button Click . "));
});

parent.addEventListener('click', function(event) {
log.appendChild(document.createTextNode("Parent Click . "));
});
</script>
</body>
</html>

React

好了,听说你没有好框架就不写代码?那这个在React中是怎么运作的呢?

考虑以下React组件,NameTitle,它包含了一个子组件,NameInput。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import React from 'react';

class NameInput extends React.Component {
constructor(props) {
super(props);
this.state = {
empty: true,
};
}

handleChange(event) {
this.setState({
empty: event.target.value.length === 0,
});
}

inputStyle() {
if (!this.state.empty) {
return {};
}
return {
backgroundColor: 'pink',
};
}

render() {
return (
<input style={this.inputStyle()}
onChange={this.handleChange.bind(this)}
placeholder="Type Your Name"/>
);
}
}
export default NameInput;

NameTitle:包裹NameInput组件,用于onChange的监听器,并在header打印名字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import React from 'react';
import NameInput from './NameInput';

class NameTitle extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
};
}

handleChange(event) {
this.setState({
name: event.target.value,
});
}

render() {
return (
<div onChange={this.handleChange.bind(this)}>
<h2>Hello {this.state.name}</h2>
<NameInput />
</div>
);
}
}
export default NameTitle;

父组件,NameTitle从在他的子组件中的input获取onChange。

这是一种优秀的策略,它可以添加更多的事件绑定行为到既存组件,而不用在属性中传递一堆事件处理句柄。

总结

在React中的事件绑定跟一般DOM很像。onChange,onFocus,onBlur和其他的事件处理句柄可以直接添加到目标元素或者任何它的父组件中去——甚至在其他的组件中。

参考

  1. Event Bubbling - Andrew H Farmer