不同框架组件化之间的对比 之 event

788 阅读4分钟

事件

事:職也。从史,之省聲。

件:分也。从人从牛。牛大物,故可分

主要是学习和探究不同的框架的事件:

  1. 不同框架事件系统基础内容,理解事件系统
  2. 内联事件
  3. 事件系统参数
  4. 事件对象
  5. 有自定义事件的框架中的自定义事件系统

React

首先要明白是事件处理程序,本质还是事件监听。

首先 React 的事件的写法设计和原生的 DOM 事件。写法遵循小驼峰,同时 JSX 支持函数,而支持 DOM 中事件字符串。

设计合成事件的目的是为了,跨浏览器的兼容性问题。使用 e 或者 event 是合成事件对象。但是 React 一般都是用受控数据,将数据保存在 State 中,这里我们使用 function Component, 因为示例中,不用考虑 this 的指向问题,但是如果 class Component 中我们,需要明确的知道 this 的指向和 this 的重新绑定。

import React from "react";

const App = props => {
  const [value, setValue] = React.useState(1);

  const handleIncreament = (args, event) => {
    setValue(value + 1);
  };

  const handleDecream = (args, event) => {
    setValue(value - 1);
  };

  return (
    <div>
      <div>目前的值是:{value}</div>

      <div>
        <button onClick={handleIncream}>增加1</button>
        <button onClick={handleDecream}>减去1</button>
      </div>
    </div>
  );
};

React 写法符合原生的 DOM 的写法,只是不再需要 addEventListener 添加句柄。

如果我们要第参数,并且在参数中有有自定数据,还有 event, 这个时候,我们就需要将我们的 handle 事件处理函数封装在一个函数里面,这个函数接收 e 事件对象,然后在将 e 传递给 handle 事件处理函数。 也就是说 event 对象,只能在顶层函数中获取。我们传入了参数之后,就不能直接获取,需要再次封装。

import React from "react";

const MyEvent = () => {
  const [value, setValue] = React.useState(1);

  const handleIncreament = (id, num, e) => {
    console.log(id, num, e);
    setValue(value + 1);
  };

  const handleDecreament = (args, e) => {
    setValue(value - 1);
  };

  return (
    <div>
      <div>目前值是{value}</div>
      <div>
        <button onClick={e => handleIncreament(12, 34, e)}>增加1</button>
        <button onClick={handleDecreament}>减去1</button>
      </div>
    </div>
  );
};

export default MyEvent;

Vue

  • 说法:Vue 页脚事件处理程序。
  • 本质: html 指令: v-on 来兼容事件(支持内联字符串函数的写法)
    • 简写方式: @
  • 事件修饰符
  • 按键修饰符
  • 系统化修饰符
  • .exact 修饰符 鼠标按钮修饰符

上面是模板中使用,Vue 在 模板转换成 render 函数的时候对这些特殊的语法进行特殊的转换,但是我们在自己写 render 函数的时候,这些修饰符可能,就不在能使用了。我们需要自己实现。

总之,Vue 对原生事件做了很多的语法糖,让我们开发的时候,觉得很甜。但是甜归甜,甜虽然可以给我们增加效率。我们还是要回归语言本质的。回归到 Vue 的本质,其实就是回到 render 函数。

示例:

  1. 使用内联字符串函数形式的事件处理程序,v-on 指令和@ 指令简写
<div>
  <button v-on:click="counter += 1">Add 1</button>
  <p>The button above has been clicked {{ counter }} times.</p>
  <button @click="counter -= 1">Add 1</button>
</div>
  1. 参数传递
  1. 事件对象

  2. 自定义事件

Angular

说法:Angular 不叫事件处理,而是叫事件绑定。 绑定方式: 没有使用指令进行绑定,而是使用 (eventName)表示事件的绑定。 当然 Angular 提供了第二种类指令的方式:on-eventName 的方式

示例:

  1. 一个简单的示例

Angular 也支持内联字符串的方式进行函数调用

<button (click)="onSave($event)">Save</button>
<button on-click="onSave($event)">on-click Save</button>
  1. 事件对象

我们处理事件之后,会有一个事件处理程序

<input
  [value]="currentItem.name"
  (input)="currentItem.name=$event.target.value"
/>

input 事件变化之后 将 $event.target.value 赋值给 currentItem.name, 然而 input 的 value 绑定的是 currentItem.name 这就是实现了一个“双绑”。

  1. 自定义事件

Angular 中提供了一个类: EventEmitter, 用于触发事件

class EventEmitter<T> extends Subject {
  constructor(isAsync?: boolean): EventEmitter<T>;
  emit(value?: T): void;
  subscribe(generatorOrNext?: any, error?: any, complete?: any): Subscription;
}
  • 子组件
<button (click)="delete()">Delete</button>
// 向外触发事件
@Output() deleteRequest = new EventEmitter<Item>();

delete() {
  this.deleteRequest.emit(this.item);
}
  • 父组件
<app-item (deleteRequest)="deleteItem($event)" [item]="currentItem"></app-item>

Svelte

Svelte 中也也叫事件处理程序.属于指令式写法,与 Vue 相似

on:eventname={handler}
on:eventname|modifiers={handler}

可见 Svelte 的写法也与 React 类似,也有 类 Vue 的修饰符。

  1. 内联事件处理程序
<button on:click="{() => count += 1}">count: {count}</button>
  1. 事件处理函数,注意写法: 与原生写法相似
<button on:click="{handleClick}">count: {count}</button>
  1. 多事件处理程序
<button on:click="{increment}" on:click="{track}">Click me!</button>
  1. 事件对象, 已经参数传递
<script>
  function track(event) {
    trackEvent(event);
  }
</script>

<button on:click="{track}">Click me!</button>
  1. 组件事件

Svelte 的组件事件,其他的框架,有类似于 redux 的味道。思路和 Vue 差不多。

import { createEventDispatcher } from "svelte";

createEventDispatcher 是一个 函数用于创建一个派发事件器:

const dispatch = createEventDispatcher();

dispatch 就是一个派发器,派发一个事件如 'message' 这个事件就是自定义事件,我们需要携带的参数,可以放在 dispatch 的第二个参数。这个和 Redux 的 action 派发是什么相似的。以及 Vuex 的派发一个 action。

<script>
  import { createEventDispatcher } from "svelte";

  const dispatch = createEventDispatcher();

  function dispatchMessage() {
    dispatch("message", {
      text: "Hi, Message is Good!"
    });
  }
</script>

<button on:click="{dispatchMessage}">
  Click to dispatch message
</button>
  1. 组件的事件和 dom 事件触发提前

当我们有多个嵌套组件的时候,我们可以在最外层组件来监听派发的事件。

小程序

小程序中也不叫事件监听,在小程序使用事件绑定的方式,处理各种事件

小结

  1. 在 React/Vue/Svelte 中以事件处理程序,来处理事件监听
  2. 在 Angular 和小程序中,使用事件绑定来事件处理程序
  3. Vue 和 Svelte 等等事件处理程序的本质是 html指令,React 最为特殊,他自己的实现了一套新的事件语法

todo

  • 良好的整理和示例
  • 原生 js 事件部分