执行 innerHTML 里的 <script>
之前在做公司的一个抽奖模板的需求时遇到了 innerHTML 里的 <script>标签不执行的情况,即脚本不被解析。
appendChild
appendChild 把<script>标签直接塞进页面是可以执行和加载里面的 js 的,我们需要做的就只是把所有的<script>找出来,然后通过 appendChild 塞到页面里,需要注意的是script的加载和执行并非是同步的。为了流程的控制,在执行 js 的时候,可以使用 promise 来控制(Promise.reduce)
JQuery.html()
jQuery 会对代码进行正则判断,符合条件就会使用jQuery的append
// rnoInnerhtml 的值
rnoInnerhtml = /<script|<style|<link/i
// html()
html: function( value ) {
return access( this, function( value ) {
var elem = this[ 0 ] || {},
i = 0,
l = this.length;
if ( value === undefined && elem.nodeType === 1 ) {
return elem.innerHTML;
}
// See if we can take a shortcut and just use innerHTML
if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
value = jQuery.htmlPrefilter( value );
try {
for ( ; i < l; i++ ) {
elem = this[ i ] || {};
// Remove element nodes and prevent memory leaks
if ( elem.nodeType === 1 ) {
jQuery.cleanData( getAll( elem, false ) );
elem.innerHTML = value;
}
}
elem = 0;
// If using innerHTML throws an exception, use the fallback method
} catch ( e ) {}
}
if ( elem ) {
this.empty().append( value );
}
}, null, value, arguments.length );
}
createContextualFragment
该方法通过调用HTML片段解析算法或XML片段解析算法返回一个文档片段
let range = document.createRange();
// make the parent of the first div in the document becomes the context node
range.selectNode(document.body);
let documentFragment = range.createContextualFragment(innerHtml);
document.body.appendChild(documentFragment)
重新触发DOMContentLoaded
let DOMContentLoadedEvent = document.createEvent('Event');
DOMContentLoadedEvent.initEvent('DOMContentLoaded', true, true);
document.dispatchEvent(DOMContentLoadedEvent);