以下の内容はhttps://m-hiyama-memo.hatenablog.com/entry/2022/07/19/151506より取得しました。


SVG.js (2)

https://svgjs.dev/docs/3.0/events/ を読んで。

文書を読むと次のように読める。null = {null}。

signature Element {
  sort self
  operation click: (self, ClickHandler) → self 
  operation click: (self, null) → self
}

同じような方式で、dblclick, mousedown, mouseup, mouseover, mouseout, mousemove, touchstart, touchmove, touchleave, touchend, touchcancel がサポートされている。

イベント名そのものがリスナー登録/リスナー削除関数の名前になっている。

  • addEventListener("foo", handler) ≡ foo(handler)
  • removeEventListener("foo") ≡ foo(null)

イベント名間違いは関数名間違いになるのでエラー検出が容易。登録・削除に2つの名前を必要としない。同じ方式でプロパティsetter/getterを単一名にすることが出来る。

  • setFoo(val) ≡ foo(val)
  • getFoo() ≡ foo()

TypeScript定義は:

class Element extends Dom implements Sugar {
  constructor(node?: SVGElement);
  constructor(attr: object);
  // ...
  click(cb: Function | null): this;
  dblclick(cb: Function | null): this;
  // ...
}

Sugerインターフェイスを実装しているのはElementクラスだけ。Sugerは描画APIプロバイダのインターフェイス。Dom API に追加分が Suger に入っているようだ。差分が明確になるので、extends Base implement Addition はいい書き方だ。

interface Sugar {
  fill(): any
  fill(fill: FillData): this;
  fill(color: string): this;
  fill(pattern: Element): this;
  fill(image: Image): this;
  stroke(): any;
  stroke(stroke: StrokeData): this;
  stroke(color: string): this;
  //...
}
イベント登録・削除方式

上記の element.click(handler) , element.click(null) 方式以外に element.on(名前, ハンドラー), element.off(名前) も使える。Eventobject の定義は循環的だが? Event, EventListener型はDOMのEvent, EventListenerをそのままらしい。

class Eventobject {
  [key: string]: Eventobject;
}

class EventTarget {
  events: Eventobject // 内部状態
  // ...
  on(events: string | Event[], cb: EventListener, binbind?: any, options?: AddEventListenerOptions): this;

  off(events?: string | Event[], cb?: EventListener | number, options?: AddEventListenerOptions): this;
  // ..
}

addEventLitener, removeEventListenerも名前だけあるが、使ってない。すべてのイベントリスナー(ほぼイベントハンドラー)を消すには element.off() とする。引数パターン(アリティとアリティごとの引数型リスト)ごとに意味が変わる、あの悪しき習慣名前節約にはなる。

APIの雰囲気〈フレーバー〉の話

jQueryは名前短縮/名前節約により「憶えることが少ない」印象を持たせウケたのかも知れない。名前短縮/名前節約とその逆の比較検討は重要だな。SVG.js は jQuery的発想で設計実装されているから、検討素材には適切だ。

ハンドラー関数の操作で言えば、名前を区別する派だと:

  1. addFooHandler(cb : FooHandler) : Result
  2. getFooHandlesr() : Array
  3. removeFooHandler(id : HandlerID) : Result

メソッドチェーンを使いたいなら:

  1. setFooHandler(cb : FooHandler) : Self
  2. getFooHandles() : FooHandler? これはチェーンにしない。
  3. removeFooHandler() : Self

複数ハンドラーは使わない(単一上書きストア)かスタックに保存する。名前を減らすには:

  1. fooHandler(cb : FooHandler) : Self
  2. getFooHandles() : FooHandler? これはチェーンにしない。
  3. fooHandler(null) : Self
イベントのファイア

ファイア〈発火〉とは、ハンドラー関数がイベントデータを引数にもらって実行されること。

  • element.fire(event) イベントデータを発火させる。
  • element.fire(event, data) 付加的データを伴ってイベントデータを発火させる。
  • element.dispatch(event) 発火した後のイベントを返す。
class Dom extends EventTarget {
   fire(event: Event | string, data?: object): this
   dispatch(event: Event | string, data?: object): Event
   // ...
}

Domクラスに addEventLitener, removeEventListener, dispathcEvent があるが使う気はないらしい。Domクラスは名前短縮/名前節約されている。Dom に対する JDom(Java)のように、JSDom指向なのだろう。JSDomの典型実装がjQuery。

class EventTarget, class Dom, class Element, class Container, class Svg, interface Sugar あたりを https://m-hiyama-second.hatenablog.com/entry/2022/07/16/192103 で見ると、JSDom的発想が分かる。




以上の内容はhttps://m-hiyama-memo.hatenablog.com/entry/2022/07/19/151506より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14