使用 Webpack4.0 打包组件库并发布到 npm

本文将会介绍如何将自己写的组件库打包成第三方库,发布到 npm 上,同时支持在原生 js / React/ Vue 下使用。Webpack4 的升级指南可以参考下 Webpack4.0 升级配置,本文不做赘述。

Webpack4.0 升级配置

本文基于 webpack 4.8.1

吐槽

webpack 彪版本号的速度真是飞快,4.0 发布没多久上去看的时候才 4.1.*,现在已经刷到 4.8.1 了,给人一种“我版本号很高了,可以安心升级了”的感觉,然而坑依然很多…尤其是 API 文档,到处可见 3.0 的陈旧信息。Code Splitting 章节点进去依然在讲 CommonsChunkPlugin ,CommonsChunkPlugin 点进去提示去看 SplitChunksPlugin,看文档的时候经常会迷失自我,心累…好了,吐槽完毕,下面是正文。需要直接复制粘贴的同学直接拉到最后~

前端基础拾遗之CSS篇

  1. 盒子模型
    CSS 中的每个元素都被表示为一个矩形的盒子,每个盒子有四个边:content edge, padding edge, border edge, and margin edge。
    box-sizing: content-box(默认),border-box ,padding-box(deprecated)。
    content-box 下盒子实际宽度不等于 width,不包括 padding 和 border 部分,布局计算不方便。border-box 下盒子实际宽度与 width 相等。

  2. 外边距合并(Margin collapsing)
    块级元素的上外边距和下外边距有时会合并(或折叠)为一个外边距,其大小取其中的最大者,这种行为称为外边距折叠(margin collapsing),有时也翻译为外边距合并。
    浮动元素和绝对定位元素的外边距不会折叠。

    上外边距和下外边距在没有 content、padding、border 间隔的情况下相遇,就会发生外边距合并,为其中一个元素添加 content、padding、border 使得上下外边距分离,即可取消叠加。

    可能发生外边距合并的三种基本情况:
    相邻元素之间、父元素与其第一个或最后一个子元素之间、空的块级元素。

    注意:

    • 上述情况的组合会产生更复杂的外边距折叠。
    • 即使某一外边距为 0,这些规则仍然适用。因此就算父元素的外边距是 0,第一个或最后一个子元素的外边距仍然会“溢出”到父元素的外面,并且使父元素产生边距效果。
    • 如果参与折叠的外边距中包含负值,折叠后的外边距的值为最大的正边距与最小的负边距(即绝对值最大的负边距)的和。
    • 如果所有参与折叠的外边距都为负,折叠后的外边距的值为最小的负边距的值。这一规则适用于相邻元素和嵌套元素。
  3. 浮动 float
    将一个元素放置在 container 的左侧或右侧,允许 text 和 inline 元素环绕它。float 使用块布局,在某些情况下会修改 display 的计算值,inline -> block, inline-block -> block, inline-table -> table, table-cell -> block。对 flex/inline-flex 无效。举个 🌰 float

  4. 清除浮动
    清除浮动是为了清除使用浮动元素产生的影响。浮动的元素,高度会塌陷,而高度的塌陷使我们页面后面的布局不能正常显示。

    clear

    • left: 元素被向下移动用于清除之前的左浮动。
    • right: 元素被向下移动用于清除之前的右浮动。
    • both: 元素被向下移动用于清除之前的左右浮动。

    举个 🌰 clearfixmulti-float-clearfix

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    .container {
    width: 400px;
    background-color: green;
    margin: 10px;
    }

    .float {
    float: right;
    width: 200px;
    height: 100px;
    background-color: red;
    }

    .container1 {
    /* overflow: hidden 亦可,各有优缺点 */
    overflow: auto;
    }

    .container2::after {
    content: "";
    display: block;
    clear: both;
    }

    .container3::after {
    content: "";
    display: table;
    clear: both;
    }

    .container4 {
    /* 类似 hardcode */
    height: 100px;
    }

    .container5::before,
    .container5::after {
    content: "";
    display: table;
    }
    .container5::after {
    clear: both;
    }
    .container5 {
    zoom: 1;
    }

    .container6 {
    /* 父元素浮动也可清除浮动,有副作用 */
    float: right;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <div class="container container1">
    <div class="float"></div>
    </div>
    <div class="container container2">
    <div class="float"></div>
    </div>
    <div class="container container3">
    <div class="float"></div>
    </div>
    <div class="container container4">
    <div class="float"></div>
    </div>
    <div class="container container5">
    <div class="float"></div>
    </div>
    <div class="container container6">
    <div class="float"></div>
    </div>
  5. 块格式化上下文(Block Formatting Context,BFC)
    浮动元素和绝对定位元素,非块级盒子的块级容器(例如,inline-block、table-cells 和 table-captions),以及 overflow 值不为 visiable 的块级盒子,都会为他们的内容创建新的 BFC(块级格式上下文)。

    在 BFC 中,盒子从顶端开始垂直地一个接一个地排列,两个盒子之间的垂直的间隙是由他们的 margin 值所决定的。在一个 BFC 中,两个相邻的块级盒子的垂直外边距会产生折叠。

    在 BFC 中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)。对于从右到左的格式来说,则触碰到右边缘。

    BFC 中的元素的布局是不受外界的影响(我们往往利用这个特性来消除浮动元素对其非浮动的兄弟元素和其子元素带来的影响。)并且在一个 BFC 中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列。

  6. 动画实现
    css 实现动画与 js 不同,css 是定义关键帧,js 则是定义渲染页面与运行时间差的关系。

    • css 实现 demo
    • setTimeout 实现 demo
    • requestAnimationFrame 实现 demo
  7. 选择器
    选择器的特殊性分成 4 个权重等级:

    • 行内样式 +1000
    • id 选择器 +100
    • 类、伪类、属性选择器 +10
    • 类型、伪元素选择器 +1
  8. 居中

    1
    2
    3
    4
    5
    6
    // flex 算是最优解,指哪打哪,特别方便
    .container {
    display: flex;
    justify-content: center;
    align-items: center;
    }
    1
    2
    3
    4
    5
    6
    // block 元素 margin
    .block-ele {
    display: block;
    margin-left: auto;
    margin-right: auto;
    }
    1
    2
    3
    4
    // inline 元素 text-align
    .inline-ele {
    text-algin: center;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 知道宽高的情况下
    .container {
    position: relative;
    }

    .child {
    box-sizing: border-box;
    position: absolute;
    height: 50px;
    width: 100px;
    top: 50%;
    left: 50%;
    margin-top: -25px;
    margin-left: -50px;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 不知道宽高的情况下
    .container {
    position: relative;
    }

    .child {
    box-sizing: border-box;
    position: absolute;
    height: 60%;
    width: 50%;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    }
  9. css 单位

    • rem
      html 元素的 font-size * 当前元素的 rem = 当前元素的 px,响应式布局利器
    • em
      根据自身的 font-size * 当前元素的 em = 当前元素的 px,按钮根据文字的大小设置对应比例的 padding 比较好用
    • vh
      1/100 的视口高度,满屏布局的时候比较好用
    • vw
      1/100 的视口高度
    • vmin / vmax
      vh 和 vw 依据于视口的高度和宽度,相对的,vmin 和 vmax 则关于视口高度和宽度两者的最小或者最大值。
    • ex
      小写 x 的高度
    • ch
      和数字 0 的宽度
  10. 响应式布局
    基于媒体查询和 rem 的响应式布局实践

  11. flex
    a-guide-to-flexbox

  12. grid
    complete-guide-grid

  13. meta

  14. 浏览器引擎前缀

    1. CSS 前缀 Edit
      主流浏览器引擎前缀:
      -webkit- (谷歌, Safari, 新版 Opera 浏览器等)
      -moz- (火狐浏览器)
      -o- (旧版 Opera 浏览器等)
      -ms- (IE 浏览器 和 Edge 浏览器)
    2. API 接口前缀
      WebKit (谷歌, Safari, 新版 Opera 浏览器等)
      Moz (火狐浏览器)
      O (旧版 Opera 浏览器等)
      MS (IE 浏览器 和 Edge 浏览器)
    3. API 属性和方法前缀
      webkit (谷歌, Safari, 新版 Opera 浏览器等)
      moz (火狐浏览器)
      o (旧版 Opera 浏览器等)
      ms (IE 浏览器 和 Edge 浏览器)
  15. 页面导入样式时,使用 <link>@import 有什么区别?
    @import 是 CSS 加载样式的方式, <link> 是 HTML 加载样式的方式。页面被加载的时,<link> 会同时被加载,而 @import 引用的 CSS 会等到页面被加载完再加载。

  16. tips 碰撞检测

  17. 圣杯布局

    float 实现真是被 Flex 爆的体无完肤,flex 实现 css 语义清晰,float 满满的黑科技糅杂在一起。

  18. MouseEvent offsetX/Y, pageX/Y, clientX/Y, screenX/Y
    mouse

  19. display

  20. position

前端基础拾遗之javascript篇

  1. 基本类型

  2. 继承实现

  3. macrotask 和 microtask
    事件循环每次只会入栈一个 macrotask ,主线程执行完该任务后又会先检查 microtasks 队列并完成里面的所有任务后再执行 macrotask。
    macrotasks: setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering
    microtasks: process.nextTick, Promises, Object.observe, MutationObserver
    https://juejin.im/entry/58d4df3b5c497d0057eb99ff
    https://stackoverflow.com/questions/25915634/difference-between-microtask-and-macrotask-within-an-event-loop-context#

  4. Event Loop
    浏览器侧

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    requestAnimationFrame(() => {
    console.log(4);
    });
    new Promise((resolve, reject) => {
    console.log(1);
    resolve();
    })
    .then(() => {
    console.log(2);
    throw new Error("err");
    })
    .catch(() => {
    console.log(3);
    });
    setTimeout(() => {
    console.log(5);
    }, 0);
    requestIdleCallback(() => {
    console.log(6);
    });

    服务端侧,setImmediate 和 setTimeout 触发先后不固定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    new Promise((resolve, reject) => {
    console.log(1);
    resolve();
    })
    .then(() => {
    console.log(3);
    throw new Error("err");
    })
    .catch(() => {
    console.log(4);
    });
    setImmediate(() => {
    console.log(5);
    });
    setTimeout(() => {
    console.log(6);
    }, 0);
    process.nextTick(() => {
    console.log(2);
    });
  5. 原型
    Function.prototypeFunction.__proto__都指向Function.prototype,这就是鸡和蛋的问题怎么出现的。
    Object.prototype.__proto__ === null,说明原型链到Object.prototype终止。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function F() {}
    let f = new F();
    console.log(f.__proto__ === F.prototype);
    console.log(F.prototype.constructor === F);
    console.log(f.constructor === F);

    console.log(F.__proto__ === Function.prototype);
    console.log(Function.prototype.constructor === Function);
    console.log(F.constructor === Function);

    console.log(Function.__proto__ === Function.prototype);
    console.log(Function.prototype.constructor === Function);

    console.log(f.prototype === undefined);
    console.log(F.prototype.__proto__ === Object.prototype);
    console.log(Function.prototype.__proto__ === Object.prototype);
    console.log(Object.prototype.__proto__ === null);
  6. 依赖

  7. 数组的方法

    • slice
      slice() 方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象。且原始数组不会被修改。
    1
    2
    3
    4
    5
    6
    7
    8
    arr.slice();
    // [0, end]

    arr.slice(begin);
    // [begin, end]

    arr.slice(begin, end);
    // [begin, end)
    • shift
      shift() 方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
  8. 不同 TAB 页下通讯

    • BroadcastChannel,Chrome54、Firefox38 Support

      1
      2
      3
      4
      5
      6
      7
      8
      9
      // tab1
      const channel = new BroadcastChannel("channel-name");
      channel.onmessage = function(e) {
      console.log(e);
      };

      // tab2
      const channel = new BroadcastChannel("channel-name");
      channel.postMessage("some message");
    • Shared Workers,Chrome、Firefox29 Support

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      // work.js
      const connections = [];
      onconnect = function(e) {
      const port = e.ports[0];
      connections.push(port);
      port.onmessage = function(e) {
      connections.forEach(function(connection) {
      if (connection !== port) {
      connection.postMessage(e.data);
      }
      });
      };
      };

      // tab1
      const worker = new SharedWorker("worker.js");
      worker.port.onmessage = function(e) {
      console.log(e.data);
      };

      // tab2
      const worker = new SharedWorker("worker.js");
      worker.port.postMessage("hello tab1");
    • localStorage

      1
      2
      3
      4
      5
      6
      7
      // tab1
      window.onstorage = function(e) {
      console.log(e);
      };

      // tab2
      localStorage.setItem("key", "value");
    • window.opener

前端基础拾遗之HTML篇

  1. DOCTYPE 作用
    DTD(文档类型定义)是一组机器可读的规则,他定义 XML 或 HTML 的特定版本中允许有什么,不允许有什么。而 DOCTYPE 是用来描述使用哪个 DTD,保证网页以标准模式渲染,一个不含任何 DOCTYPE 的网页将会以 怪异(quirks) 模式渲染。HTML5 之前的 HTML 基于 SGML(Standard Generalized Markup Language, 标准通用标记语言)标准,需要 DTD 来保证在标准模式下渲染。HTML5 只需要 DOCTYPE 就可以保证在标准模式下渲染。

  2. 浏览器解析 HTML 方式
    标准模式、怪异模式和部分怪异(近乎标准)模式。在标准模式中,浏览器根据规范显示页面;在混杂模式中,页面以一种比较宽松的向后兼容的方式显示。那些基于 Mozilla 的 Gecko 渲染引擎的,或者 Internet Explorer 8 在 strict mode 下,除了在处理表格的方式上有细微差异外,与标准模式相同。

  3. 行内元素与块级元素对比
    内容上,
    一般情况下,行内元素只能包含数据和其他行内元素。而块级元素可以包含行内元素和其他块级元素。这种结构上的包含继承区别可以使块级元素创建比行内元素更”大型“的结构。
    格式上,
    默认情况下,行内元素不会以新行开始,而块级元素会新起一行。

  4. 行内元素列表
    一个行内元素只占据它对应标签的边框所包含的空间。
    b, big, i, small, tt
    abbr, acronym, cite, code, dfn, em, kbd, strong, samp, var
    a, bdo, br, img, map, object, q, script, span, sub, sup
    button, input, label, select, textarea

  5. 块级元素列表
    块级元素占据其父元素(容器)的整个空间,因此创建了一个“块”。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <address> 联系方式信息
    <article> HTML5 文章内容
    <aside> HTML5 伴随内容
    <audio> HTML5 音频播放
    <blockquote> 块引用
    <canvas> HTML5 绘制图形
    <dd> 定义列表中定义条目描述
    <div> 文档分区
    <dl> 定义列表
    <fieldset> 表单元素分组
    <figcaption> HTML5 图文信息组标题
    <figure> HTML5 图文信息组
    <footer> HTML5 区段尾或页尾
    <form> 表单
    <h1> , <h2> , <h3> , <h4> , <h5> , <h6> 标题级别 1-6.
    <header> HTML5 区段头或页头
    <hgroup> HTML5 标题组
    <hr> 水平分割线
    <noscript> 不支持脚本或禁用脚本时显示的内容
    <ol> 有序列表
    <output> HTML5 表单输出
    <p> 行
    <pre> 预格式化文本
    <section> HTML5 一个页面区段
    <table> 表格
    <tfoot> 表脚注
    <ul> 无序列表
    <video> HTML5 视频
  6. 常见的浏览器内核有哪些?
    Trident:主要有 IE 浏览器以及多核浏览器
    Gecko:主要有 Firefox 以及 Firefox 的衍生浏览器
    WebKit:主要有 Chrome 与 Chrome 的衍生浏览器、Safari 以及多核浏览器
    Presto:之前主要应用于 Opera,不过现在的 Opera 使用 WebKit 内核
    EdgeHTML:Microsoft Edge,Trident 的一个分支,移除所有旧版 Internet Explorer 遗留下来的代码,并重写主要的代码以和其他现代浏览器的设计精神互通有无

  7. HTML 语义化
    在程序中, 语义指的是一段代码的含义 — 例如 “这个 HTML 的元素有什么作用,扮演了什么样的角色”。
    对开发人员及团队,有利于增加代码可读性,减少差异化;
    对搜索引擎,有助于爬虫抓取更多的有效信息,有利于确定上下文和各个关键字的权重,利于 SEO;
    对浏览器,即使在 CSS 加载异常的情况下,也能提供一个基础的默认文档样式,方便屏幕阅读器以更有意义的方式渲染。

  8. 渲染原理
    webkit.png

    1. 浏览器会将 HTML 解析成一个 DOM TreeDOM Tree的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点。
    2. 将 CSS 解析成 CSS Rule Tree
    3. 根据 DOM TreeCSS Rule Tree 来构造 Rendering Tree。注意:Rendering Tree 渲染树并不等同于 DOM 树,因为一些像 Header 或 display:none 的东西就没必要放在渲染树中了。
    4. 有了 Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的 CSS 定义以及他们的从属关系。下一步操作称之为 layout,顾名思义就是计算出每个节点在屏幕中的位置。
    5. 再下一步就是绘制,即遍历 render 树,并使用 UI 后端层绘制每个节点。

    reflow(回流):读取或设置位置、尺寸、计算样式等等,都有可能触发 reflow。

    repaint(重绘):改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画, 但是元素的几何尺寸没有变。

    https://gist.github.com/paulirish/5d52fb081b3570c81e3a
    http://www.cnblogs.com/slly/p/6640761.html

  9. HTTP 超文本传输协议(HyperText Transfer Protocol)

  10. HTTP2
    多路复用、二进制分帧、头部压缩、服务端推送。

    HTTP/1.x 客户端需要使用多个连接才能实现并发和缩短延迟;HTTP/1.x 不会压缩请求和响应标头,从而导致不必要的网络流量;HTTP/1.x 不支持有效的资源优先级,致使底层 TCP 连接的利用率低下;等等。

    HTTP/2 通过支持标头字段压缩和在同一连接上进行多个并发交换,让应用更有效地利用网络资源,减少感知的延迟时间。具体来说,它可以对同一连接上的请求和响应消息进行交错发送并为 HTTP 标头字段使用有效编码。 HTTP/2 还允许为请求设置优先级,让更重要的请求更快速地完成,从而进一步提升性能。出台的协议对网络更加友好,因为与 HTTP/1.x 相比,可以使用更少的 TCP 连接。

    这意味着与其他流的竞争减小,并且连接的持续时间变长,这些特性反过来提高了可用网络容量的利用率。 最后,HTTP/2 还可以通过使用二进制消息分帧对消息进行更高效的处理。
    https://developers.google.com/web/fundamentals/performance/http2/?hl=zh-cn

    • 所有通信都在一个 TCP 连接上完成,此连接可以承载任意数量的双向数据流。
    • 每个数据流都有一个唯一的标识符和可选的优先级信息,用于承载双向消息。
    • 每条消息都是一条逻辑 HTTP 消息(例如请求或响应),包含一个或多个帧。
    • 帧是最小的通信单位,承载着特定类型的数据,例如 HTTP 标头、消息负载,等等。 来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。
  11. iframe 优缺点
    优点:
    样式隔离,内外样式不会冲突;低改动成本接入其他模块功能;无刷新文件上传;实现长连接,作为 Websocket 不支持浏览器的替代方案
    缺点:
    iframe 会阻塞主页面的 onload 事件;搜索引擎的检索程序无法解读这种页面,不利于 SEO;iframe 和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载。

  12. Websocket 替代方案

  13. DOM BOM 区别
    DOM 全称是 Document Object Model,也就是文档对象模型,用来操作 HTML 中的元素。例如:document.bodydocument.getElementById('someid')document.title = 'Welcome'

    BOM 是 Browser Object Model,浏览器对象模型,用来控制浏览器的行为。例如,location.href = "http://www.xxxx.com"window.reload

  14. DOM1/DOM2/DOM3 区别
    DOM1 级主要定义了 HTML 和 XML 文档的底层结构。在 DOM1 中,DOM 由两个模块组成:DOM Core(DOM 核心)和 DOM HTML。其中,DOM Core 规定了基于 XML 的文档结构标准,通过这个标准简化了对文档中任意部分的访问和操作。DOM HTML 则在 DOM 核心的基础上加以扩展,添加了针对 HTML 的对象和方法,如:JavaScript 中的 Document 对象.

    在 DOM1 的基础上 DOM2 引入了更多的交互能力,也支持了更高级的 XML 特性。DOM2 将 DOM 分为更多具有联系的模块。DOM2 级在原来 DOM 的基础上又扩充了鼠标、用户界面事件、范围、遍历等细分模块,而且通过对象接口增加了对 CSS 的支持。DOM1 级中的 DOM 核心模块也经过扩展开始支持 XML 命名空间。

    DOM3 进一步扩展了 DOM,引入了以统一方式加载和保存文档的方法,它在 DOM Load And Save 这个模块中定义;同时新增了验证文档的方法,是在 DOM Validation 这个模块中定义的。

  15. addEventListener、attachEvent、on 区别
    attachEvent 是 IE8- 添加事件的方法,onclick 会覆盖掉之前绑定的事件,addEventListener 以事件数组的形式添加事件监听,不会覆盖掉之前的事件监听。1,2

  16. 浏览器前进/后退缓存(Backward/Forward Cache,BF Cache)
    对整个 web 页面的一个浏览器会话进行了内存缓存,包括他们对 JavaScript 状态。在访问过的页面间后退和前进不需要页面加载同时保存 JavaScript 状态。这个特性,被称为 bfcache(“后退前进缓存”),使得页面导航(切换)非常快。这个状态缓存被保存直到用户关闭浏览器。
    检测是否被缓存:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    window.addEventListener(
    "pageshow",
    function(event) {
    console.log("event.persisted" + event.persisted);
    },
    false
    );
    window.addEventListener(
    "pagehide",
    function(event) {
    console.log("event.persisted" + event.persisted);
    },
    false
    );

    https://harttle.land/2017/03/12/backward-forward-cache.html
    https://developer.mozilla.org/en-US/docs/Archive/Misc_top_level/Working_with_BFCache
    https://developer.mozilla.org/zh-CN/docs/Mozilla/Firefox/Releases/1.5/Using_Firefox_1.5_caching

  17. 事件的传播机制 w3c
    eventflow
    三个阶段:首先进入捕获阶段 Window ->Document-><html>-><body>,直到达到目标元素,再进入冒泡阶段,从目标元素反向沿着捕获路径回到 Window

  18. parentNode 和 parentElement 的区别
    在大部分情况下 parentElement === parentNode,只有在 parentNode 不是 html element 的时候,parentElement = null。

    1
    2
    3
    4
    5
    document.body.parentNode; // the <html> element
    document.body.parentElement; // the <html> element

    document.documentElement.parentNode; // the document node
    document.documentElement.parentElement; // null
  19. children(HTMLCollection) 和 childNodes(NodeList) 的区别
    childNodes 比 children 多包含了几个 text 节点,children 只有 html element。
    如下图,children[0] === childNodes[1]
    childNodes-vs-children

  20. document.ready 实现

  21. http 302 和 form 表单跳转区别

javascript audio 对象常用事件

最近在做一个媒体播放器,集成了图片+音频播放模式和视频播放模式,研究了下 js audio 对象的事件,整理了相关事件及触发顺序。

音频的初始加载事件顺序:依次触发 onloadstartonprogressonsuspend,然后 onprogressonsuspend 交替触发,直到触发 ondurationchangeonloadedmetadataonloadeddataoncanplayoncanplaythrough,加载完成。

点击播放后触发事件顺序:
onplayonplayingontimeupdate,播放控件开始缓冲部分音频文件onprogress,缓冲足够多的音频片段后触发onsuspend,当缓冲即将播放完后又触发onprogressonsuspend,依次循环直到音频全部缓冲完毕。

音频播放完毕后触发:
onpauseonended

暂停播放控件时触发:
onpause

从暂停恢复播放后触发:
onplayonplaying