调用Firebase登录时首次出现[Vue warn]: Cannot find element: #app的原因
问题原因分析
核心触发逻辑
你遇到的警告本质是重复触发Vue实例挂载,且第二次挂载时DOM中已不存在#app元素,完整触发流程如下:
- 首次打开页面时,Firebase Auth初始状态为未登录,
onAuthStateChanged第一次触发,正常创建Vue实例挂载到index.html中原生的<div id="app"></div>元素上。Vue的挂载逻辑会把目标元素整个替换为根组件渲染的内容,只要你的App.vue根节点没有手动加id="app"属性,挂载完成后DOM里就不存在id="app"的元素了。 - 点击登录按钮触发
signIn方法,登录成功后Firebase Auth状态从「未登录」切换为「已登录」,onAuthStateChanged会第二次触发,又尝试新建Vue实例挂载到#app上,但此时DOM里已经没有这个元素,就抛出了找不到元素的警告。 - 刷新页面后警告消失的原因是:刷新后Firebase Auth初始状态就是已登录,
onAuthStateChanged只会触发一次,此时DOM里还有原生的#app元素,一次挂载成功不会触发重复挂载逻辑,因此没有警告。
注:
alert是同步阻塞API,不会影响该警告的触发,只是你感知上会觉得弹出alert之后才出警告,实际是登录成功状态变更同步触发了onAuthStateChanged回调。
修复方案
给onAuthStateChanged加挂载判断,避免重复创建Vue实例即可,修改main.js代码:
import Vue from "vue"; import App from "./App.vue"; import router from "./router"; import store from "./store"; import Vue2Editor from "vue2-editor"; import firebase from 'firebase/app'; import "firebase/auth" Vue.use(Vue2Editor); Vue.config.productionTip = false; // 定义变量存储Vue实例,避免重复挂载 let vueApp = null firebase.auth().onAuthStateChanged(()=>{ if(!vueApp){ vueApp = new Vue({ router, store, render: (h) => h(App), }).$mount("#app"); } })
如果你的业务需要在登录状态切换时做其他逻辑,可以单独处理,不要重复挂载Vue实例。也可以选择在App.vue的根元素上添加id="app"属性,这样即使重复挂载也能找到元素,但更推荐第一种方案,避免不必要的性能损耗。
内容的提问来源于stack exchange,提问作者Prasanga Thapaliya
相关产品推荐
相关产品推荐

