If块内绑定元素无法引用:Google API加载延迟引发的问题
问题描述
我写了一个判断用户是否通过Google登录的{#if}块,但因为Google API加载需要时间,导致目标元素还没渲染完成,就算用bind:this也没法引用到这个元素(testBtn)。代码如下:
let testBtn; onMount(()=>{ [...] console.log(testBtn) // 这里打印undefined,元素还没渲染 }) [...] {#if userLogged === false} <button class="text-lg text-black bg-white px-5 py-2 border-2 border-white rounded-2xl hover:bg-transparent hover:text-white transition-all duration-200" on:click={login}>Login with Google</button> {:else if userLogged === true} <div class="flex items-center"> <h3 class="text-lg mr-5">Olá {username}</h3> <div class="relative group"> [...] <button class="rounded-md p-2 bg-slate-100 hover:bg-slate-200 text-black my-2 btnAddCampaing" id="btnAddCampaing" bind:this={testBtn}>Criar uma campanha</button> <button class="rounded-md p-2 bg-slate-100 hover:bg-slate-200 text-black my-2" on:click={()=>signOut(auth).then(()=>{})}>Sair</button> </div> </div> </div> {/if}
解决方法
1. 用反应式语句监听登录状态变化
userLogged是控制元素渲染的核心变量,当它从false切换到true后,目标按钮才会被渲染。用Svelte的$:反应式语法监听这个变量,就能在元素渲染完成后立刻拿到引用:
let testBtn; let userLogged = false; // 当userLogged变为true时触发 $: if (userLogged) { console.log(testBtn); // 这里能正常拿到元素 // 执行你需要的元素操作,比如绑定事件、修改属性 }
2. 登录成功后等待DOM更新
如果你的login函数是异步调用Google API,那在登录成功、更新userLogged后,用svelte提供的tick()方法等待DOM渲染完成,再访问元素:
import { tick } from 'svelte'; async function login() { // 调用Google登录接口 await signInWithGoogle(auth); // 更新登录状态 userLogged = true; // 等待Svelte完成DOM更新 await tick(); // 现在可以安全访问testBtn console.log(testBtn); }
3. 给元素绑定自身挂载事件
直接在目标按钮上添加on:mount事件,元素挂载到DOM的瞬间就会触发回调,完全不用担心时机问题:
<button class="rounded-md p-2 bg-slate-100 hover:bg-slate-200 text-black my-2 btnAddCampaing" id="btnAddCampaing" bind:this={testBtn} on:mount={() => { console.log(testBtn); // 元素已存在,直接操作 }} > Criar uma campanha </button>
4. 定时器兜底(应急用)
如果以上方法都不适用,可以用定时器轮询检查元素是否存在,不过这种方法不够可靠,仅作为应急方案:
onMount(()=>{ const checkTimer = setInterval(() => { if (testBtn) { console.log(testBtn); clearInterval(checkTimer); // 执行操作 } }, 100); })
内容的提问来源于stack exchange,提问作者Vinicius Antonio
相关产品推荐
相关产品推荐

