原生DOM事件、react16、17和Vue合成事件

目录

原生DOM事件

注册/绑定事件

DOM事件级别

DOM0:onclick传统注册:

唯一(同元素的(不)同事件会覆盖)

没有捕获和冒泡的,只有简单的事件绑定

DOM2:addEventListener监听注册:可添加多个,优先级低于传统注册,IE9以上

引入了事件捕获、冒泡阶段

元素.addEventListener(事件类型type,执行函数handler[,ueseCapture捕获true/false]) 默认值为false(即 使用事件冒泡)

DOM3:对 DOM 2 级事件的扩展。

引入事件类型,如 input、change 等

加入特性

异步执行:

自定义事件:CustomEvent构造函数 创建, dispatchEvent 方法触发

事件的停止:stopPropagation(),preventDefault()

DOM事件流:捕获->冒泡(默认)

执行顺序

具体的元素>层级高document(包括react16事件委托)

同层级的按注册顺序

不支持冒泡:与用户界面交互或设备输入相关

焦点、鼠标进出、加载/卸载、尺寸、表单改变(/提交/重置)

阻止事件

DOM树上的传播(捕获/冒泡):event.stopPropagation()

阻止剩下同事件+event.stopPropagation():event.stopImmediatePropagation()

默认行为(链接的跳转、表单的提交):event.preventDefault():

事件处理位置/DOM元素上的handler值

原生事件:事件处理函数

React:nonp空函数

事件被分解后绑定在document

React17事件统一绑定container

事件保存在fiberNode对象的memoizedProps 和 pendingProps属性中

(React17取消)事件池:创建/回收->数组弹出

1.事件注册(浏览器):初始化事件参数

1.事件合成:用插件机制 初始化事件参数+映射原生事件类型

2.事件绑定:注册监听器,绑定 dispatchEvent统一事件处理

3.事件触发:批量更新处理

Vue

与react区别:不暴露给开发者

绑定处理:模板和指令(@)

用法


原生DOM事件

注册/绑定事件

DOM事件级别

DOM0:onclick传统注册:
唯一(同元素的(不)同事件会覆盖)
没有捕获和冒泡的,只有简单的事件绑定
// 第一种
    <button onclick="console.log(1)">点击</button>

// 第二种
    <button id="btn">点击</button>

    const btn = document.querySelector('#btn')
    btn.onclick = function () {}
