本文为系列文章:
手写虚拟DOM(一)—— VirtualDOM介绍
手写虚拟DOM(二)—— VirtualDOM Diff
手写虚拟DOM(三)—— Diff算法优化
手写虚拟DOM(四)—— 进一步提升Diff效率之关键字Key
手写虚拟DOM(五)—— 自定义组件
手写虚拟DOM(六)—— 事件处理
手写虚拟DOM(七)—— 异步更新
一、前言
今天,我们继续在之前项目的基础上扩展功能。
任何页面除了展示功能数据,也会涉及到人机交互。截止到目前,功能数据的展示我们已经大致实现,本章我们就实现最基本的事件交互(事件处理)。事件有很多,比如:
- 点击事件;
- 滚动事件;
- 键盘事件;
等等;
二、实现事件处理
事件的绑定一般是定义在元素或是组件的属性中:
class DemoComp extends Component {
......
click = () => {
console.log('DemoComp.click');
};
render() {
return (
<div onClick={this.click}>
<div>This is DemoComp....props = {this.props.value}</div>
<div>DemoComp.state.name = {this.state.name}{this.state.value}</div>
</div>
);
}
}
如果我们直接编译,不会有任何报错,也能够正常显示,如下图:
31fdsf43f4wf44.png
点击之后,在 Console 界面,就会提示报错(需要函数名):
f43g9fd0gfdigweg904gfeisfjs.png
将 click 由 class 属性改为方法:
click() {
console.log('DemoComp.click');
};
点击之后,没有任何效果。
但是,我们在React中这么使用就不会有问题,是我们哪里不对么?嗯,肯定不对!
我们回想一下,我们的代码中,哪里设置“属性”?
一共有两处:
- setProps:当
新增/替换
节点时,依次给该节点元素及子元素设置属性值; - diffProps:当
更新
节点时,则是比较dom与vdom的属性,以及各节点的tag;
本章既然讲到了事件,我们应该用 addEventListener 来处理,而不再是 setAttribute。
接下来,我们开始改造我们的属性设置的函数:
事件都是以“on”开头,之后接着是首字母大写的事件名,比如:onClick
function setAttribute(element, key, value) {
if (key.substring(0, 2) === 'on') { // event
element.addEventListener(key.substring(2).toLowerCase(), value.bind(element));
} else {
element.setAttribute(key, value);
}
}
判断如果是on开头,则拿事件名,onClick 的事件名是 click,然后 addEventListener 设置事件名和回调函数;
注:这里的回调函数需要bind该element!
如果不是on开头,就设置属性就行。
function setProps(element, props) {
for (let k in props) {
if (props.hasOwnProperty(k)) {
setAttribute(element, k, props[k]); // 修改此处
}
}
// 保存当前的属性,之后用于新VirtualDOM的属性比较
element['props'] = props;
}
function diffProps(props, element) {
......
// 遍历props的所有键值
Object.keys(all).forEach(key => {
......
// 老vdom没有该属性,or 该属性值与新vdom的属性值不一致
if (ov === undefined || ov !== nv) {
setAttribute(element, key, nv); // 修改此处
}
......
});
......
}
然后,编译运行,查看 Elements 及 Console:
0fje939f032f90hf9ew0f39f3.png
点击结果:
mpecje0w9c203jv029v.png
一切正常!
三、总结
本文基于上一个版本的代码,加入了对事件处理的支持。
项目源码:
https://github.com/qingye/VirtualDOM-Study/tree/master/VirtualDOM-Study-06
网友评论