后端的html内容在vue中解析,基于Vue来解析页面在浏览器中呈现的过程中所涉及到的知识点...
发布日期:2021-06-24 14:06:09 浏览次数:2 分类:技术文章

本文共 4103 字,大约阅读时间需要 13 分钟。

前言

此篇文章是基于Vue来分析一下从编辑好代码->打包->将dist文件夹放置到服务器上->访问该网址->页面呈现。此过程所涉及到的知识点,本篇很少涉及到具体的代码,主要是理论上的知识,如有错误,烦请各位在评论区指出。

概念

Vue-cli(快速建立开发环境的脚手架)

webpack(模块打包工具)

Vue-loader(将单文件组件.vue解析成JS代码形式)

单页面应用与多页面应用(SPA与MPA)

浏览器进程(包括JS脚本执行、HTML/CSS的渲染)

JS、CSS的加载与阻塞

路由(封装好的Vue-Router)

动态加载JS脚本

在我们初学Vue的时候,多数人是在html文件中创建标签进行代码的编写,所有我们所需要的组件都在一个或多个scrpit标签下进行注册。但是在真实项目中,我们会编写成千上万行代码,如果都放在一个文件下,那样会导致可读性十分地差。所以Vue官方推出了Vue-cli(cli = Command-Line Interface = 命令行界面),通过在命令行窗口中输入某条命令,即可创建一个真实项目中所需要的元素(包括目录、主文件入口、根组件、开发/生产环境的默认配置...),这样我们只需要在对应目录编写代码,通过import/export引入对应模块,修改配置,再输入自带的命令,就可以生成一个页面,并且代码可读性十分强。

其实在Vue-cli中已经集成了webpack,我们可以通过配置webpack.xxx.conf.js文件,按照你的需求进行打包。而为什么我们需要webpack这个打包工具呢?是因为在项目中,我们需要有模块化的思想,将不同功能的模块分到不同的文件中,将一些公共资源如公共样式,背景图片等都提取出来。 关于webpack的原理、loader、plugin等在此处先不做解析(因为还不会...)。

.vue单文件组件中包含、、,而浏览器是无法解析.vue文件的,所以我们需要一种工具将其转换为浏览器可以解析的JS代码,这个就是Vue-loader的作用,具体的原理仍然不做解析(还没有读懂源码...)

单页面应用和多页面应用的区别:

单页面是指只有一个主页面的应用,一开始只需加载一次js、css等相关资源。所有的内容都包含在主页面,对每一个功能模块组件化。单页应用跳转,就是切换相关组件,仅刷新局部资源。

多页面是指有多个独立的页面的应用,每个页面必须重复加载js,、css等相关资源。多页应用跳转,需要整页资源刷新。

浏览器进程: 浏览器是多进程的、浏览器渲染进程是多线程的

那么浏览器包括哪几个进程呢?

Browser进程:浏览器的主进程,只有一个。

负责浏览器界面的显示,与用户交互。比如前进、后退等

负责各个页面的管理,创建、销毁其余进程

网络资源的下载与管理

将渲染进程内部的渲染树绘制到用户界面上

第三方插件进程:每种类型的插件对应一个进程,当使用该插件时才创建

GPU进程:进行3D CSS的渲染等

浏览器渲染进程(浏览器内核、Render进程,内部是多线程的):默认每个Tab页面都有一个,互不影响。功能:页面渲染、脚本执行、事件处理

那么浏览器渲染进程包括哪几个线程的呢?

GUI渲染线程:

负责渲染浏览器界面,解析HTML、CSS,构建DOM树和Render树,进行布局与绘制

当界面需要重绘时或者由于某种操作引发回流时,该线程就会执行

GUI渲染线程与JS引擎线程是互斥的(十分重要),当JS引擎执行时GUI渲染线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时被立刻执行

JS引擎线程

也称为JS内核,负责处理JavaScript脚本程序。(例如我们熟悉的V8引擎)

JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个Tab页(Renderer进程)中无论什么时候都只有一个JS线程在运行JS程序

GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。

事件触发线程

归属于浏览器而不是JS引擎,用来控制事件循环 (事件队列)

当JS引擎执行代码块如setTimeout时(也可以是来自浏览器内核的其他线程,如DOM事件、Ajax异步请求等),会将对应任务添加到事件触发线程中

当对应的事件符合触发条件时会被触发,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理

由于JS的单线程关系,所以这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)

定时触发器线程

setInterval与setTimeout所在线程

浏览器定时计数器并不是由JavaScript引擎计数的,(因为JavaScript引擎是单线程的,如果处于阻塞线程状态就会影响计时的准确)

因此通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待JS引擎空闲后执行)

W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。

