t_hazawaの日記

株式投資とWebエンジニアリングのブログです。株式投資の目次は→です。 https://t-hazawa.hatenablog.com/entry/2021/02/12/220933

JavaScript中級者になろう 17章を読んだ(DOM4, Web Components)

前: JavaScript中級者になろう 16章(後半)を読んだ (ES2015-17) - t_hazawaの日記

経緯

  • JS力を付けたかった
  • ES2017までの文法はわかったのだと思う
  • でも、世間で使われてるライブラリは多分これからだ!

2022/01/21 21:35

第十七章 DOM4とHTML

十七章第一回 MutationObserver

https://uhyohyo.net/javascript/17_1.html

  • いきなり分からない言葉がでた
  • html5の仕様には、各要素の定義と同時にその要素のdom定義も定められています

  • domも数回のバージョンアップを経験しており、伝統的にdomのバージョンはレベルと呼ばれています 第十章で紹介したXPath、またtextContentなどがレベル3にあたります。レベル3までのDOMは2004年までに策定完了しており、比較的古典的な概念でした。

  • Level 4で一気に進化したっぽい 2022/01/21 21:41
  • ちなみに、W3C仕様では、DOM3までは正式名称を「Document Object Model Level 3」といったのに対し、DOM4はそれが正式名称 HTML5と同様、WHATWGによるLiving Standardも策定

  • HTML5で新しく追加されたtime要素 ただ、このtime要素に対するブラウザ側の視覚的対応はあまり進んでいません

  • DOMContentLoaded, load イベント
  • DOMContentLoadedはdocumentで発生し、loadはwindowで発生する

  • こういう風にDOMをいじりたい場合、画像やCSSが読み込まれているかどうかは関係ないため、DOMContentLoadedがよく使われます。

  • querySelectorAll
  • jQueryからやってきたみたいなものだ (名前が長い)
  • 返り値はどちらもNodeList getElementsByTagNameで返されるものとquerySelectorAllで返されるものは、動的かそうでないかという違いがあります getElementsByTagNameで返されるNodeListは動的ですが、querySelectorAllはそうではありません 動的というのは、呼び出しの後に起きた変化が反映される

  • 日時時刻ばかりでなく時間(何分とか何時間とか)を表す文字列かもしれません

  • for(const time of Array.from(times)){

  • for-of 分の ここに const を書くのね
  • time.title = date.toString();

  • querySelectorAll でとったものも .titleとすればいじれるのね?
  • この例で何が問題かというと、ページを読み込んだ時点であったtime要素には対応できますが、逆にいうとそれ以外は対応できません 今の時代、ページはjavascriptによってどんどん書き換えられます

  • frontendっぽいはなし
  • 新しい要素)がページ(domツリー)に追加されたことを検知する方法があればいい

  • DOM3にも Mutation Events というものがあった 
  • 新しい要素が追加されるとDOMNodeInsertedというイベントが発生 パフォーマンスに問題があるとかで、現在では非推奨

  • Mutation Observerは、DOMに対する変更を検知し、コールバックにより通知

  • var mo = new MutationObserver(function(records){}); DOMツリーに変更があるたびにこの関数が呼ばれます MutationRecordの配列

  • MutationRecordはどんな変更が加えられたのかを示すオブジェクト

  • 実際に監視を開始するには、observeメソッドを呼び出します。第1引数は監視するノード、第2引数はオプションオブジェクト

  • なんか、 ESにネイティブである機能、関数と、ライブラリの関数かの見分けが付けにくい感じがする。
  • childList: true とか attributes: true とか characterData: true とかでなにの変化を検知するか指定できる
  • まだまだめちゃながい
  • 子孫は検知するオプションもある
  • subtree から 2022/01/21 22:22

