Event.target neden Typescript'te Öğe değil?


116

Bunu sadece KeyboardEvent'imle yapmak istiyorum

var tag = evt.target.tagName.toLowerCase();

Event.target, EventTarget türünde iken, Element'ten miras almaz. Bu yüzden bunu şöyle yapmalıyım:

var tag = (<Element>evt.target).tagName.toLowerCase();

Bu muhtemelen bazı tarayıcıların standartlara uymamasından kaynaklanıyor, değil mi? TypeScript'te doğru tarayıcı agnostik uygulaması nedir?

Not: KeyboardEvent'i yakalamak için jQuery kullanıyorum.


7
Biraz daha temiz sözdizimivar element = ev.target as HTMLElement
Adrian Moisa

Yanıtlar:


57

ElementTüm olay hedefleri öğe olmadığından, öğesinden miras almaz .

MDN'den :

Öğe, belge ve pencere en yaygın olay hedefleridir, ancak diğer nesneler de olay hedefleri olabilir, örneğin XMLHttpRequest, AudioNode, AudioContext ve diğerleri.

Kullanmaya KeyboardEventçalıştığınız şey bile bir DOM öğesinde veya pencere nesnesinde (ve teorik olarak başka şeylerde) gerçekleşebilir, bu nedenle tam orada evt.targetbir Element.

Bir DOM öğesindeki bir olaysa, güvenle varsayabileceğinizi söyleyebilirim evt.target. bir Element. Bunun bir tarayıcılar arası davranış meselesi olduğunu düşünmüyorum. Sadece bu EventTarget, daha soyut bir arayüz Element.

Daha fazla okuma: https://typescript.codeplex.com/discussions/432211


8
Bu durumda, KeyboardEvent ve MouseEvent'in her zaman ilişkili Öğeyi içeren kendi EventTarget eşdeğerine sahip olması gerekir. DOM çok tehlikeli ...: /
daniel.sedlacek

7
DOM veya TypeScript konusunda uzman değilim ancak EventTarget tasarımının çok fazla belirsiz olduğunu ve bunun TypeScript ile hiçbir ilgisi olmadığını söyleyebilirim.
daniel.sedlacek

2
@ daniel.sedlacek Öte yandan, KeyboardEvents hem DOM öğelerinde hem de pencere nesnesinde (ve teorik olarak başka şeylerde) oluşabilir, bu nedenle, tam da orada olması gerektiğini düşünmediğiniz sürece, KeyboardEvent.targetbundan daha spesifik bir tür vermek imkansızdır. genel tür ve kodunuzun her yerine koymak zorunda kalmak ister . Bu noktada, acı verici olsa da, sadece açık oyuncu kadrosunu yapmaktan daha iyi olursunuz. EventTargetKeyboardEventKeyboardEvent<T extends EventTarget>KeyboardEvent<Element>
JLRishe

14
Gelecekte başkaları için yararlı olduğu durumlarda value, bir <select>etiketin özelliğine erişmek için belirli bir öğe türü olarak yayınlamam gerekiyordu . eglet target = <HTMLSelectElement> evt.target;
munsellj

1
@munsellj (maalesef) bu, yazılı bir ortamda belirsizlikleri ele almanın doğru yoludur.
pilau

47

Typcript kullanarak, yalnızca işlevim için geçerli olan özel bir arayüz kullanıyorum. Örnek kullanım durumu.

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

Bu durumda, handleChange, hedef alanı HTMLInputElement türünde olan bir nesne alır.

Daha sonra kodumda kullanabilirim

<input type='text' value={this.state.value} onChange={this.handleChange} />

Daha temiz bir yaklaşım, arayüzü ayrı bir dosyaya koymak olacaktır.

interface HandleNameChangeInterface {
  target: HTMLInputElement;
}

daha sonra aşağıdaki işlev tanımını kullanın:

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

Benim kullanım durumumda, handleChange için tek arayanın bir HTML öğesi türü girdi metni olduğu açıkça tanımlanmıştır.


Bu benim için mükemmel çalıştı - her türlü pisliği deniyordum, EventTarget'ı genişletiyordum vs. ama bu en temiz çözüm +1
Kitson

1
Buna ek olarak, olay tanımını genişletmeniz gerekirse, şöyle bir şey yapabilirsiniz:handleKeyUp = (event: React.KeyboardEvent<HTMLInputElement> & { target: HTMLInputElement }) => {...}
Kitson

41

JLRishe'nin cevabı doğru, bu yüzden bunu olay işleyicimde kullanıyorum:

if (event.target instanceof Element) { /*...*/ }

28

Typescript 3.2.4

Mülk almak için hedefi uygun veri türüne çevirmelisiniz:

e => console.log((e.target as Element).id)

Bu <HTMLInputElement>event.target;sözdizimiyle aynı mı ?
Konrad Viltersten

@KonradViltersten, aynı şeyi yapıyorlar. asO JSX çeliştiği çünkü sözdizimi tanıtıldı. asTutarlılık için kullanılması tavsiye edilir . basarat.gitbooks.io/typescript/docs/types/type-assertion.html
Adam

İşte görüyorum. Ayrıca, ekibin arka uç deneyimine bağlı olarak çoğu durumda bir avantaj olan daha fazla C # 'ish gibi görünüyor. Sözdiziminin bir şeye benzediği ancak teknik olarak tamamen farklı bir şeyi ima ettiği sahte arkadaşlardan biri olmadığı sürece. ( Angular ve C # arasında var ve const olduğunu düşünüyorum , üzücü bir deneyimim, hehe).
Konrad Viltersten

2

Eğer uzanır kendi genel arabirimi oluşturmak Could Event. Bunun gibi bir şey mi?

interface DOMEvent<T extends EventTarget> extends Event {
  target: T
}

O zaman bunu şu şekilde kullanabilirsiniz:

handleChange(event: DOMEvent<HTMLInputElement>) {
  this.setState({ value: event.target.value });
}

1

TypeScript ile tür takma adlarını kullanabiliriz, örneğin:

type KeyboardEvent = {
  target: HTMLInputElement,
  key: string,
};
const onKeyPress = (e: KeyboardEvent) => {
  if ('Enter' === e.key) { // Enter keyboard was pressed!
    submit(e.target.value);
    e.target.value = '';
    return;
  }
  // continue handle onKeyPress input events...
};

0

@Bangonkali doğru cevabı veriyor, ancak bu sözdizimi daha okunabilir ve bana daha hoş görünüyor:

eventChange($event: KeyboardEvent): void {
    (<HTMLInputElement>$event.target).value;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.