


新しい HTML5 機能 Mutation Observer_html5 チュートリアル スキルに基づいたエディターの取り消しおよびロールバック操作の実装
MutationObserver の概要
MutationObserver は、特定の範囲内の DOM ツリーが変更されたときに適切に対応できる機能を開発者に提供します。この API は、DOM3 イベント仕様で導入された Mutation イベントを置き換えるように設計されています。
Mutation Observer は、DOM の変更を監視するためのインターフェイスです。 DOM オブジェクト ツリーに変更が発生すると、Mutation Observer に通知されます。
Mutation Observer には次の機能があります:
•すべてのスクリプト タスクが完了するまで実行前に待機します。つまり、非同期で行います。
•DOM 変更を 1 つずつ処理するのではなく、DOM 変更レコードを処理用の配列にカプセル化します。
•DOM ノードで発生するすべての変更を監視でき、特定の種類の変更も監視できます
MDN 情報: MutationObserver
MutationObserver はコンストラクターであるため、作成時に new MutationObserver;
を渡す必要があります。MutationObserver をインスタンス化する場合、コールバック関数が必要です。コールバック関数は、指定された DOM ノード (ターゲット ノード) が変更されたときに呼び出されます。
呼び出されると、オブザーバー オブジェクトは 2 つのパラメーターとともに関数に渡されます。1: 最初のパラメータは、複数の MutationRecord オブジェクトを含む配列です。
2: 2 番目のパラメータはオブザーバー オブジェクト自体です。
例:
});
オブザーバーメソッド
インスタンスオブザーバーには 3 つのメソッドがあります: 1: 監視 ; 2: 切断 ;
メソッドを観察しますObserve メソッド: 監視する必要があるターゲット ノードを現在のオブザーバー オブジェクトに登録し、ターゲット ノードで DOM が変更されたときに通知を受け取ります (同時にその子孫ノードを監視することもできます)。 このメソッドには 2 つのパラメーターが必要です。1 つ目はターゲット ノードで、2 つ目のパラメーターは変更を監視する必要があるタイプ (json オブジェクト) です。例は次のとおりです。
コードをコピーします
'attributeOldValue' : true, //属性の元の値
'characterDataOldValue' : true
});
切断メソッド
takeRecords
オブザーバー オブジェクトのレコード キューをクリアし、Mutation イベント オブジェクトを含む配列を返します。
MutationObserver は、指定したノード内で発生する変更が毎回記録されるため、エディターのやり直しと元に戻すの実装に最適です。従来のキーダウンまたはキーアップの実装を使用する場合、次のような欠点があります。
1: スクロールが失われ、スクロール位置が不正確になります。2: フォーカスを失った;
....MutationObserver を通じて実装された、元に戻すとやり直し (元に戻すとロールバックの管理) のための管理プラグイン MutationJS を作成するのに数時間かかりました。別のプラグインの紹介として: (
http://files.cnblogs.com/files/diligenceday/MutationJS.js):
コードをコピーします/**
* @desc MutationJs は、指定されたノード要素をリッスンすることで DOM3 の新しいイベント MutationObserve を使用し、内部 dom 属性または dom ノードの変更をリッスンし、対応するコールバックを実行します。*/
window.nono = window.nono || {};
/**
* @desc
**/
nono.MutationJs = function( dom ) {
//統一互換性の問題
var MutationObserver = this.MutationObserver = window.MutationObserver ||
window.WebKitMutationObserver ||
window.MozMutationObserver;
// ブラウザーがまたは MutationObserver;
this.mutationObserverSupport = !!MutationObserver;
//デフォルトでは、子要素、子要素の属性、および属性値の変更をリッスンします;
this.options = {
'childList': true,
'subtree' : true,
'attributes' : true,
'characterData' : true,
'attributeOldValue' : true,
'characterDataOldValue' : true
} ;
//MutationObserve のインスタンスを保存します;
this.muta = {};
//リスト変数はユーザーの操作を保存します;
this.list = [ ];
//現在のロールバック インデックス
this.index = 0;
//dom がない場合は、デフォルトで body をリッスンします;
this.dom = dom|| .documentElement.body || document. getElementsByTagName("body")[0];
//すぐに監視を開始します;
this.observe( );
};
$.extend(nono. MutationJs.prototype, {
//ノード変更のコールバック。やり直しと元に戻すをリストに保存する必要があります。
"callback" : function ( records ,instance ) {
// をクリアする必要がありますインデックスの後ろのもの;
this .list.splice( this.index 1 );
var _this = this;
records.map(function(record) {
var target = record.target;
console.log(record) ;
//要素を削除または追加します;
if( Record.type === "childList" ) {
//要素を削除する場合;
if (record.removedNodes.length ! == 0) {
//要素の相対インデックスを取得します;
var Indexs = _this.getIndexs(target.children, Record.removedNodes);
_this.list .push({
"undo " : function() {
_this.disconnect();
_this.addChildren(target, Record.removedNodes ,indexs );
_this.reObserve();
},
"redo " : function() {
_this.disconnect();
_this.removeChildren(target, Record.removedNodes );
_this.reObserve();
}
});
//要素が追加された場合;
};
if(record.addedNodes.length !== 0) {
//要素の相対インデックスを取得;
var Indexs = _this.getIndexs( target.children , Record.addedNodes );
_this.list.push({
"元に戻す" : function() {
_this.disconnect();
_this.removeChildren(target, Record.addedNodes );
_this.reObserve();
},
"redo" : function () {
_this.disconnect();
_this.addChildren(target, Record.addedNodes, Indexes);
_this.reObserve();
}
});
};
//@desc 文字データとは一体何ですか;
//ref: http:// baike.baidu.com/link?url=Z3Xr2y7zIF50bjXDFpSlQ0PiaUPVZhQJO7SaMCJXWHxD6loRcf_TVx1vsG74WUSZ_0-7wq4_oq0Ci-8ghUAG8a
}else if( Record.type === "characterData" ) {
var oldValue = record.oldValue;
var newValue = record .target.textContent //|| Record.target.innerText は IE789 互換性を処理する準備ができていないため、innerText は必要ありません;
_this.list.push({
"元に戻す" : function() {
_this.disconnect();
target.textContent = oldValue;
_this.reObserve();
},
"やり直し" : function () {
_this.disconnect();
target.textContent = newValue;
_this.reObserve();
}
});
//属性が変更された場合、スタイル、データセット、属性はすべて属性の変更に属しており、統合処理が可能です;
}else if( Record.type === "attributes" ) {
var oldValue = record.oldValue;
var newValue = record.target.getAttribute( record.attributeName );
var attributeName = record.attributeName;
_this.list.push({
target.setAttribute(attributeName, oldValue);
_this.reObserve();
},
"重做 (" : function ) {
_this.disconnect();
target.setAttribute(attributeName, newValue);
_this.reObserve();
}
});
}
}
} } );
// 重新設定索引;
this.index = this.list.length-1;
},
"removeChildren" : function ( target, Nodes ) {
for ( var i= 0, len=nodes.length; i
};
},
"addChildren" : 函數(目標、節點、索引) {
for(var i= 0, len=nodes.length;我 if(target.children[indexs[i]]) {
target.insertBefore(nodes[i], target.children[indexs[i]]) ;
}else{
target.appendChild(nodes[i]);
};
};
},
//快速方法,用於判斷子元素在父元素的哪個節點上;
"indexOf" : function ( target, obj ) {
return Array.prototype.indexOf.call ( target, obj)
},
"getIndexs" : function (target, objs) {
var result = [];
for(var i=0; i
};
回傳結果;
},
/**
* @desc 指定監聽的物件
**/
"observe" : function( ) {
if( this.dom.nodeType !== 1) return alert("參數不同,第一個參數應該是一個dom 節點");
this. muta = new this.MutationObserver( this.callback.bind(this) );
//立即開始監聽;
this .muta.observe( this.dom, this.options );
},
/**
* @desc 重新開始監聽;
**/
"reObserve" : function () {
this.muta.observe( this.dom, this.options );
},
/**
*@desc 不記錄dom操作, 所有在這個函數內部的操作不會記錄到undo和redo的列表中;
**/
"without" : function ( fn ) {
this.disconnect();
fn&fn ();
this.reObserve();
},
/**
* @desc 取消監聽;
**/
"disconnect" : function () {
return this.muta.disconnect() ;
},
/**
* @desc 儲存Mutation操作到list;
**/
},
/**
* @desc ;
**/
"save" : function ( obj ) {
if(!obj.undo)returnalert("傳進來的第一個參數必須有undo方法才行");
if(!obj.redo)returnalert( "傳進來的第一個參數必須有redo方法才行");
this.list.push(obj) ;
},
/**
* @desc 把指定index後面的操作刪除;
**/
"reset " : function () {
//清空備份;
this.list = [];
this .index = 0;
},
/**
* @desc 往回走, 取消回退
**/
"splice" : 函數(index ) {
this.list.splice(index );
},
/**
* @desc 往前走,重新操作
**/
"undo" : function () {
if( this.canUndo() ) {
this.list[this.index].undo();
this.index--;
};
},
/**
* @desc 判斷是否可以撤銷操作
**/
"重做" : function () {
if( this.canRedo ( ) ) {
this.index ;
this.list[this.index].redo();
};
},
/**
* @desc 判斷是否可以重新操作;
**/
"canUndo" : function () {
return this.index !== -1;
},
/***/
"canRedo" : function () {
返回this.list.length-1 !== this.index;
}
MutationJS 如何使用
那這個MutationJS怎麼用呢?
//これは MutationJS オブジェクトをインスタンス化します。パラメータが渡されない場合、デフォルトで body 要素の変更を監視します。
mu = new nono.MutationJs();
//指定した要素を渡すことができます。例:
mu = new nono.MutationJS( document.getElementById("div0") );
//この要素の下にあるすべての要素の変更がプラグインによって記録されます。 ;
ミューテーション インスタンス mu にはいくつかのメソッドがあります:
1: mu.undo() 操作のロールバック
2: mu.redo() ロールバックを元に戻す
3: mu.canUndo() が逆に操作できるかどうか、戻り値は true または false です。
4: mu.canRedo() がロールバックをキャンセルできるかどうか、戻り値は true または false です。
5: mu.reset() はすべての元に戻すリストをクリアし、スペースを解放します。
6: mu.without() は関数パラメータを渡しますが、関数内のすべての DOM 操作はによって記録されません。
MutationJS は、参照用に単純な undoManager を実装しています。これは、Firefox、Chrome、Google Chrome、および IE11 で完全に動作します。
<スクリプト src="http://cdn.bootcss.com/jquery/1.9.0/jquery.js">
<スクリプト src="http://files.cnblogs. com/files /diligenceday/MutationJS.js">
MutationObserver元の一連のミューテーション イベントを削除すると、ブラウザは指定された要素の下にあるすべての要素の追加、削除、置換などを監視します;
;
;
;
<入力値= "テキスト" id="値">
<スクリプト>
window.onload = function () {
window.mu = new nono.MutationJs();
//監視をキャンセル
mu.disconnect();
//監視を再開
mu .reObserve();
document.getElementById("b0").addEventListener("click", function ( ev ) {
div = document.createElement("div");
div.innerHTML = document .getElementById("value ").value;
document.getElementById("div").appendChild( div );
});
document.getElementById("prev").addEventListener("click" , function ( ev ) {
mu.undo();
});
document.getElementById("next").addEventListener("click", function ( ev ) {
mu.redo ();
});
};
IE でのデモのスクリーンショット:
MutatoinObserver のブラウザ互換性:
機能 | クロム | Firefox (Gecko) | Internet Explorer | オペラ | サファリ |
---|---|---|---|---|---|
基本サポート |
18
26 |
14(14) | 11 | 15 | 6.0WebKit |

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