异步http请求线程

在XMLHttpRequest连接后通过浏览器新开一个线程发送请求

检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中进行注册,再由JavaScript引擎执行。

1b889077b7ecc4ca8ce3cd4055f9117e.png

JS、CSS的加载与阻塞:其实这一部分就是我们上面所说的GUI渲染线程与JS引擎线程的互斥。由于JavaScript是可操纵DOM的,如果在修改这些元素属性同时渲染界面(即JS线程与GUI线程同时运行),那么渲染线程前后获得的元素就可能不一致了。接下来简单说一下浏览器渲染流程:

解析HTML建立DOM树

解析CSS与DOM树结合形成Render树

布局Render树(Layout/Reflow),负责各元素尺寸、位置的计算

绘制Render树(Paint),绘制页面像素信息

浏览器将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上

8baf9020f73262259d5925cf8c19d382.png

现在具体来说一下在代码中JS、CSS阻塞的应用:

首先先来明确几个概念:

CSS加载不会阻塞DOM树解析

CSS加载会阻塞Render树的渲染

CSS会阻塞JS执行

JS会阻塞DOM树解析

DOMContentLoaded事件

当初始的HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表、图像和子框架的完成加载。DOMContentLoaded事件必须等待其所属script之前的样式表加载解析完成才会触发

load事件

当onload事件触发时,页面上所有的DOM、样式表、脚本、图片都已经加载完成了

CSS是由单独的下载线程异步下载的

DOMContentLoaded事件只等待其所属的script之前的样式表

当解析起遇到script标签时,文档会立即停止解析直到脚本执行完毕,如果脚本是外部的,那么解析过程会停止,直到从网络同步抓取资源完成后再继续。因为我们的脚本会操作DOM,所以在脚本跑完之前浏览器不知道脚本会把DOM改成什么样,所以就等脚本执行完再解析DOM

async模式下,JS不会阻塞浏览器做其他事情,它的加载是异步的,当它加载结束后,JS脚本会立即执行。

defer模式下,JS加载是异步的,执行是被推迟的。等整个文档解析完成、DOMContentLoaded事件即将被触发时,被标记了defer的JS文件才会开始依次执行

从应用的角度来说,一般当我们的脚本与DOM元素和其它脚本之间的依赖关系不强时,我们会选用async;当脚本依赖于DOM元素和其它脚本的执行结果时,我们会选用defer。一句话,defer是"解析完DOM再执行",async是"下载完就执行"。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。

preload属性与prefetch属性:

preload(预加载):元素的rel属性的属性值preload能够让你在你的HTML页面中

元素内部书写一些声明式的资源获取请求,可以指明那些资源是在页面加载完成后即刻需要的。对于这种即刻需要的资源,你可能希望在页面加载的生命周期的早期阶段就开始获取,在浏览器的主渲染机制介入前就进行预加载。这一机制使得资源可以更早的得到加载并可用,且更不易阻塞页面的初步渲染,进而提升性能。

只是预加载,并不运行。

用下面两种方法即可加载完运行

预加载CSS

预加载js

prefetch(预获取):为了提示浏览器,用户未来的浏览有可能需要加载目标资源,所以浏览器有可能通过事先获取和缓存对应资源,优化用户体验。

路由(Vue-router):在我们的单页面应用中,切换页面是通过改变URL从而改变对应的组件来实现局部刷新,而这里的URL可以等同于路由。路由可以分为前端路由和后端路由,在这里说的是前端路由。前端路由的实现主要基于两种:

1、hash

2、history API

大家可以去看一下我的公众号:前端高级进阶,里面有详细的内容

最后就是动态加载JS了,因为单页面应用在页面初始化时会将所有组件的内容都以一个JS文件的形式进行加载,当文件过大时,会造成加载时间过长,首页白屏,用户体验差,所以呢,我们采用路由懒加载的技术,将不同路由对应的组件拆分成不同的JS文件,当我们访问对应路由时才去访问对应的JS文件,而这里就设计到动态加载JS了,其实这里webpack内部有一个插件已经帮我们实现了,当访问某路由时,会解析JS文件并且将对应的组件挂载到容器下。

结论

最后,再整体地回顾一下流程。

当运行npm run build命令时,会将所编写好的文件进行打包生成dist文件夹,里面包含着index.html、static-css、js、img、fonts文件夹,index.html就是我们访问的主页面,在

标签中通过引入css文件,在有一个
,这个就是我们的主容器,而在下面有各种

转载地址:https://blog.csdn.net/weixin_33308985/article/details/117872516 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:python注释改编码_Python变量、编码、注释
下一篇:android正则表达式网址简书,正则表达式使用场景

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月10日 00时35分59秒