DOM编程 动态脚本 1 2 3 4 5 6 7 8 9 10 11 function loadScriptString (code ) { var script=document .createElement("script" ); script.type="text/javascript" ; try { script.appendChild(document .createTextNode(code)); }catch (ex){ script.text=code; } document .body.appendChild(script); } loadScriptString("function sayHi(){alert('hi');}" );
动态样式 1 2 3 4 5 6 7 8 9 10 11 12 function loadStyleString (css ) { let style=document .createElement("style" ); style.type="text/css" ; try { style.appendChild(document .createTextNode(css)); }catch (ex){ style.styleSheet.cssText=css; } let head=document .getElementsByTagName("head" )[0 ]; head.appendChild(style); } loadStyleString("body[background-color:red}" );
对于IE,要小心使用styleSheet.cssText,如果重用同一个style元素并设置该属性超过一次,则可能导致浏览器崩溃,将cssText设置为空字符串也可能导致浏览器崩溃
表单 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 let table=document .createElement("table" );table.border=1 ; table.width="100%" ; let tbody=document .createElement("tbody" );table.appendChild(tbody); table.insertRow(0 ); tbody.rows[0 ].insertCell(0 ); tbody.rows[0 ].cells[0 ].appendChild(document .createTextNode("Cell 1,1" )); tbody.rows[0 ].insertCell(1 ); tbody.rows[0 ].cells[1 ].appendChild(document .createTextNode("Cell 2,1" )); table.insertRow(1 ); tbody.rows[1 ].insertCell(0 ); tbody.rows[1 ].cells[0 ].appendChild(document .createTextNode("Cell 1,2" )); tbody.rows[1 ].insertCell(1 ); tbody.rows[1 ].cells[1 ].appendChild(document .createTextNode("Cell 2,2" )); document .body.appendChild(table);
NodeList 1 2 3 4 5 let divs=document .getElementsByTagName("div" );for (let i=0 ,len=divs.length;i<len;i++){ let div=doocument.createElement("div" ); document .body.appendChild(div); }
Mutationobserver接口 在DOM被修改时异步执行回调,使用MutationObserver可以观察整个文档,DOM树的一部分或某个元素
MutationObserver的实例通过调用MutationObserver构造函数并传入一个回调函数创建
1 let observer=new MutationObserver(()=> console .log('DOM was mutated' ));
observe()方法 接收两个参数:要观察其变化的DOM节点,以及一个MutationObserverInit对象(用于控制观察哪些方面的变化,是一个键值对形式配置选项的字典)
1 2 let observer=new MutationObserver(()=> console .log('<body> attributes changed' ));observer.observe(document .body,{attributes :true });
body元素上任何属性发生变化都会被这个MutationObserver实例发现,然后异步执行注册的回调函数,body元素后代修改或其他非属性修改不会触发回调进入任务
1 2 3 4 5 6 let observer=new MutationObserver(()=> console .log('<body> attributes changed' ));observer.observe(document .body,{attributes :true }); document .body.className='foo' ;console .log('Changed body class' );
回调与MutationRecord 每次回调都会收到一个MutationRecord实例的数组,包含的信息发生了什么变化以及DOM哪一部分受到影响
1 2 3 4 5 6 7 8 9 let observer=new MutationObserver((mutationRecords )=> console .log(mutationRecords));[observer.observe(document .body,{attributes :true }); document .body.setAttributeNS('foo' ,'bar' ,'baz' );let observer=new MutationObserver((mutationRecords )=> console .log(mutationRecords));observer.observe(document .body,{attributes :true }); document .body.className='foo' ;document .body.className='bar' ;
disconnect()方法 会停止此后变化事件的回调,也会抛弃已经加入任务队列要异步执行的回调
1 2 3 4 5 6 7 8 9 10 11 let observer=new MutationObserver(()=> console .log('<body>attributes changed' ));observer.observe(document .body,{attributes :true }); document .body.className='foo' ;observer.disconnect(); document .body.className='bar' ;setTimeout (()=> { observer.disconnect(); document .body.className='bar' ; },0 );
复用MutationObserver 1 2 3 4 5 6 7 8 9 10 let observer=new MutationObserver((mutationRecords )=> console .log(mutationRecords.map((x )=> x.target)));let childA=document .createElement('div' ); childB=document .createElement('span' ); document .body.appendChild(childA);document .body.appendChild(childB);observer.observe(childA,{attributes :true }); observer.observe(childB,{attributes :true }); childA.setAttribute('foo' ,'bar' ); childB.setAttribute('foo' ,'bar' );
重用MutationObserver 调用diaconnect()不会结束MutationObserver的生命,还可以重新使用这个观察者,再将它关联到新的目标结点
MutationObserverInit与观察范围 观察属性 设置attributes为true,观察所有属性
1 2 3 4 5 6 7 8 9 let observer=new MutationObserver((mutationRecords )=> console .log(mutationRecords));observer.observe(document .body,{attributes :true }); document .body.setAttribute('foo' ,'bar' );document .body.setAttribute('foo' ,'baz' );document .body.removeAttribute('foo' );
用attributeFilter添加白名单属性
1 2 3 4 5 6 let observer=new MutationObserver((mutationRecords )=> console .log(mutationRecords));observer.observe(document .body,{attributeFilter :['foo' ]}); document .body.setAttribute('foo' ,'bar' );document .body.setAttribute('baz' ,'qux' );
在记录中保存属性原来的值
1 2 3 4 5 6 let observer=new MutationObserver((mutationRecords )=> console .log(mutationRecords.map((x )=> x.oldValue)));observer.observe(document .body,{attributeOldValue :true }); document .body.setAttribute('foo' ,'bar' );document .body.setAttribute('foo' ,'baz' );document .body.setAttribute('foo' ,'qux' );
观察字符数据 1 2 3 4 5 6 7 8 9 10 11 12 13 let observer=new MutationObserver(document .body.firstChild,{characterData :true });document .body.firstChild.textContent='foo' ;observer.observe(document .body.firstChild,{characterData :true }); document .body.firstChild.textContent='foo' ;document .body.firstChild.textContent='bar' ;document .body.firstChild.textContent='baz' ;let observer=new MutationObserver((mutationRecords )=> console .log(mutationRecords.map((x )=> x.oldValue)));document .body.firstChild.textContent='foo' ;observer.observe(document .body.firstChild,{characterDataOldValue :true }); document .body.firstChild.textContent='foo' ;document .body.firstChild.textContent='bar' ;document .body.firstChild.textContent='baz' ;
观察子节点 1 2 3 4 5 6 7 8 document .body.innerHTML='' ;let observer=new MutationObserver((mutationRecords )=> console .log(mutationRecords));document .body.appendChild(document .createElement('div' ));document .body.appendChild(document .createElement('span' ));observer.observe(document .body,{childList :true }); document .body.insertBefore(document .body.lastChild,document .body.firstChild);
观察子树 1 2 3 4 5 document .body.innerHTML='' ;let observer=new MutationObserver((mutationRecords )=> console .log(mutationRecords));document .body.appendChild(document .createElement('div' ));observer.observe(document .body,{attributes :true ,subtree :true }); document .body.firstChild.setAttribute('foo' ,'baz' );
异步回调与记录队列 takeRecords()方法 清空记录队列,取出并·返回其中的所有MutationRecord实例,可以用在希望断开与观察目标的联系,但又希望处理由于disconnect()而被抛弃的记录队列中的MutationRecord实例
1 2 3 4 5 6 7 8 let observer=new MutationObserver((mutationRecords )=> console .log(mutationRecords));observer.observe(document .body,{attributes :true }); document .body.className='foo' ;document .body.className='bar' ;console .log(observer.takeRecords());console .log(observer.takeRecords());