在Livewire/Alpine.js更新DOM后,如何最优调用tippy()?
优化Livewire中Tippy的初始化方案
当前实现方式
我通过body标签的x-init完成Tippy的首次初始化:
<body x-data x-init="tippy('[data-tippy-content]')">
当Livewire动态添加/移除DOM元素时,需要重新调用tippy()来识别新元素。按照Livewire文档,我通过钩子监听元素初始化事件并分发自定义事件:
document.addEventListener("DOMContentLoaded", () => { Livewire.hook('component.initialized', (component) => {}) Livewire.hook('element.initialized', (el, component) => { el.dispatchEvent(new Event("livewire-element-initialized")); }) Livewire.hook('element.updating', (fromEl, toEl, component) => {}) Livewire.hook('element.updated', (el, component) => {}) Livewire.hook('element.removed', (el, component) => {}) Livewire.hook('message.sent', (message, component) => {}) Livewire.hook('message.failed', (message, component) => {}) Livewire.hook('message.received', (message, component) => {}) Livewire.hook('message.processed', (message, component) => {}) });
随后在body标签中监听自定义事件,触发Tippy初始化:
<body x-data x-on:livewire-element-initialized.window="tippy('[data-tippy-content]')">
存在的问题
该方案可正常运行,但效率偏低——每次DOM更新操作中,livewire-element-initialized事件会被多次触发,而我只需要在DOM更新完成后调用一次tippy()即可。
优化方案
方案1:利用message.processed钩子(推荐)
message.processed钩子会在Livewire完成所有消息处理、DOM更新完毕后全局触发一次,非常适合用来做全局的Tippy重新初始化:
document.addEventListener("DOMContentLoaded", () => { // 首次初始化Tippy tippy('[data-tippy-content]'); // 监听消息处理完成事件,确保DOM已更新完毕 Livewire.hook('message.processed', () => { // 先销毁现有Tippy实例,避免重复绑定导致的异常 tippy('[data-tippy-content]', { destroy: true }); // 重新初始化所有带tippy属性的元素 tippy('[data-tippy-content]'); }); });
此时body标签可以简化,不需要额外的x-init和事件监听:
<body x-data>
方案2:防抖处理重复触发
如果仍需保留基于元素初始化的逻辑,可以通过防抖函数限制tippy()的调用频率,确保短时间内只执行一次:
document.addEventListener("DOMContentLoaded", () => { let debounceTimer; // 封装防抖后的Tippy初始化函数 const initTippy = () => { clearTimeout(debounceTimer); debounceTimer = setTimeout(() => { tippy('[data-tippy-content]', { destroy: true }); tippy('[data-tippy-content]'); }, 100); // 可根据DOM更新速度调整延迟时间 }; // 首次初始化 initTippy(); // 监听元素初始化事件,触发防抖后的初始化 Livewire.hook('element.initialized', () => { initTippy(); }); });
内容的提问来源于stack exchange,提问作者Adam Lambert
相关产品推荐
相关产品推荐