DOM2:addEventListener监听注册:可添加多个,优先级低于传统注册,IE9以上
引入了事件捕获、冒泡阶段
元素.addEventListener(事件类型type,执行函数handler[,ueseCapture捕获true/false]) 默认值为false(即 使用事件冒泡
   <button id="btn">点击</button>
   
   const btn = document.querySelector('#btn')
   btn.addEventListener('click', () => {})
DOM3:对 DOM 2 级事件的扩展。
引入事件类型,如 inputchange
加入特性
异步执行:
element.addEventListener('click', function(event) {
  setTimeout(function() {
    // 异步执行的代码
    console.log('异步执行的代码');
  }, 0);
});
自定义事件:CustomEvent构造函数 创建, dispatchEvent 方法触发
// 创建自定义事件
var customEvent = new CustomEvent('myEvent', { detail: { key: 'value' } });

// 添加事件监听器
element.addEventListener('myEvent', function(event) {
  console.log('自定义事件触发了', event.detail.key);
});

// 触发自定义事件
element.dispatchEvent(customEvent);
事件的停止:stopPropagation(),preventDefault()

DOM事件流:捕获->冒泡(默认)

  • 事件捕获:由外往内,从事件发生的根节点开始,逐级往下查找,一直到目标元素。
  • 事件冒泡:由内往外,从具体的目标元素触发,逐级向上传递,直到根节点
element.addEventListener(event, function[, useCapture]);
//useCapture 默认为false,即冒泡阶段调用事件处理函数,
//为ture时,在事件捕获阶段调用处理函数

事件队列:捕获事件,将 unShift到执行队列的前面,冒泡事件,将 push 到执行队列后面 

执行顺序

具体的元素>层级高document(包括react16事件委托)
同层级的按注册顺序

不支持冒泡:与用户界面交互或设备输入相关

焦点、鼠标进出、加载/卸载、尺寸、表单改变(/提交/重置)

  1. focusblur 事件:这些事件与元素获得或失去焦点相关,通常不会冒泡到父元素。

  2. mouseentermouseleave 事件:这些事件在鼠标指针进入或离开元素时触发,不会冒泡。

  3. load 事件:当页面或资源加载完成时触发,不会冒泡到父元素。

  4. unload 事件:在页面即将卸载时触发,不会冒泡。

  5. resize 事件:当浏览器窗口大小改变时触发,不会冒泡。

  6. submit 事件:当表单提交时触发,通常不会冒泡到父元素。

  7. reset 事件:当表单重置时触发,不会冒泡。

  8. change 事件:当用户改变表单元素的值时触发,通常在元素自身上触发而不会冒泡。

阻止事件

DOM树上的传播(捕获/冒泡):event.stopPropagation()

<div id="parent">
  <button id="myButton">Click me</button>
</div>

<script>
const parent = document.getElementById('parent');
const button = document.getElementById('myButton');

parent.addEventListener('click', function(event) {
  console.log('Parent handler');
});

button.addEventListener('click', function(event) {
  console.log('Button handler');
  event.stopPropagation();
});
</script>

阻止剩下同事件+event.stopPropagation():event.stopImmediatePropagation()

如果多个事件监听器被附加到相同元素的相同事件类型上,当此事件触发时,它们会按其被添加顺序被调用

如果在其中一个事件监听器中执行 stopImmediatePropagation() ,那么剩下的事件监听器都不会被调用。

<button id="myButton">Click me</button>

<script>
const button = document.getElementById('myButton');

button.addEventListener('click', function(event) {
  console.log('First handler');
  event.stopImmediatePropagation();
});

button.addEventListener('click', function(event) {
  console.log('Second handler');
});

button.addEventListener('click', function(event) {
  console.log('Third handler');
});
</script>

默认行为(链接的跳转、表单的提交):event.preventDefault():

<a id="myLink" href="https://www.example.com">Click me</a>

<script>
const link = document.getElementById('myLink');

link.addEventListener('click', function(event) {
  console.log('Link clicked');
  event.preventDefault(); // 阻止链接的跳转
});
</script>

事件处理位置/DOM元素上的handler值

原生事件:事件处理函数

React:nonp空函数

button上绑定了两个事件

document上的事件监听器,

button,但是事件处理函数handle,并不是我们的handerClick事件,而是noop

事件被分解后绑定在document

onClick分解:click(事件类型)

onChange分解:blur , change , input , keydown , keyup 

将事件绑定在document统一管理是为了跨浏览器包装

React17事件统一绑定container

ReactDOM.render(app, container);绑定在rootNode

因为微前端一个前端系统中可能有多个应用

事件保存在fiberNode对象的memoizedProps 和 pendingProps属性中

(React17取消)事件池:创建/回收->数组弹出

当事件被频繁的创建和回收,会影响性能

React事件池中事件并不会被释放,而是存入到一个数组中,如果这个事件触发,则直接在这个数组中弹出即可,这样就避免了频繁创建和销毁

但是对应的性能没有提高,所以就React17取消了事件池

1.事件注册(浏览器):初始化事件参数

1.事件合成:用插件机制 初始化事件参数+映射原生事件类型

2.事件绑定:注册监听器,绑定 dispatchEvent统一事件处理

 scorll,focus,blur等是在事件捕获阶段发生的,其他的都是在事件冒泡阶段发生的

3.事件触发:批量更新处理

Vue

与react区别:不暴露给开发者

绑定处理:模板和指令(@)

用法

区别 原生事件 合成事件
命名 纯小写onclick 小驼峰onClick
参数 字符串 函数
阻止默认事件 e.preventDefault()和return false e.preventDefault()

事件源不同,阻止默认事件的方式不同,原生事件和合成事件的e.preventDefault()并非是同一个函数

「react进阶」一文吃透react事件系统原理 - 掘金

合成事件 – React

猜你喜欢

转载自blog.csdn.net/qq_28838891/article/details/134184128