ファイルの転送中に、転送ができない問題に直面したことはありますか?最近、多くの Windows ユーザーが、ファイルをフォルダーにコピーして貼り付けるときに、「宛先フォルダーのファイル名が長すぎます」というエラーがスローされるという問題に直面したと報告しています。さらに、他の Windows ユーザーの中には、ファイルを開くときに「ファイル名または拡張子が長すぎる」とファイルを開くことができないと不満を漏らす人もいました。これにより、ファイルを他のフォルダーに転送できなくなり、ユーザーは失望します。この問題を分析する中で、私たちは問題を軽減し、ユーザーが簡単にファイルを転送できるようにする一連の解決策を考え出しました。同様の状況にある場合は、この投稿を参照して詳細を確認してください。出典:https

Python コードを作成するには、統合開発環境 (IDE) を使用するより良い方法はありません。作業をよりシンプルかつ論理的にできるだけでなく、プログラミングのエクスペリエンスと効率も向上します。これは誰もが知っています。問題は、数多くの選択肢の中から最適な Python 開発環境をどのように選択するかです。

最近、多くの Windows ユーザーが、Microsoft Windows で認識されないアプリケーションを起動しないよう Windows Defender SmartScreen がユーザーに警告し、毎回「とにかく実行」オプションをクリックしなければならないことにイライラしたと報告しています。 Windows ユーザーは、これを回避または無効にするために現時点で何ができるのかわかりません。この問題を調査した結果、システムの Windows Defender 機能は、設定アプリケーションまたはローカル グループ ポリシー エディターを使用するか、レジストリ ファイルを調整することによって無効にできることがわかりました。こうすることで、ユーザーは防御側の SmartScreen に直面する必要がなくなります。お使いのシステムでも次のような問題が発生した場合は、

C言語は基本的かつ重要なプログラミング言語であり、初心者にとっては適切なプログラミングソフトウェアを選択することが非常に重要です。市場にはさまざまな C プログラミング ソフトウェアのオプションがありますが、初心者にとってはどれが自分に適しているかを選択するのは少し混乱するかもしれません。この記事では、初心者がすぐに始められ、プログラミング スキルを向上できるように、5 つの C 言語プログラミング ソフトウェアをお勧めします。 Dev-C++Dev-C++ は、無料のオープンソース統合開発環境 (IDE) であり、特に初心者に適しています。シンプルで使いやすい統合エディター、

Windows 7 の Windows MovieMaker を覚えていますか? Windows MovieMaker の販売を中止して以来、Microsoft は本格的なムービー メーカーをリリースしていません。一方で、小型軽量の内蔵ビデオエディターを搭載して写真アプリを刷新しようとしました。長い時を経て、Microsoft はすべての Windows 11 デバイス向けに優れたビデオ プロセッサである Clipchamp を発売しました。この記事では、Windows 11 デバイス上の Clipchamp アプリからすべてを取得する方法について詳しく説明します。 Clipchamp の使い方 – 詳細なチュートリアルが利用可能

多くの Windows ユーザーは、ログイン試行の失敗や複数のシステムのシャットダウンにより、Windows 11/10 システムにログインできないという問題に遭遇しました。ユーザーは何もできないのでイライラしています。ユーザーは、システムにログインするための PIN コードを忘れたり、ソフトウェアの使用またはインストール時に遅延が発生したりして、システムが何度も強制的にシャットダウンされる可能性があります。したがって、消費者がこの問題を解決するのに間違いなく役立つ、利用可能な最良のソリューションのリストを作成しました。さらに詳しく知りたい場合は、この記事を読み続けてください。注: これを行う前に、PIN をリセットするためのシステム管理者の資格情報と Microsoft アカウントのパスワードを持っていることを確認してください。そうでない場合は、1 時間ほど待って、正しい PIN を使用して試してください。

