事件侦听器未从 HTML 导入中的 JS 脚本触发
Event Listener not firing from JS script within HTML Import
我正在使用以下函数将 form.html
导入 index.html
:
function importHTML() {
let link = document.createElement('link');
link.rel = 'import';
link.href = 'form.html';
link.onload = (e) => {
console.log('Successfully loaded import: ' + e.target.href);
importContent();
}
link.onerror = (e) => {
console.log('Error loading import: ' + e.target.href);
}
document.head.appendChild(link);
let importContent = () => {
let importContent = document.querySelector('link[rel="import"]').import;
if (importContent != null) {
let el = importContent.querySelector('#formContainer');
let container = document.body.querySelector('main');
container.appendChild(el.cloneNode(true));
}
}
}
这可以创建一个新的 link rel="import"
标签,并将其附加到 index.html
的 head
中。 link 完成加载后,form.html
的内容将附加到主体容器。
在 form.html
我有一个脚本,它获取分页元素的句柄以附加事件处理程序:
<section id="formContainer">
<form>
...
</form>
<!-- NOTE: pagination controls -->
<div class="pagination">
<span id="pageBack"><i><</i></span>
<span id="pageForward"><i>></i></span>
</div>
<script>
let importDoc = document.currentScript.ownerDocument;
let pageForward = importDoc.querySelector('#pageForward');
let pageBack = importDoc.querySelector('#pageBack');
// these elements are present in the console at runtime
console.log(pageForward, pageBack);
pageForward.addEventListener('click', (e) => {
console.log('click event heard on pageBack');
});
pageBack.addEventListener('click', (e) => {
console.log('click event heard on pageBack');
});
</script>
</section>
我遇到的问题是尽管控制台没有显示错误,但事件侦听器没有触发。
我认为这可能与 加载顺序 有关并对此进行了一些试验,确保在解析脚本之前加载导入,尽管我是不是 100% 确定这是否按预期工作。
我发现通过在 importContent()
函数之后动态加载它可以将我的执行脚本移动到主文档中,但我更愿意将表单的关联脚本封装在导入中。
想法?
事件侦听器附加到错误的元素。在您的示例中,它们是在导入文档中的 <span>
元素上设置的。
但是这些元素是被克隆的,被点击的 <span>
元素是没有设置事件监听器的克隆元素。
要使代码正常工作,您应该查询 <body>
中的元素,而不是查询导入的文档。
在form.html:
<script>
let importDoc = document.currentScript.ownerDocument
let el = importDoc.querySelector( '#formContainer' )
let container = document.body.querySelector( 'main ' )
container.appendChild( el.cloneNode( true ) )
let pageForward = container.querySelector( '#pageForward' )
let pageBack = container.querySelector( '#pageBack')
// these elements are present in the console at runtime
console.log(pageForward, pageBack);
pageForward.addEventListener('click', e =>
console.log( 'click event heard on pageBack' )
)
pageBack.addEventListener('click', e =>
console.log( 'click event heard on pageBack' )
)
</script>
注意:导入文档中的 会在导入文档后立即执行。无需等待 onload
事件并从主文档调用回调。
如果您想推迟脚本的执行,您需要将其放在 <template>
元素中。
我正在使用以下函数将 form.html
导入 index.html
:
function importHTML() {
let link = document.createElement('link');
link.rel = 'import';
link.href = 'form.html';
link.onload = (e) => {
console.log('Successfully loaded import: ' + e.target.href);
importContent();
}
link.onerror = (e) => {
console.log('Error loading import: ' + e.target.href);
}
document.head.appendChild(link);
let importContent = () => {
let importContent = document.querySelector('link[rel="import"]').import;
if (importContent != null) {
let el = importContent.querySelector('#formContainer');
let container = document.body.querySelector('main');
container.appendChild(el.cloneNode(true));
}
}
}
这可以创建一个新的 link rel="import"
标签,并将其附加到 index.html
的 head
中。 link 完成加载后,form.html
的内容将附加到主体容器。
在 form.html
我有一个脚本,它获取分页元素的句柄以附加事件处理程序:
<section id="formContainer">
<form>
...
</form>
<!-- NOTE: pagination controls -->
<div class="pagination">
<span id="pageBack"><i><</i></span>
<span id="pageForward"><i>></i></span>
</div>
<script>
let importDoc = document.currentScript.ownerDocument;
let pageForward = importDoc.querySelector('#pageForward');
let pageBack = importDoc.querySelector('#pageBack');
// these elements are present in the console at runtime
console.log(pageForward, pageBack);
pageForward.addEventListener('click', (e) => {
console.log('click event heard on pageBack');
});
pageBack.addEventListener('click', (e) => {
console.log('click event heard on pageBack');
});
</script>
</section>
我遇到的问题是尽管控制台没有显示错误,但事件侦听器没有触发。
我认为这可能与 加载顺序 有关并对此进行了一些试验,确保在解析脚本之前加载导入,尽管我是不是 100% 确定这是否按预期工作。
我发现通过在 importContent()
函数之后动态加载它可以将我的执行脚本移动到主文档中,但我更愿意将表单的关联脚本封装在导入中。
想法?
事件侦听器附加到错误的元素。在您的示例中,它们是在导入文档中的 <span>
元素上设置的。
但是这些元素是被克隆的,被点击的 <span>
元素是没有设置事件监听器的克隆元素。
要使代码正常工作,您应该查询 <body>
中的元素,而不是查询导入的文档。
在form.html:
<script>
let importDoc = document.currentScript.ownerDocument
let el = importDoc.querySelector( '#formContainer' )
let container = document.body.querySelector( 'main ' )
container.appendChild( el.cloneNode( true ) )
let pageForward = container.querySelector( '#pageForward' )
let pageBack = container.querySelector( '#pageBack')
// these elements are present in the console at runtime
console.log(pageForward, pageBack);
pageForward.addEventListener('click', e =>
console.log( 'click event heard on pageBack' )
)
pageBack.addEventListener('click', e =>
console.log( 'click event heard on pageBack' )
)
</script>
注意:导入文档中的 会在导入文档后立即执行。无需等待 onload
事件并从主文档调用回调。
如果您想推迟脚本的执行,您需要将其放在 <template>
元素中。