2022/01/22 20:07

  • discoonect() でおわり
  •     //テキストノード等の場合querySelectorAllがないので確認する
      if(node.querySelectorAll){
    
  • これでメソッドの存在を確かめられるわけね

yomiowa 2022/01/22 20:59

十七章第二回 DOM4的なメソッド

https://uhyohyo.net/javascript/17_2.html

5000字くらい

  • dom4では基本的な機能に対して新しいメソッドがいろいろ追加されました

  • ちなみに、これらのメソッドはjqueryという有名なライブラリの影響を受けているようです

  • DocumentTypeはDOCTYPE宣言、すなわち<!doctype html>の部分を表すノードです。こんなノードもあったのですね とはいえ、HTML5の時代においてはこのノードはほとんど形骸化してしまった

  • 書かなくなったのかな?
  • 最後のProcessingInstruction(処理命令)はXML文書でのみ登場するもので、こういうやつを表すノードです。

  • <?xml-stylesheet href="foo.xsl" type="text/xsl" ?>
  • このように<?で始まり?>で終わるのがProcessing Instruction
  • DocumentTypeとProcessingInstructionはまず使わないでしょう

  • ちなみに、従来は複数の種類のノードに存在すべきメソッドは全部nodeに定義されていました。

  • 互換性の問題から、appendchildといった旧来のメソッドをいきなり消すことはできません。そこで、parentnodeにしかない新しいメソッドを導入することにしたのです。appendchildは依然として存在し続けますが、それでも新しいメソッドを作ることに意味はあります。というのも、最近はjavascriptの開発環境が充実し、自動補完や(typescriptでは)型チェックなどもできるようになりました。 その精度を向上させることができるでしょう

  • まずはappendです。これは子ノードを追加するメソッドです。さきほどまでさんざん例に出してきたappendchildが進化したメソッドです。

  • 進化したポイントは、まず引数は1つだけではなく任意の数可能です。これにより、複数のノードを一度に追加することができます

  • カンたんな名前なのに、見覚えがないメソッドがあるなと思ってた2022/01/24 1:49
  • もう1つは、テキストノードを挿入したいときはdocument.createtextnodeを使ってテキストノードを作るかわりに、引数に文字列を渡すと勝手にテキストノードに変換してくれる

  • 子ノードを追加するメソッドはもう1つあります。prependです。appendでは親ノードの子の最後に全部追加しますが、prependは最初に追加します。

  • つよそう 2022/01/24 1:53
  • firstElementChildとlastElementChildというプロパティがあります。これは、子ノードでElementであるもののうち最初/最後のものを返します。従来(Nodeのプロパティとして)存在したfirstChildとlastChildは、すべての子ノードのうち最初/最後のノードを返すことになります。

  • のulに対してそのfirstChildはulタグとliタグの間にある改行のテキストノードとなりますが、firstElementChildは最初のli要素になります。正直テキストノードとかどうでもいいという場面も多いので、こちらが役に立つ場面が多いでしょう。

  • めんどくさく罠っぽい 改行テキストノードだ
  • 他に、AllではないquerySelectorというメソッドもあり、こちらはセレクタにマッチする要素のうち最初のひとつのみを返します

  • 他に、queryAllとqueryという似た名前のメソッドがあります。こちらはセレクタではなく相対セレクタ(> pみたいな)にマッチする要素を返します。

  • まず、最初のメソッドはremoveです。これは引数なしのメソッドで、親ノードから自身を取り除きます。

  • replaceWithです。これは親のreplaceChildを呼ぶのに相当するメソッドで、引数に渡されたノードで自身を置き換えます。先ほど紹介したappendやprependと同様に、複数のノードや文字列を引数に渡すことができます。

  • beforeとafterメソッドがあります。これは、自分の前または後に、兄弟として引数のノードを追加する

  • プロパティとして、previousElementSiblingとnextElementSiblingがあります。previousElementSiblingは、自身の兄弟ノードで、自身より前にあってElementであるもののうち最初のもの(一番自身に近いもの)を返します。

  • 今回はDOM4時代の基本的なメソッドをいくつか紹介しました。とても便利なメソッドたちですが、現在(2015年5月)まだブラウザの実装がぜんぜん追い付いていない

  • まだ2015/5の情報だった ES2015で大進化したとはいえ長いJS道

よみおわ 2022/01/24 2:05

十七章第三回 Custom Elements

https://uhyohyo.net/javascript/17_3.html

8100字

  • Web Components
  • 名前だけkiitakotoann
  • ウェブページの構築に使える再利用可能なパーツ

  • そのための Custom Elements
  • 実は、独自のHTML要素を作るには、HTMLElementを継承したクラスを作ります クラスの構文を使わないとうまくいきません

  • 要素を定義したらそれをカスタム要素として登録する必要があります window.customElementsを用います。このオブジェクトはdefineメソッドを持っており、このメソッドを用いてカスタム要素を登録します

  • window.customElements.define('my-element', MyElement);

  • 要素名はハイフンマイナス(-)を含む必要があります。ハイフンを含むことで、カスタム要素ではない普通のHTML要素と区別することができます。

  • タグ名にはアルファベット以外も使うことができます。"x-日本語??????"などの要素名も可能です。

  • var elm = document.createElement('my-element');

  • jsでしか使えないのかな html に <my-element> と書いて使えないのかな?
  • カスタム要素のインスタンスはdocument.createElementを使わずに、コンストラクタをnewすることでも作ることができます。 document.body.appendChild(new MyElement());

  • <my-element id="elm">
    <p>これはテストです。</p>
    

    </my-element>

  • 書いてもツカエるらしい
  • 既に取得した要素も変化するというのは興味深いというか面白いというかやばい挙動ですね

  • connectedCallbackメソッドは、その要素が文書に挿入されたときに呼び出されます(引数無し)。

  • 僕の知らない関数がたくさんあるね
  • なんか html に <my-element> と書いた後に CustomElementを定義しても、ちゃんと動作する (不思議)
  • 既に文書中に追加されているので即座にconnectedCallbackが呼ばれるという流れになります

  • なるほど
  • static get observedAttributes(){ return ['content']; } とすると この当時でも クラス内にいれれたという感じ

よみおわ 2022/01/24 22:14

十七章第四回 Shadow DOM

https://uhyohyo.net/javascript/17_4.html

  • 3書いくらい続くshadow dom
  • 8000時
  • ここでは、shadowというのは隠されているということを意味しています。 shadow domによりある要素の実装(中身)を隠蔽することができる

  • shadow domを使うには、要素に対してshadowrootを作ります そのためには、elementが持つattachshadowメソッドを呼び出します。

  • 実は、shadowrootが作られるとその中身が要素の中身となり、子要素たちは無視されるのです。

  • shadowrootを用いて要素の中身を作ってやることで、要素の内部構造が外から見えなくなります。これにより、前回述べたような、外から直接要素の中身をいじられて挙動がおかしくなるというようなことを防ぐことができます。

  • 隠したがり屋3
  • 上の例の12行目にあるように、ある要素に対してShadowRootが作られると、その要素のshadowRootプロパティでShadowRootオブジェクトを取得できます。

  • JSでしか shadowRootの中身は維持れ無いのかな?
  • modeが"open"となっているのを"closed"とすると、ShadowRootが隠されます。つまり、shadowRootプロパティを用いて取得できなくなります

  • 実は、ShadowRootを作ったときはattachShadowの返り値としてShadowRootが得られる

  • 自分はそれを使って維持れる

2022/01/25 22:26 - shadowrootの下にある隠された木構造のことをshadow tree(shadowツリー)といいます - > shadow domの便利さを説明していきます。。。実は、shadowツリーはcssに関して特殊な扱いを受けます。簡単に言うと、shadowツリーの中身は外のスタイル定義の影響を受けません。中のスタイル定義は外に影響を与えません。 - スタイル定義の影響はうけないけど、スタイルけいしょうの影響はうける - > style="color: initial" - これでキャンセルしよう

読了 2022/01/25 23:09 

十七章第五回 Shadow DOM 2

https://uhyohyo.net/javascript/17_5.html

8500じ

  • HTML5のtemplate要素 template要素は、別のところで使いたいHTMLの断片をあらかじめ書いておくことができる要素です。 template>

  • innerHTMLの場合はデータが文字列なので、innerHTMLにそれが代入されるとまずは文字列をHTMLとして解析してDOMの木構造を作る必要があります。対して、template要素の中身は既に解析されており、木構造として保持されています 高速に行うことができる

  • template要素とCustom Elements, Shadow DOMの組み合わせ方です。今後はこれを使っていきましょう。

  • 定番の組合せらしい
  • スロットは、shadowツリーの中にslot要素を配置することにより作ります

  • shadowツリーの中にスロットを配置することで、本来の(shadowツリーではない方の)子要素をスロットの位置に配置することができます

  • <my-element> の中身が template> の中の の中にあらわれるらしい
  • ちなみに、shadowツリーではない本来の子孫たちのことは、shadowツリーと対比してlightツリーと呼ばれます

  • slotは複数おけるとのこと
  • デフォルトスロットとは、name属性により名前が付けられていないスロットです。 同じスロットに複数の要素を入れることができます

  • slot="title" なものが name="title"なslotに入る

よみおわ 2022/01/27 0:19

十七章第六回 Shadow DOM 3

https://uhyohyo.net/javascript/17_6.html

2500時

  • Shadow DOMとイベント shadowツリーの中で発生したイベントはどうなるのでしょうか。 shadowツリーの中で発生したイベントがshadowツリーの外に出た場合、shadowホストが発生源であるように偽装される

  • カスタム要素を使う側はその内部構造を知らなくても要素を使えないといけないのです。

  • shadow domは、カスタム要素を作るときには必須といえるほど便利

十七章第七回 HTML Imports

https://uhyohyo.net/javascript/17_7.html

6500時

  • 今回紹介するのが最後のひとつ、HTML Imports 読み込むのはjavascriptファイルではなくhtml文書

  • 他のhtml文書を読み込むためにやはりlink要素を使います link要素のrel属性を"import"にすることにより、他のhtml文書を読み込むことを示すことができます。

  • 読み込んだHTML文書はJavaScriptから見ることができます。そのためには、link要素のノード(HTMLLinkElement)が持つプロパティimportを参照します。これは、読みこまれた文書を表すDocumentオブジェクトです。

  • ところで、link要素によって読みこまれた文書中にスクリプトがあった場合はどうなるでしょうか。実は、その場合そのスクリプトはちゃんと実行されます 読みこまれる文書内で作られた関数fooを読み込む側の文書で使うことができています

  • 読みこまれる側でもdocumentというグローバル変数が読み込む側の文書を指している

  • 読み込む側の文書となるなら、読みこまれる側の文書を得るにはどうすればよいのでしょうか。それには、document.currentScript.ownerDocumentとします。ownerDocumentは以前紹介しましたね。そのノードが属するDocumentを示すプロパティです。

  • 今まで解説したことを利用すると、カスタム要素の定義を別の文書に独立させることができます。

  • なるほど。この技術、jsの実際の世界で使われてるのかな? 2022/01/28 0:26
  • 今回は全体が無名関数に囲まれています(20?39行目)。この目的は、変数tmpやMyElementクラスを関数の中のローカル変数としてしまうことで外から隠蔽することです

  • template要素はhtmlの概念なので、javascriptファイルだけでなくhtml文書の形で読み込めるようにする必要があったのです。これを可能にしてくれるのがhtml importsというわけですね

  • 特に、類似した機能を持つes modulesが先に安定したためes modulesのほうに注目が集まっているようです。

ヨミオワ 2022/01/28 0:33 あと行っかい!

質問と回答1

https://uhyohyo.net/javascript/qa1.html

3700時

  • String#matchの返り値の配列にはもうひとつinputというプロパティがあり、これは検索対象の文字列全体です。

  • var regexp= /090-(\d{4})-(\d{4})/g;

  • で regexp.exec() すると、lastIndexをつかってうまいこと鄒プできる