视察者形式引见
视察者设想形式定义了对象间的一种一对多的依靠关联,以便一个对象的状况发作变化时,
一切依靠于它的对象都获得关照并自动革新。
一些好的文章
视察者形式与托付形式的区分
深切明白JavaScript系列(32):设想形式之视察者形式
【Javascript设想形式3】-视察者形式
MutationObserver引见
能够运用的设置
- childList: *true =========================能够视察子元素
- attributes: *true ========================能够视察属性
- characterData: *true ====================能够视察数据
- subtree: *true =========================能够视察一切子女
- attributeOldValue: *true ==================能够保留属性旧值
- characterDataOldValue: ==================*true 能够保留数据旧值
- attributeFilter: ==========================设置指定视察属性元素鸠合
note: Mutation Observers 被限定能够视察Dom序列化状况 在视察textarea内内容转变时 没法触发
observe 一个被视察者对象 一份设置
void observe(
Node target,
MutationObserverInit options
);
disconnet 断开视察者与目的链接
void disconnect();
takeRecords 返回对象一切视察纪录
Array takeRecords();
MutationObserver运用
差别浏览器之间存在兼容性问题
var MutationObserver = window.MutationObserver
|| window.WebKitMutationObserver
|| window.MozMutationObserver;
html
<ol contenteditable oninput="">
<li>Press enter and look at the console</li>
</ol>
猎取list dom
var list = document.querySelector('ol');
实例化MutationObserver
var Observer = new MutationObserver(function(mutations){
});
Mutation Observer 对象
监测childList
Observer.observe(list, {
childList: true
});
不过值得注意的是 这里观察的是list直接child 假如要观察child的child 就须要开启subtree
比如要检测如许的行动
list.childNodes[0].appendChild(document.createElement('div'));
observer须要变动设置
Observer.observe(list, {
childList: true,
subtree: true
});
(mutationObserver观察childlist) jsbin地点
observe 罕见设置 及其诠释
observer.observe(target, {childList:true,subtree:true})
//subtree属性让视察行动举行"递归",这时候,以target节点为根节点的整棵DOM树发作的变化都可能会被视察到
observer.observe(document, {childList:true,subtree:true})
//假如target为document或许document.documentElement,则当前文档中一切的节点增添与删除操纵都邑被视察到
observer.observe(document, {childList:true,attributes:true,characterData:true,subtree:true})
//当前文档中险些一切范例的节点变化都邑被视察到(包括属性节点的变化和文本节点的变化等)
observe 视察characterData
Observer.observe(list, {childList:true});
//假定此时target的outHTML内容为<div>foo<div>,则:
list.childNodes[0].data = "bar";
//不会触发还调函数,由于childList只视察节点的新建与删除,
而这里target节点的子节点依然只要一个,没有多,没有少
Observer.observe(list, {
childList:true,characterData:true});
//加上characterData属性,许可视察文本节点的变化,行不行?
list.childNodes[0].data = "sds";
//照样不会触发还调函数,由于发作变化的是target节点的子节点,我们现在的目的节点只要一个,就是target.
Observer.observe(list, {
childList:true,characterData:true,subtree:true});
//加上subtree属性,视察一切子女节点
list.childNodes[0].data = "cha";
(mutationObserver观察characterdata) jsbin地点
observe 视察attribute
Observer.observe(list, {attributes:true});
//只视察目的节点的属性节点
list.setAttribute("foo","bar");
//不论foo属性存在不存在,都邑触发还调函数
list.setAttribute("foo","bar");
//纵然前后两次的属性值一样,照样会触发还调函数
list.removeAttribute("foo");
//移除foo属性节点,触发还调函数
list.removeAttribute("foo");
//不会触发还调函数,由于已没有属性节点可移除了
Observer.observe(list, {attributes:true,attributeFilter:["bar"]});
//指定要视察的属性名
list.setAttribute("foo","bar");
//不会触发还调函数,由于attributeFilter数组不包括"foo"
list.setAttribute("bar","foo");
(mutationObserver观察attribute) jsbin地点
我们最先做一个编辑器
功用 向前 向后而且按钮要能随时转变
ol设置为contenteditable时,当每次敲击回车时,ol的children会增添一个li 而且我们组织一个observer监听它子元素的变化, 如许我们便能够获得每次转变后一切新的children
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'childList') {
var list_values = [].slice.call(list.children)
.map( function(node) { return node.innerHTML; })
.filter( function(s) {
if (s === '<br>') {
return false;
}
else {
return true;
}
});
console.log(list_values);
}
});
});
observer.observe(list, {
attributes: true,
childList: true,
characterData: true
});
编辑器对与每行变化也须要监测, 我们能够本身组织一个entry保留每次数据
var observer = new MutationObserver(function (mutations) {
// Whether you iterate over mutations..
mutations.forEach(function (mutation) {
// or use all mutation records is entirely up to you
var entry = {
mutation: mutation,
el: mutation.target,
value: mutation.target.textContent,
oldValue: mutation.oldValue
};
console.log('Recording mutation:', entry);
});
});
编辑器统计字数
var observer = new MutationObserver(function(mutations){ mutations.forEach(function(mutation){
if(mutation.type == "characterData") {
var newValue = mutation.target.textContent;
textinputcount.innerHTML = "还能够输入"+(1000 - newValue.length+"字");
}
});