質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

1回答

1340閲覧

javascriptで先行してuiを更新する方法

Hayashi_Jelly

総合スコア26

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

1クリップ

投稿2021/10/16 13:22

編集2021/10/18 23:17

前提・実現したいこと

  • DOMContentLoaded イベント発生した時点で、

大量の要素に対し、イベントハンドラの登録や初期処理を行う
load()(ユーザー定義) 処理を行っています。
これが完了すると、文書が整って見えるようになるのですが、
多少(5秒程度)、時間が掛かるので、
その間は画面全体に半透明のフィルターを発生させて、
ロード中であることを明示しています。
半透明のフィルターは、元々は表示されており(display: block;)、
同じく、DOMContentLoaded イベント内の最後で、
非表示(display: none)にしています。

  • webシステムなどではなく、ローカルで閲覧するhtmlファイルなのですが、

オリジナルの状態から、UI経由で文書の状態を変更したものを保存(ctrl + s)
したいケースが多々あります。
保存された状態のhtmlを閲覧しようとすると、半透明のフィルターは非表示
の状態で保存されているため、半透明のフィルターは表示されなくなってしまいます。

  • 前置きが長くなりましたが、

ここで、一番最初の処理として、半透明のフィルターを再表示する
init()(ユーザー定義) 処理を行い、再表示されるようにしたいのですが、
これが、うまくいきません。

  • 下記していますが、DOMContentLoadedloadedイベントを分けて上手くいかなかったので、

原因が良く分かっていません。
なぜ、このようになってしまうのか、または、どのようにすればうまくいくのか
ご教示いただきたいです。

該当のソースコード

具体的なコードがなく、申し訳ないのですが・・・

html

1<head> 2 <style> 3 .no-disp-important { display: none !Important; } 4 </style> 5</head> 6<div id='loading'> 7</div> 8<div id='main'> 9</div> 10<script> 11(function() { 12 document.addEventListener('DOMContentLoaded', () => { 13 init(); // 半透明のフィルターを再表示 14 load(); // イベントハンドラの登録や初期処理 15 show(); // 半透明のフィルターを除去 16 }, false); 17}()); 18 19function init() { 20 const loading = document.getElementById('loading'); 21 loading.classList.remove('no-disp-important'); 22} 23 24function load() { 25 // 大量の要素に対し、イベントハンドラの登録や初期処理を行う 26 // 5秒程度掛かる 27 : 28} 29 30function show() { 31 const loading = document.getElementById('loading'); 32 loading.classList.add('no-disp-important'); 33} 34 35</script>

試したこと

  • プロセスが同じでは無理かと思い、DOMContentLoadedloadedイベントで区別する
  • UIスレッドじゃないと意味ないのでは?と思いつつ、

スレッドを分ければいいのかと思い、非同期処理にしてみる。

js

1 document.addEventListener('DOMContentLoaded', () => { 2 new Promise((resolve, reject) => { 3 init(); 4 }); 5 }, false); 6 window.addEventListener('load', () => { 7 new Promise((resolve, reject) => { 8 load(); 9 resolve(); 10 }) 11 .then((resolve, reject) => { 12 show(); 13 }); 14 }, false);
  • タイマーを使って待ち合わせてみる。

js

1 document.addEventListener('DOMContentLoaded', () => { 2 new Promise((resolve, reject) => { 3 init(); 4 }); 5 }, false); 6 window.addEventListener('load', () => { 7 new Promise((resolve, reject) => { 8 const waiting = function() { 9 const timeoutId = setTimeout(waiting, 1000); 10 const loading = document.getElementById('loading'); 11 if (!loading.classList.contains('no-disp-important')) { 12 clearTimeout(timeoutId); 13 } 14 } 15 waiting(); 16 resolve(); 17 }) 18 .then((resolve, reject) => { 19 return load(); 20 }) 21 .then((resolve, reject) => { 22 show(); 23 }); 24 }, false);

いずれの結果も同じで、フィルターを発生させることはできません

環境

  • Microsoft Edge

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2021/10/18 00:51 編集

ちょっと質問内容が伝わってきません 半透明のオーバーレイが乗った状態で保存(?)したら半透明にしたいということですか? その状態なら多分そうなると思いますが・・・ そもそもJSで構築したHTMLを保存できる状態なのでしょうか?
Lhankor_Mhy

2021/10/18 00:54

関数load の処理には非同期的なものは含まれないのですか?
Hayashi_Jelly

2021/10/19 23:22 編集

伝わりづらく申し訳ありません。 htmlは手書きしたものとかではなく、プログラムから生成されるものです。jsは手書きです。 また実際のコードで、jsはクラスの追加・削除で表示・非表示していて、要素の生成は特にしていません。 生成時点(オリジナル)のテキストとしては、オーバーレイ要素(id=loading)に、非表示クラス(disp-no-important)は付加されてなく、 初回閲覧時に、show()処理で非表示クラスが付加されます。 これ以降、htmlを保存すると、オーバーレイ要素に非表示クラスが付加された状態で保存されるため、 次回閲覧時にはオーバーレイが発生しない状態から開始されてしまいます。 これを解消するために、init()処理で、真っ先に非表示クラスを削除すればいいという実装をしているのですが、これが上手くいっておりません。 環境をあまり考えていませんでしたが、win10 + edgeです 保存すると、クラスが追加・削除された状態でテキストが保存されています。 関数load の処理は、addEventListenr()が大量にあります。 addEventListenr()は非同期という認識です。
Lhankor_Mhy

2021/10/19 00:42

わかりにくくで申し訳ないです。 load()の処理が5秒かかるとのこと、5秒間もブロッキング処理をするのは一般的ではないかな、と思いましたので非同期でノンブロックにしてあるのではないかな、と思ったのです。 つまり、「load()の終了」と「load()の処理終了」とはイコールではないのではないかな、ということがお聞きしたいことです。
Hayashi_Jelly

2021/10/20 00:07

あまり、JavaScript、というより非同期処理について理解できてなく、余計混乱させてしまったら申し訳ありませんが・・・ 「load()の終了と、load()の処理終了をイコールにする」は、「load() 内部をpromiseで囲う」、という認識です。 実際のload() 処理は、そのようなコードはありません。load()の終了と、load()の処理終了は同じです。 理想では、load()の処理の間、オーバレイが画面全体に発生し、ロード中であることが明記されるため、 あまりノンブロッキングにする意味はないのかな、と思っています。
Lhankor_Mhy

2021/10/20 00:35

とすると、DOMの再描画に依存するコードが書いてあるとかですかね……?
Lhankor_Mhy

2021/10/20 00:43

そうか、保存しない時は上手く動作していたということは、load()→show()の流れには問題がなくて、init()→load()に問題があるのではないかな?
guest

回答1

0

ベストアンサー

推測ですが、こういうことかもしれません。
setTimeout でラップすることによって、イベントループを回すことができます。
サンプルを置いておきます。
https://jsfiddle.net/Lhankor_Mhy/juymew7f/

js

1 (function () { 2 document.addEventListener('DOMContentLoaded', () => { 3 init(); 4 setTimeout(() => { // setTimeout をコメントアウトすると#loadingが表示されない 5 load(); 6 show(); 7 }, 0); 8 }, false); 9 }());

参考:

DOM への変更はタスクが完了した後にのみ描画されます

イベントループ(event loop): microtask と macrotask

投稿2021/10/20 01:15

Lhankor_Mhy

総合スコア36158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Hayashi_Jelly

2021/10/20 23:56

うまくいきました。ありがとうございます。 参考の方も読ませていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問