Heim  >  Artikel  >  Web-Frontend  >  Implementieren von Editor-Rückgängig- und Rollback-Vorgängen basierend auf der neuen HTML5-Funktion Mutation Observer_html5 Tutorial-Fähigkeiten

Implementieren von Editor-Rückgängig- und Rollback-Vorgängen basierend auf der neuen HTML5-Funktion Mutation Observer_html5 Tutorial-Fähigkeiten

WBOY
WBOYOriginal
2016-05-16 15:46:111872Durchsuche

Einführung in MutationObserver

MutationObserver bietet Entwicklern die Möglichkeit, angemessen zu reagieren, wenn sich der DOM-Baum innerhalb eines bestimmten Bereichs ändert. Diese API soll das in der DOM3-Ereignisspezifikation eingeführte Mutation-Ereignis ersetzen.

Mutation Observer ist eine Schnittstelle zur Überwachung von DOM-Änderungen. Mutation Observer wird benachrichtigt, wenn Änderungen im DOM-Objektbaum auftreten.

Mutation Observer verfügt über die folgenden Funktionen:

•Es wartet, bis alle Skriptaufgaben abgeschlossen sind, bevor es ausgeführt wird, d. h. auf asynchrone Weise.
•Es kapselt DOM-Änderungsdatensätze zur Verarbeitung in ein Array, anstatt DOM-Änderungen einzeln zu verarbeiten.
•Es kann alle Änderungen beobachten, die in DOM-Knoten auftreten, und es kann auch eine bestimmte Art von Änderungen beobachten

MDN-Informationen: MutationObserver

MutationObserver ist ein Konstruktor, daher müssen Sie beim Erstellen einen neuen MutationObserver übergeben;

Beim Instanziieren von MutationObserver ist eine Rückruffunktion erforderlich, wenn sich der angegebene DOM-Knoten (Zielknoten) ändert

Beim Aufruf wird das Beobachterobjekt mit zwei Parametern an die Funktion übergeben:

 1: Der erste Parameter ist ein Array, das mehrere MutationRecord-Objekte enthält;

 2: Der zweite Parameter ist das Beobachterobjekt selbst

Zum Beispiel:

 


Code kopierenDer Code lautet wie folgt:
var observer = new MutationObserver( function(mutations ) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});



Beobachtermethoden

Der Instanzbeobachter verfügt über drei Methoden: 1: beobachten; 2: trennen; ;;

Beobachtungsmethode

Beobachtungsmethode: Registrieren Sie den Zielknoten, der beobachtet werden muss, beim aktuellen Beobachterobjekt und erhalten Sie eine Benachrichtigung, wenn sich das DOM im Zielknoten ändert (Sie können gleichzeitig auch seine Nachkommenknoten beobachten); Diese Methode erfordert zwei Parameter, der erste ist der Zielknoten und der zweite Parameter ist der Typ, der auf Änderungen überwacht werden muss, bei dem es sich um ein JSON-Objekt handelt. Das Beispiel lautet wie folgt:

 

Code kopieren

Der Code lautet wie folgt: Observer.observe( document. body, { 'childList': true, //Die untergeordneten Elemente dieses Elements werden hinzugefügt oder gelöscht
'subtree': true, //Alle untergeordneten Elemente dieses Elements werden hinzugefügt oder gelöscht
' attributes': true, //Auf Attributänderungen achten
'characterData': true, //Auf Text- oder Kommentaränderungen warten
'attributeOldValue': true, //Originalwert des Attributs
'characterDataOldValue': wahr
});




Trennmethode
Die Methode „Disconnect“ hört auf, die Eigenschaften und Knotenänderungen des Zielknotens zu beobachten, bis die Observation-Methode das nächste Mal erneut aufgerufen wird

takeRecords

Löschen Sie die Datensatzwarteschlange des Beobachterobjekts und geben Sie ein Array zurück, das das Mutationsereignisobjekt enthält;

MutationObserver eignet sich perfekt zum Implementieren des Wiederherstellens und Rückgängigmachens eines Editors, da alle Änderungen, die innerhalb des angegebenen Knotens auftreten, jedes Mal aufgezeichnet werden. Wenn Sie die herkömmliche Keydown- oder Keyup-Implementierung verwenden, gibt es einige Nachteile, wie zum Beispiel: 1: Scrollen geht verloren, was zu einer ungenauen Scrollposition führt;

2: Fokus verloren;

....

Es dauerte ein paar Stunden, ein Management-Plug-in MutationJS für Undo und Redo (Verwaltung von Undo und Rollback) zu schreiben, das über MutationObserver implementiert wurde und verwendet werden kann als separate Plug-in-Einführung: (

http://files.cnblogs.com/files/diligenceday/MutationJS.js

):



Code kopieren


Der Code lautet wie folgt:


/**
* @desc MutationJs, verwendet das neue Ereignis MutationObserve von DOM3, indem es auf bestimmte Knotenelemente lauscht, auf Änderungen in internen Dom-Attributen oder Dom-Knoten wartet und entsprechende Rückrufe ausführt;*/
window.nono = window.nono ||. {};
/**
* @desc
**/
nono.MutationJs = function( dom ) {
//Einheitliche Kompatibilitätsprobleme
var MutationObserver = this.MutationObserver = window.MutationObserver ||
window.WebKitMutationObserver ||
window.MozMutationObserver;
//Bestimmen Sie, ob der Browser vorhanden ist oder Ob MutationObserver unterstützt werden soll;
this.mutationObserverSupport = !!MutationObserver;
// Standardmäßig auf Änderungen in untergeordneten Elementen, Attributen von untergeordneten Elementen und Attributwerten warten;
this.options = {
'childList': true,
'subtree': true,
'attributes': true,
'characterData': true,
'attributeOldValue': true,
'characterDataOldValue' : true
} ;
//Dies speichert die Instanz von MutationObserve;
this.muta = {};
//Die Listenvariable speichert die Operationen des Benutzers;
this.list = [ ];
//Der aktuelle Rollback-Index
this.index = 0;
//Wenn kein Dom vorhanden ist, wird standardmäßig auf den Body gelauscht;
this.dom = dom|| .documentElement.body ||. document. getElementsByTagName("body")[0];
//Überwachung sofort starten;
this.observe( );
};
$.extend(nono. MutationJs.prototype, {
//Rückruf für Knotenänderungen, Sie müssen das Wiederherstellen und Rückgängigmachen in der Liste speichern;
"callback" : function ( Records , Instanz ) {
//Sie müssen das löschen diejenigen hinter dem Index;
this .list.splice( this.index 1 );
var _this = this;
Records.map(function(record) {
var target = record.target;
console.log(record) ;
//Elemente löschen oder hinzufügen;
if( record.type === "childList" ) {
//Wenn Sie Elemente löschen;
if (record.removedNodes.length ! == 0) {
//Den relativen Index des Elements abrufen;
var indexes = _this.getIndexs(target.children, record.removedNodes);
_this.list .push({
"undo " : function() {
_this.disconnect();
_this.addChildren(target, record.removedNodes ,indexes );
_this.reObserve();
},
"redo " : function() {
_this.disconnect();
_this.removeChildren(target, record.removedNodes );
_this.reObserve();
}
});
//Wenn Elemente hinzugefügt werden;
};
if(record.addedNodes.length !== 0) {
//Den relativen Index des Elements abrufen ;
var indexes = _this.getIndexs( target.children , record.addedNodes );
_this.list.push({
"undo" : function() {
_this.disconnect();
_this.removeChildren(target, record.addedNodes );
_this.reObserve();
},
"redo" : function () {
_this.disconnect();
_this.addChildren(target, record.addedNodes, indexes);
_this.reObserve();
}
});
};
//@desc Was zum Teufel ist CharacterData? ;
//ref: http:// baike.baidu.com/link?url=Z3Xr2y7zIF50bjXDFpSlQ0PiaUPVZhQJO7SaMCJXWHxD6loRcf_TVx1vsG74WUSZ_0-7wq4_oq0Ci-8ghUAG8a
}else if( record.type ===. "charact erData") {
var oldValue = record. oldValue;
var newValue = record.target.textContent //||, ist nicht für die IE789-Kompatibilität vorbereitet, daher wird innerText nicht benötigt;
_this.list.push({
"undo" : function() {
_this.disconnect();
target.textContent = oldValue;
_this.reObserve();
},
"redo" : function () {
_this.disconnect();
target.textContent = newValue;
_this.reObserve();
}
});
//Wenn sich die Attribute ändern , Stil, Datensatz, Attribut gehören alle zu Attributänderungen, Sie können eine einheitliche Verarbeitung durchführen;
}else if( record.type === "attributes" ) {
var oldValue = Record.oldValue;
var newValue = Record.target.getAttribute( Record.attributeName );
var attributeName = Record.attributeName;
_this.list.push({
"실행 취소" : function() {
_this.disconnect();
target.setAttribute(attributeName, oldValue);
_this.reObserve();
},
"redo" : function() {
_this.disconnect();
target.setAttribute(attributeName, newValue);
_this.reObserve();
}
});
};
} );
//중신설设置索引;
this.index = this.list.length-1;
},
"removeChildren" : 함수( 대상, 노드 ) {
for( var i= 0, len= node.length; i target.removeChild( node[i] );
};
},
"addChildren": 함수( 대상, 노드, 인덱스) {
for(var i= 0, len= 노드.길이; 나는 if(target.children[ indexs[i] ]) {
target.insertBefore( 노드[i] , target.children[ 인덱스[i] ]) ;
}else{
target.appendChild( 노드[i] );
};
};
},
//快捷방법,사용来判断child재父元素的哪个节点上;
" indexOf": 함수(target, obj) {
return Array.prototype.indexOf.call(target, obj)
},
"getIndexs": 함수(target, objs) {
var 결과 = [];
for(var i=0; i result.push( this.indexOf(target, objs[i]) );
};
return result;
},
/**
* @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" : 함수 () {
this.muta.observe( this.dom, this.options );
},
/**
*@desc는 DOM 작업을 기록하지 않으며 이 함수 내의 모든 작업은 실행 취소 및 다시 실행 목록에 기록되지 않습니다.
**/
"without" : function ( fn ) {
this.disconnect();
fn&fn ();
this.reObserve();
},
/**
* @desc 모니터링 취소;
**/
"disconnect" : function () {
return this.muta.disconnect() ;
},
/**
* @desc Mutation 작업을 목록에 저장합니다.
**/
"save" : function ( obj ) {
if(!obj.undo)return warning("传进来的第一个参数必须 유 실행 취소 방법 실행");
if(!obj.redo)return 경고("传进来的第一个参数必须유재실행 방법 실행");
this.list.push(obj) ;
},
/**
* @desc ;
**/
"reset" : function () {
//清空数组;
this.list = [];
this .index = 0;
},
/**
* @desc 지정된 인덱스 뒤의 작업을 삭제합니다.
**/
"splice" : 함수( 인덱스 ) {
this.list.splice( 인덱스 );
},
/**
* @desc 뒤로 이동, 롤백 취소
**/
"undo" : function () {
if( this.canUndo() ) {
this.list[this.index].undo();
this.index--;
};
},
/**
* @desc 계속해서 다시 하세요
**/
"redo" : function () {
if( this.canRedo( ) ) {
this.index ;
this.list[this.index].redo();
};
},
/**
* @desc는 작업을 취소할 수 있는지 여부를 결정합니다
**/
"canUndo": 함수() {
return this.index !== -1;
},
/**
* @desc는 재작동 가능 여부를 결정합니다.
**/
"canRedo": 함수() {
return this.list.length-1 !== this.index;
}
});

MutationJS如何使사용

那么这个MutationJS如何使사용呢?


复代码
代码如下:

//Dies dient dazu, ein MutationJS-Objekt zu instanziieren, es überwacht standardmäßig Änderungen im Body-Element;
// Sie können ein angegebenes Element übergeben. Zum Beispiel:
mu = new nono.MutationJS( document.getElementById("div0") );
//Dann werden alle Elementänderungen unter diesem Element vom Plug-in aufgezeichnet ;

Mutationsinstanz mu hat mehrere Methoden:

1: mu.undo()-Operations-Rollback;

2: mu.redo() Rollback rückgängig machen;

3: Ob mu.canUndo() zurückoperieren kann, der Rückgabewert ist wahr oder falsch;

4: Ob mu.canRedo() den Rollback abbrechen kann, der Rückgabewert ist wahr oder falsch;

5: mu.reset() löscht alle Rückgängig-Listen und gibt Speicherplatz frei

6: mu.without() übergibt einen Funktionsparameter und alle DOM-Operationen innerhalb der Funktion werden von mu nicht aufgezeichnet;

MutationJS implementiert einen einfachen UndoManager als Referenz, der perfekt auf Firefox, Chrome, Google Chrome und IE11 läuft:

Code kopieren

Der Code lautet wie folgt:







MutationObserver dient zum Ersetzen. Entfernen Sie die ursprüngliche Reihe von Mutationsereignissen, und der Browser überwacht das Hinzufügen, Löschen, Ersetzen usw. aller Elemente unter dem angegebenen Element;



;
;

;



<script><br> window.onload = function () {<br> window.mu = new nono.MutationJs();<br> //Überwachung abbrechen<br> mu.disconnect();<br> //Überwachung neu starten<br> mu .reObserve(); <br> document.getElementById("b0").addEventListener("click", function ( ev ) {<br> div = document.createElement("div");<br> div.innerHTML = document .getElementById("value").value;<br> document.getElementById("div").appendChild( div );<br> });<br> document.getElementById("prev").addEventListener("click" , function ( ev ) {<br> mu.undo();<br> });<br> document.getElementById("next").addEventListener("click", function ( ev ) {<br> mu.redo ();<br> });<br> };<br></script>



Screenshot der DEMO unter IE:

Browserkompatibilität von MutatoinObserver:

Funktion Chrom Firefox (Gecko) Internet Explorer Oper Safari
Grundlegende Unterstützung
18

Webkit

26

14(14) 11 15 6.0WebKit

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn