ホームページ > ウェブフロントエンド > H5 チュートリアル > 新しい HTML5 機能 Mutation Observer_html5 チュートリアル スキルに基づいたエディターの取り消しおよびロールバック操作の実装

新しい HTML5 機能 Mutation Observer_html5 チュートリアル スキルに基づいたエディターの取り消しおよびロールバック操作の実装

WBOY
リリース: 2016-05-16 15:46:11
オリジナル
1898 人が閲覧しました

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 番目のパラメータはオブザーバー オブジェクト自体です。

例:


コードをコピーします
コードは次のとおりです:
varobserver = new MutationObserver( function(mutations ) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});




オブザーバーメソッド

インスタンスオブザーバーには 3 つのメソッドがあります: 1: 監視 ; 2: 切断 ;

メソッドを観察します

Observe メソッド: 監視する必要があるターゲット ノードを現在のオブザーバー オブジェクトに登録し、ターゲット ノードで DOM が変更されたときに通知を受け取ります (同時にその子孫ノードを監視することもできます)。 このメソッドには 2 つのパラメーターが必要です。1 つ目はターゲット ノードで、2 つ目のパラメーターは変更を監視する必要があるタイプ (json オブジェクト) です。例は次のとおりです。

コードをコピーします

コードは次のとおりです。observer.observe( document. body, { 'childList': true, //この要素の子要素が追加または削除されます
'subtree': true, //この要素のすべての子要素が追加または削除されます
' attribute' : true, //属性の変更をリッスン
'characterData' : true, //テキストまたはコメントの変更をリッスン
'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({ _this.disconnect();
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 target.removeChild(nodes[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 result.push( this.indexOf(target, objs[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 オペラ サファリ
基本サポート 14(14) 11 15 6.0WebKit

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート