04.输出流/InputStream

一套webkit的讲解教程,旨在快速打通渲染流程,讲解可在同名b/dy中找到

为什么要使用输出流的方式而非特殊的字符串封装? document.write是什么? 为什么要用流? .....

实际上,输出流就是字符串更多功能的封装,比如他有多个修改的入口【同时支持document.write和网络层的数据】,实现上由两段字符串/指针组成,网络层数据入总体的字符串队尾,document.write的数据入临时的字符串【"队首"】

因为在此之前,字节已经过了编码,这里的输出流,更类似于字符流而非字节流

注:为什么要用流,会涉及一点多线程的内容,一个线程读,一个线程写,要么全读完再写,要么读操作的地方使用监听,使用中间层输出流可以解决以上类似的问题

api

dom.spec.whatwg.org/#document.w...

document.open

打开一个新文档,即打开一个新的输出流,并擦除当前文档的内容

document.write

在document被加载完后调用docuemnt.write方法时将会自动去触发document.open()。在载人页面后,浏览器输出流自动关闭;在此之后,任何一个对当前页面进行操作的document.write()方法将打开---个新的输出流。它将清除当前页面内容(包括源文档的任何变量或值)

但是,在那之前,document.write都是将数据直接插入到流中

document.close

关闭输出流,在加载完页面后,自动close

涉及到文档关闭,这里就有一个时间点,这个时间点是DCL

例子

demo - parse/1.hml

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div>1
        <script>
            document.write("</div>--<div>")
        </script>
        23
    </div>
</body>
</html>

它可以添加任意词组进入输出流 考虑到输出流的来源可以基于网络或js,那有没有可能,输出流完全由js控制的?

iframe-deom - parse/2.html

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div>
        1
    </div>
    <script>
        const ifr = document.createElement("iframe");
        document.body.appendChild(ifr);
        const ifrdoc = ifr.contentWindow.document;
        // 开新的输出流
        ifrdoc.open();
        ifrdoc.write("<div>iframe</div>");
        ifrdoc.write("<div>123</div>");
        // 结束,开始渲染,如果没有加载结束后,自动关闭
        ifrdoc.close();
    </script>
</body>
</html>

注1:考虑下iframe/frame,可以手动添加额外的节点,当然,也是很老的策略

注2:frame属于废弃的标签,但内部还是有这个概念【框】

注3:ifrdoc.close涉及到的时间点L 【可调整】

解析 - parse/3.html

因为创建词组属于parseHtml, 那是不是包含了script的页面,parseHtml就会执行两次?

我写多次document.write时,会不会触发多次解析?或者说重绘/重排?

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div>1
        <script>
            document.write("</div>--<div>")
            document.write("</div>--<div>")
            document.write("</div>--<div>")
        </script>
        23
    </div>
</body>
</html>
  1. 输出流里的内容处理完之前,是不会进行到下一个阶段的
  2. 下一个阶段才是排版,渲染
  3. 当然,要是强制中断【debugger】,肯定会生成dom或layout【强制提交缓存】

DCL

DOMContentLoaded事件,当 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,无需等待样式表、图像和子框架的完成加载。此后document.write将进入新的解析流中

DOMContentLoaded-parse/4.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        document.write("123")
        document.addEventListener('DOMContentLoaded', function() {
            console.log('DOMContentLoaded')
            document.write("456")
        })
        document.write("789")
    </script>
</head>
<body>
    
</body>
</html>

在DOMContentLoaded加载前与加载后,调用document.write产生的效果是不一样的,在文档加载结束前调用,属于加入输入流,但在加载后,属于创建输入流

考虑到DCL,你会发现这种描述方式并不受控【受网络影响,当然,肯定已经解决了】

document.write的二义性 - parse/5.html

比如以下场景,当我在若网络环境下,使用setTimeout,是否会出现二义性?

比如网速比较快,DOMContentLoaded加载完了,所有创建输入流

但网速比较慢,DOMContentLoaded没加载完,所有加入输入流

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

</head>
<div>
    <script>
        document.write("123")
        setTimeout(()=>{
            document.write("456")
        })
    </script>
    <div>很多占位耗时的内容</div>    
</div>
<body>
    
</body>
</html>

延迟脚本的write会立刻打开一个新的输出流,防止二义性

相关推荐
福兮说2 小时前
前端下载大文件,点了按钮半天没反应:fetch + blob 的三个问题和三种替代写法
前端·javascript·性能优化·文件下载
GreenTea2 小时前
我把 Agent 的 while 循环拆掉了:一种你可能没想到的 Agent 架构
前端·后端·架构
科技观察哨2 小时前
六足平台选型与纳米定位系统集成:HEB-640六自由度位移台在半导体光刻对准中的参数边界与国产替代评估
前端·人工智能
niucloud-admin2 小时前
JAVA V6 多商户商城 开发文档——web前端
前端
颜进强3 小时前
16 · NestJS LifecycleEvents 生命周期事件:五个钩子、三条边界,和 rag-server 的优雅停机
前端·后端·ai编程
今年下半年4 小时前
【VUE】整合腾讯地图、自定义区域边界、村委名称及资产统计(放大显示资产点位)
前端·javascript·vue.js
郑州光合科技余经理4 小时前
同城电商系统:库存变更怎么同步到订单
java·开发语言·前端·后端·uni-app·php·ai编程
前端snow6 小时前
ai agent --- DeepAgents 中间件
前端
data analyse 4567 小时前
报表能自定义的国内统计工具有哪些
前端·数据分析