vue2首次加载屏幕闪烁问题
作者:程琬清君
vue2首次加载屏幕闪烁
先看我的bug动图:
我想要的动图:
可能图片不明显 反正就是只要这个正在加载资源这个页面
1.了解vue项目执行流程
vue项目中影响组件渲染和挂载有这几个文件:index.html、main.js、App.vue、路由配置,那么它们之间的关系是如何呢?
答:
- 1.index.html是项目入口
- 2.main.js是入口文件(值得关注的是main.js的render函数,下面会详细的讲)
- 3.App.vue根组件
- 4.路由配置(作用是:将路由名字和组件映射并渲染到App.vue)
执行顺序:index.html、main.js、App.vue、路由配置index.js、具体vue组件
index.html
①想要项目打包体积小,我们经常将第三方库的cdn写在index.html,比如(需要先将cdn下载到项目里):
<head> <link rel="stylesheet" href="<%= BASE_URL %>cdn/element-ui/2.15.12/theme-chalk/index.css" rel="external nofollow" > </head>
有人可能会问BASE_URL是什么?答:这个BASE_URL是根据vue.config.js的publicPath去设置的路径,这个路径决定了我们的前端项目打包后获取静态资源的默认的根路径。
- ②body标签里的<noscript></noscript>里写如果没有js支持时,将写的的代码。
- ③重点!!body标签里的<div id="app"></div>里面写的是:当vue实例还没有完成挂载时,vue项目将显示什么内容。
列取一段代码:
<body> <div id="app"> <div class="avue-home"> <div class="avue-home__main"> <img class="avue-home__loading" src="<%= BASE_URL %>svg/loading-spin.svg" alt="loading"> <div class="avue-home__title"> 正在加载资源 </div> <div class="avue-home__sub-title d"> 初次加载资源可能需要较多时间 请耐心等待 </div> </div> </div> </div> </body>
- ④那跟<div id="app"><div>同级的标签还会显示吗?答:会!因为在vue实例还没有挂载时,会运行index.html整个文件。
- ⑤js也就是<script>标签最好写在</body>之上,比如:
简写代码:
<body> <div id="app"> </div> <script src="<%= BASE_URL %>cdn/xlsx/xlsx.full.min.js"></script> </body>
main.js
- ①我们最应该也重点注意到这段代码:
var vue = new Vue({ router, render: h => h(App), beforeCreate() { } // 一般不写生命周期,这里我只是列出来告诉你们--->这里是vue实例,所以什么生命周期,data统统可以写 }).$mount('#app')
1.render是重点:请务必注意它必须要有返回值。为什么是render?
答:请看这2句代码
import Vue from 'vue'; import App from './App';
(1)vue.js才是完整版的vue,包含了:核心功能 + 模板解析器,它在
(2)vue.runtime.xxx.js是运行版的vue,只包含了:核心功能,没有模板解析器。
完整的vue你可以看node_modules下的vue文件,如下图
因为我们项目里用的是残缺的vue.js,是一个不会解析template标签的vue.js,引用render是为了减少打包的文件大小、使打包文件不会出现没有用处的模板解析器。
2.项目中出现白屏闪烁的原因以及解决方式
原因:可以根据上面的vue项目执行的流程可得,vue实例中的组件的模板内容(即app.vue)取代了index.html的<div id="app"></div>里的内容,在这个瞬间出现的白屏闪烁。
我看了网上很多人说v-cloak但我试了没用,以下是我的处理方式,效果是达到了,可能还不够很好,如果有大佬有更好的办法请在此条文章下评论大家一起探讨。
1.我原本的代码:
index.html <div id="app"> <div class="avue-home"> <div class="avue-home__main"> <img class="avue-home__loading" src="<%= BASE_URL %>svg/loading-spin.svg" alt="loading"> <div class="avue-home__title"> 正在加载资源 </div> <div class="avue-home__sub-title d"> 初次加载资源可能需要较多时间 请耐心等待 </div> </div> </div> </div>
2.我修改后的代码
index.html文件里(你没看错,我将我要展示的内容写到了<div id="app">同级的地方):
<div id="app"> </div> <div class="avue-home"> <div class="avue-home__main"> <img class="avue-home__loading" src="<%= BASE_URL %>svg/loading-spin.svg" alt="loading"> <div class="avue-home__title"> 正在加载资源 </div> <div class="avue-home__sub-title d"> 初次加载资源可能需要较多时间 请耐心等待 </div> </div> </div>
并在index.html文件里写上avue-home的样式,我的样式是(供参考):
.avue-home { background-color: #303133; height: 100vh; width: 100%; display: flex; flex-direction: column; position: fixed; top: 0; left: 0; z-index: 999; }
接下来是重点了:
我们都知道最后是app.vue的代码替换了<div id='app'>,所以在app.vue文件里写:
- app.vue
mounted () { // 当app.vue挂载完毕时,让浏览器延迟1s自动删除class为.avue-home的这个节点(有点绕,但可以好好想想) const avueHome = document.querySelector('.avue-home') // 获取到这个class的节点 setTimeout(() => { avueHome.parentNode.removeChild(avueHome) // 该节点的父级去删除这个class }, 1000) },
希望大家细品这两句代码。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。