Windows に Clipchamp をインストールして使用する方法 Clipchamp アプリはまだ Windows にプリインストールされていませんが、これは将来の予定です。同時に、最初に Clipchamp をダウンロードしてインストールする必要があります。 Windows 11 および Windows 10 に Clipchamp をインストールして使用するには: Microsoft Store から Clipchamp をダウンロードしてインストールします。インストールしたら、[スタート] メニューで Clipchamp を検索して起動します。 Clipchamp ウィンドウでは、Microsoft または Google アカウントでログインするか、自分の個人メールを使用する必要があります。

ワード エディタ (ワード プロセッサとも呼ばれます) は、ドキュメントの作成、印刷、編集を可能にするデバイスまたはソフトウェアとして定義できます。取り消し線のキーボード ショートカットを含む、さまざまなキーボード ショートカット、文字、コマンドを使用して、コンテンツを入力したり、画面や印刷物に表示したり、電子的に保存したり、キーボードから変更したりできます。コンピューターは、さまざまな問題の解決に役立つように作られています。ただし、ワードプロセッサが役立つ機能の中で最も人気があるのはワードプロセッサです。技術の進歩により、モバイル デバイスやコンピュータにインストールされたソフトウェア アプリケーションとして、またはさまざまなプロバイダーが提供するクラウド サービスとしてテキスト エディタにアクセスできるようになりました。ワード プロセッサは、電動タイプライターに似たスタンドアロン型のマシンとして 1960 年代初頭に初めて導入されました。タイプライターよりも優れています。
