Web 基础

吴心役
2023-12-01

HTML

HTML 是 Hyper Text Markup Language 的缩写,中文称为超文本标记语言。

HTML 文档是指用 HTML 写成的扩展名为 .html 的文件,HTML 文当能够被浏览器识别,并翻译成对人类友好的形式展现出来,浏览器上的网页就是 HTML 文档,打开浏览器的调试模式(一般是按F12),就能看到 HTML 文档的源码。

HTML 标签是由尖括号包围的关键词,如 <html>,HTML 标签分为两种:

  • 空标签:空标签内没有内容,如 <br /> 标签。
  • 非空标签:非空标签内可以写入内容,如 <h1> 标签,一个完整的非空标签由开始标签、结束标签和标签内容组成,如 <h1>晚上标签内容</h1>。包裹在非空标签内的标签内容就是网页上展示的东西。

一般来说每个 HTML 标签都具有一定的含义,用于描述文档的内容,如 <title> 标签就表示文档的标题,当浏览器翻译 <title> 标签的内容时就能知道,文档的标题是什么。如一个文档 <title> 标签是 <title>我是网页的标题</title>,当浏览器翻译它是就会知道这个文档的标题是 我是网页的标题

一个简单的 HTML 文档示例

<!DOCTYPE html>
<html>
  <head>
    <title>文档标题</title>
  </head>
  <body>
    文档内容
  </body>
</html>
  1. <!DOCTYPE> 用于声明文档使用的 HTML 版本,<!DOCTYPE html> 表示使用 HTML5 ,这个标签可以不写,但一般写上会比较好。
  2. <html> 用于声明一个 HTML 文档,一个文档中只能有一个 <html> 元素,除了<!DOCTYPE> 以外,其他的 HTML 元素都应该包裹在 <html></html> 中,注意 <html> 是用来声明 HTML 文档的,不可忽略,虽然有时候忽略掉也不会有影响,但一般写上比较好。
  3. <head> 用于声明文档的头部部分,文档的头部部分一般还包含 <title><mate><base> 等用于描述文档基本信息的标签。
  4. <body> 用于声明文档的内容,<body></body> 中的内容会作为文档的内容显示。
  5. <body><head> 是同级标签,不要相互嵌套使用。

一个 HTML 文档的格式大概就是这样子的,剩下的就是在 <head><body> 标签中添加内容来丰富文档了。

一些标签

  1. <!DOCTYPE>:位于文档最前面的位置,处于 <html> 标签之前,它不是一个标签,只是用来告知浏览器文档使用了哪种 HTML 版本。

    • HTML 5

      <!DOCTYPE html>
      
    • HTML 4.01 Strict

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
      
    • HTML 4.01 Transitional

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
      
    • HTML 4.01 Frameset

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
      

      不同版本的 HTML 对标签的支持程度不同,现在一般使用最新的版本,即 HTML5 版本。

  2. <abbr>:定义缩写,当鼠标悬浮在缩写上时会显示完整的信息。例:

    <abbr title="HyperText Markup Language">HTML</abbr>
    
  3. <base><base> 标签为页面上的所有的相对链接规定默认 URL 或默认目标,在一个文档中,最多能使用一个 <base> 标签,且必须位于 <head> 元素内部。

    属性:

    • hred :规定页面中所有相对链接的基准 URL。
    • target :规定页面中所有的超链接和表单在何处打开。该属性会被每个链接中的 target 属性覆盖。
      • _blank:在新窗口打开。
      • _parent:在父窗口中打开。
      • _self:默认,在当前页面打开。
      • _top:在当前窗口打开,并替换当前窗口。
  4. **<meta> **:示不能由其它HTML元相关元素 (<base> <link> , <script> <style><title>) 表示的元数据信息,通常位于 <head> 标签内。

    1. charset:当前文档使用的字符编码,可以被任何一个元素的 lang 属性覆盖,推荐使用 utf-8

    2. content:包含 http-equivname 属性的值。

    3. http-equiv:这个属性已经过期,不要使用。

    4. name:定义文档级元数据的名称。与 content 属性包含的值相关联,参数如下:

      • application-name:定义正运行在该网页上的网络应用名称;

      • author:这个文档的作者的名称。

        <meta name="author" content="aioverg" />

      • description:页面内容的简短描述。 一些浏览器,会将其用作为书签页面的默认描述。

      • generator:包含生成页面的软件的标识符。

      • keywords:定义文档关键字,用逗号分隔的与页面内容相关的单词。

        <meta name="keywords" content="HTML, CSS, meta" />

      • viewport:提供有关视口初始大小的提示,仅供移动设备使用。值为:

        <meta name="viewport" content="key=value, key=value" />

        keyvalue描述
        width正整数、device-widthpx 为单位, 定义视口的宽度
        height正整数、device-heightpx 为单位, 定义视口的高度
        initial-scale0.0 ~ 10.0之间的数定义设备宽度与视口大小之间的缩放比率
        maximum-scale0.0 ~ 10.0之间的数定义缩放的最大值;必须大于或等于minimum-scale的值,不然会导致不确定的行为发生。
        minimum-scale0.0 ~ 10.0之间的数定义缩放的最小值;它必须小于或等于maximum-scale的值,不然会导致不确定的行为发生。
        user-scalableyes、no如果设置为 no,用户将不能放大或缩小网页。默认值为 yes
  5. HTML媒体

    HTML5 提供了 <video><audio> 元素以便在网页中嵌入富媒体,通过这些元素自带的 API 可以来控制音频、视频的播放、进度等。其中 controls 属性会启用浏览器默认的播放设置,但在不同的浏览器中默认播放设置可能存在差异,若想在不同的浏览器中使播放设置保持一致,可用使用 HTMLMediaElement API 来以编程式的方式自定义控制视频。

  6. <template>:创建一个模板来保存文档内容,一般来说模板内的内容是由 JavaScript 实例化的,注意模板内容不会显示在页面上,若要将模板的内容显示在页面上,需要提取模板的内容放入页面中的其他元素内。例如:

    <div id="ex"></div>
    <template id="temp"></template>
    <script>
        if('content' in document.createElement('template')){//判断<template>是否支持
            let temp = document.querySelector('#temp')
    		temp.innerHTML = "<h4>aioverg</h4>"//将内容插入到模板中
    		let ex1 = document.querySelector('#ex')
    		ex1.appendChild(temp.content)//将模板内容插入到<div>中展示
        }else{}
    </script>
    
  7. <slot>:占位符,与 <template> 配合使用,在实例化组件的时候插入内容。例如:

    <element-define>
        <span slot="two">slot</span>
    </element-define>
    
    <template id="element-define">
        <p>aioverg</p>
        <slot name="one"><p>默认显示内容</p></slot>
        <slot name="two"><slot>
    </template>
    <script>
        customElements.define('element-define',
            class extends HTMLElement {
                constructor() {
                super();
                var template = document.getElementById('element-define').content;
                const shadowRoot = this.attachShadow({mode: 'open'}).appendChild(template.cloneNode(true));
            }
    })
    </script>
    

其它

  1. <p> 元素不能嵌套块级元素,嵌套的块级元素不会成为 <p> 的子元素,且 <p> 的开始和闭合标签会变成两个完整的 <p> 元素。

  2. src 是指向物件的来源地址,是引入。在 <img><script><iframe> 等元素上使用。 当浏览器解析到该资源时会暂停其他资源的下载和处理,直至将该资源加载,编译,执行完毕, 图片和框架等元素也是如此,类似于该元素所指向的资源嵌套到当前标签内,这也是为什么要把js放在底部而不是头部。

  3. href 是超文本引用,指向需要连结的地方,是与该页面有关联的,是引用。在 <link><a> 等元素上使用。 当浏览器解析到该资源时会下载但不会停止对当前文档的处理。

  4. HTML中引入SVG的几种方法:

    1. 作为图片使用

      <img src = 'name.svg' />
      
    2. 作为CSS背景图片

      background: url(name.svg)
      
    3. 作为一个嵌入对象<object>标签

      <object type='image/svg+xml' data='name.svg'>
          <!-- 浏览器不支持时的备选内容-->
      </object>
      
    4. 使用 <iframe> 标签

      <iframe src='name.svg'>
          <!--浏览器不支持时的备选内容-->
      </iframe>
      
    5. 使用 <embed> 标签

      <embed type='image/svg+xml' src='name.svg' />
      
    6. 使用内联 <svg> 标签

      <svg><!--svg内容--></svg>
      

CSS

CSS 是 Cascading Style Sheets 的缩写,中文称为层叠样式表,是一种样式表语言,用来描述 HTML 或 XML(包括如 SVG、MathML 或 XHTML 之类的 XML 分支语言)文档在屏幕、纸质、音频等其他媒体上的呈现方式。

引入样式

<link>@import

<link> 是 HTML 标签,只能在 HTML 文档中使用,语法:<link rel="stylesheet" href="./file.css" />

@import 可以在 HTML 文档和 CSS 文件中使用,在 HTML 文档中使用:

<style type="text/css">
    @import url(./file.css)
</style>

在 CSS 文件中使用:

@import url(./file.css)

选择器

id > class = 属性 = 伪类选择器 > 标签 = 伪元素 >通配符

当权重一样时:!important > 内部 > 内联 > 外联(当权重一样时条件成立)。

基本选择器

  1. elementName{}:元素选择器。
  2. className{}:类选择器。
  3. idName:id选择器。
  4. *{}:通配选择器。
  5. selectNameA, aelectNameB{}:组选择器,同时选择 selectNameA aelectNameB 节点。
  6. selectName[]{}:属性选择器,示例:
    • a[title]{}:选择存在title属性的<a>元素。
    • a[title="aioverg"]:选择存在title属性,且属性值为aioverg<a>元素。
    • a[title*="aioverg"]:选择存在title属性,且属性值包含aioverg<a>元素。
    • a[title$="aioverg"]:选择存在title属性,且属性值以aioverg结尾的<a>元素。
    • a[title^="aioverg"]:选择存在title属性,且属性值以aioverg开头的<a>元素。
    • a[title~="aioverg"]:选择存在title属性,且属性值以空格分隔的值列表中有aioverg<a>元素。
    • a[title|="aioverg"]:选择存在title属性,且属性值是aioverg或以aioverg-开头的<a>元素。

关系选择器

  1. selectNameA + selectNameB{}:相邻兄弟选择器,selectNameBselectNameA的相邻兄弟节点。
  2. selectNameA ~ selectNameB{}:通用兄弟选择器,selectNameBselectNameA的兄弟节点。
  3. selectNameA > selectNameB{}:子选择器,selectNameBselectNameA的直接子节点。
  4. selectNameA selectNameB{}:后代选择器,selectNameBselectNameA的后代节点。

伪类选择器

  1. :active:设置元素被用户激活时的样式(即鼠标点击和松开之间的样式)。

  2. :checked:匹配处于选中状态的元素,(用于<input>typeradiocheckbox时)。

  3. :disabled:匹配任何被禁用的元素。如果一个元素不能被激活(如选择、点击或接受文本输入)或获取焦点,则该元素处于被禁用状态。

  4. :default:表示一组相关元素中的默认表单元素。可以在 <button>、<input type="checkbox">、<input type="radio">、 <option> 上使用。例如:

    <form id="ex1">
        <input type="radio" checked/>
        <input type="radio" />
        <input type="checkbox" checked/>
        <input type="checkbox" />
        <select>
            <option>one</option>
            <option selected>two</option>
        </select>
    </form>
    <style>
        #ex1 input:default {/*默认选中的<input>元素有黄色阴影*/
            box-shadow: 0 0 2px 1px yellow;
        }
        #ex1 option:default {/*默认选中的<option>元素有黄色阴影*/
            color: yellow;
     }
    </style>
    
  5. :defined:表示任何已定义的元素,包括浏览器内置的标准元素以及已成功定义的自定义元素 (例如通过CustomElementRegistry.define()方法)。

  6. :empty:匹配没有子元素的元素。

  7. :enabled:匹配被启用的元素,如果一个元素能够被激活(如选择、点击或接受文本输入),或者能够获取焦点,则该元素是启用的。

  8. :focus:设置元素成为焦点时的样式。

  9. :first-child:匹配一组兄弟元素中的第一个。

  10. :first-of-type:匹配一组兄弟元素中第一个符合类型的元素。

  11. :first:打印文档时第一页的样式,配合@page使用。

  12. :focus-within:匹配获得焦点的元素或它的后代获得焦点的元素。

  13. :hover:设置元素在鼠标悬停时的样式。

  14. :indeterminate 选择状态不确定的表单元素。

  15. :in-range :选择 <input>元素,其当前值处于属性minmax 限定的范围之内。

  16. :invalid:选择内容未通过验证的 <input> 或其他 <form> 元素。

  17. :link:选择未被访问的超链接<a>

  18. :lang(fr):选择使用fr语言的元素。

  19. :last-child:选择一组兄弟元素中的最后一个。

  20. :last-of-type:选择一组兄弟元素中最后一个符合类型的元素。

  21. :left:打印文档时左侧页的样式,配合@page使用。

  22. :not(s):匹配不含有选择符的元素。

  23. :nth-child(an + b):从前向后选择一组兄弟元素中位置为an + b的元素,n默认为0,1,2···ab为指定的整数参数。如:2n + 1匹配第1、3、5···个元素。

  24. :nth-last-child(an + b):从后向前选择一组兄弟元素中位置为an + b的元素,n默认为0,1,2···ab为指定的整数参数。如:2n + 1匹配倒数第1、3、5···个元素。

  25. :nth-of-type(an + b):从前向后选择一组兄弟元素中符合类型的元素且位置为an + b的元素,n默认为0,1,2···ab为指定的整数参数。如:2n + 1匹配第1、3、5···个元素。

  26. :nth-last-of-type(an + b):从后向前选择一组兄弟元素中符合类型的元素且位置为an + b的元素,n默认为0,1,2···ab为指定的整数参数。如:2n + 1匹配倒数第1、3、5···个元素。

  27. :only-child:匹配没有兄弟元素的元素。与:first-child:last-child效果相同。

  28. :only-of-type:匹配一组兄弟元素中没有相同类型的元素。

  29. :optiomal:选择没有required属性的<input>、<select>、<textarea> 元素。

  30. :out-of-range:选择<input>元素,其当前值处于属性minmax限定的范围外。

  31. :placeholder-shown :选择有placeholder属性的<input><textarea>元素。

  32. :root:选择元素在文档的根元素。

  33. :right:打印文档时右侧页的样式,配合@page使用。

  34. :read-only:选择所有处于不可编辑状态的元素。

  35. :read-write:选择所有处于可编辑状态的元素。

  36. :required:选择拥有required属性<input>元素。

  37. :target:选择唯一的页面元素(目标元素),其id 与当前URL片段匹配。

  38. :visited:选择已被访问时的超链接<a>

  39. :valid:选择内容过验证的 <input> 或其他 <form> 元素。

注意

  1. 伪类选择器要紧跟在普通选择器或关系选择器后面。

  2. 一组兄弟元素指,标签、类、id等选择符相同的元素,且中间不能夹杂其它元素。如:

    <span id="a">one</span>
    <span id="a">two</span>
    <span class="b">thr</span>
    <span id="a">fou</span>
    <span class="b">fiv</span>
    <!--当使用id="a"来选择兄弟元素时,one,two是一组兄弟元素,fou是另一组兄弟元素。-->
    <!--当使用class="b"来选则兄弟元素时,thr是一组,fou是一组。-->
    

伪元素选择器

  1. ::after:创建一个伪元素,作为已选中元素的最后一个子元素,通常会配合 content 属性来为该元素添加装饰内容。例如:

    添加内容
    <span id="ex2">添加内容</span>
    <style>
        #ex2::after{
            content: "-aioverg";
         color: blue;
        }
    </style>
    
  2. ::before:创建一个伪元素,其将成为匹配选中的元素的第一个子元素。通常会配合 content 属性来为该元素添加装饰内容。

  3. ::first-line:在某块级元素的第一行应用样式。

  4. ::first-letter:选中某块级元素第一行的第一个字母,并且文字所处的行之前没有其他内容(如图片和内联的表格)。

  5. ::selection:应用于文档中被用户高亮的部分(比如使用鼠标或其他选择设备选中的部分)。

  6. ::slotted():暂略。

计量单位

文本相对长度单位

  1. em:相对于父容器的字体尺寸,浏览器默认字体大小是16px。
  2. ex:相对于父容器的字体高度的一半。
  3. ch:相对于父容器的字体宽度的一半。
  4. rem:相对于根元素<html>的字体尺寸。

视口相对长度单位

  1. vw:相对于视口的宽度。视口宽度总是等于100vm
  2. vh:相对于视口的高度。视口宽度总是等于100vh
  3. vmax:相对于视口的高度或宽度中最大的那个,视口的高度或宽度总是等于100vmax,如视口的高度为100px,宽度为200px,则100vmax=200px
  4. vmin:相对于视口的高度或宽度中最小的那个,视口的高度或宽度总是等于100vmax,如视口的高度为100px,宽度为200px,则100vmax=100px

绝对长度单位

  1. cm:厘米

  2. mm:毫米

  3. q:1/4毫米

  4. in:英寸

  5. pt:点

  6. pc:派卡

  7. px:像素,像素的长度是固定的。

    换算关系:1in = 2.54cm = 25.4 mm = 72pt = 6pc = 96px

角度单位

deg:度,π = 180deg

grad:梯度,π = 200grad

rad:弧度,2π rad = 360deg

turn:转,2π = 1 turn

换算关系:90deg = 100grad = 0.25turn ≈ 1.570796326794897rad

时间

  1. s:秒
  2. ms:毫秒
  3. 换算关系:1s = 1000ms

频率

  1. Hz:赫兹,一秒钟内完成的周期个数

  2. kHz:千赫兹

    换算关系:1kHz = 1000Hz

分辨率

  1. dpi:每英寸包含点的数量。
  2. dpcm:每厘米包含点的数量。
  3. dppx:每像素包含点的数量。

颜色

  1. HEX:十六进制记法,取值#RRGGBBRR红色GG绿色BB蓝色的取值范围为00 ~ FF

  2. RGBRGB记法,取值rgb(R, G ,B)R红色G绿色B蓝色的取值范围为0 ~ 2550.0% ~ 100%

  3. RGBARGBA记法,取值rgba(R, G, B, A)R红色G绿色B蓝色的取值范围为0 ~ 2550.0% ~ 100%A指透明度,取值范围为0 ~ 1

  4. HSLHSL记法,取值hsl(H, S, L)H色调的取值范围为0 ~ 360S饱和度取值范围为0.0% ~ 100.0%L亮度取值范围为0.0% ~ 100.0%

  5. HSLAHSLA记法,取值hsl(H, S, L, A)H色调的取值范围为0 ~ 360S饱和度取值范围为0.0% ~ 100.0%L亮度取值范围为0.0% ~ 100.0%A指透明度,取值范围为0 ~ 1

  6. transparent:全透明黑色的速记法。与rgba(0, 0, 0, 0)效果相同。

  7. currentColor:表示color属性的值,若用在自身上,即color: currentColor,则相当于是color: inherit。注意在border-color属性中,属性的默认值为color属性的值,所以

    p {
        border: 1px solid;
        color: red;
    }
    

    会得到一个红色的边框。

百分比%:情况不定,暂略。

关键字

  1. inherit:指定一个属性从父元素继承它的值。
  2. initial:设置一个属性的值为默认值,即不会继承父元素的值。
  3. !important:标注有!important的属性不会被覆盖。

函数

  1. calc():四则运算,如:width: calc(200px - 100px)等于width: 100px,注意,进行运算的对象的单位要是一样的。

  2. counter():将计数器的值添加到元素。

  3. counters():将计数器的值添加到元素。

  4. sttr():返回元素的属性值,参数必须为参数的属性,如:

    <a href="http://aioverg.com">荆棘之旅</a>
    <style>
        /*会将标签<a>的href属性的值作为<a>标签最后一个元素*/
        a::after {
            content: attr(href)
        }
    </style>
    
  5. url():指向对一个资源的指针。如:

    <p></p>
    <style>
        p {/*为<p>设置背景图片*/
            background-image: url("aioverg.jpg")
        }
    </style>
    
  6. image():大多数浏览器不支持,暂略。

  7. image-set():大多数浏览器不支持,暂略。

  8. linear-gradient():使用颜色创建线性的渐变图像。

  9. radial-gradient():使用颜色创建径向的渐变图像。

  10. repeating-linear-gradient():使用颜色创建重复径向的渐变图像。

  11. repeating-radial-gradient():使用颜色创建重复线性的渐变图像。

元素属性

元素模型属性

  1. box-sizing:设置元素的模型类型。
    • content-box:默认,paddingborder 不包含在 contentwidthheight 中的盒模型。
    • border-boxpaddingborder 包含在 contentwidthheight 中的盒模型。
  2. box-shadow: h-shadow v-shadow blur spread color inset:定义元素的阴影。
    • h-shadow:必需,水平阴影位置,正值,阴影出现在元素右侧;负值,则阴影出现在元素左侧
    • v-shadow:必需,垂直阴影位置,正值,阴影出现在元素底部;负值,则阴影出现在元素顶部
    • blur:模糊距离,值越大,模糊面积越大,阴影就越大越淡。 不能为负值,默认为0,此时阴影边缘锐利。
    • spread:阴影的大小,取正值时,阴影扩大;取负值时,阴影收缩。默认为0,此时阴影与元素同样大。
    • color:阴影颜色,默认取当前最近的文本颜色
    • insert:布尔属性,阴影放在内部(默认为外部)
  3. opacity:设置元素的透明度级别。
    • number:范围在 0.0 ~ 1.0 之间,如果超过了这个范围,其计算结果将截取到与之最相近的值。
  4. line-height:设置元素的行高。
    • normal:默认。设置合理的行间距,允许内容顶开或溢出指定的容器边界
    • number:相对值,参照当前的字体尺寸,不允许负值。
    • length:绝对值,不允许负值。
  5. vertical-align:设置行内元素或表格单元格元素的垂直对齐方式。
    • baseline:默认。把当前元素的基线与父级元素的基线对齐。如果该元素没有基线,就将底部外边距的边界和父级元素的基线对齐。
    • sub:垂直对齐文本的下标。把当前盒的基线降低到合适的位置作为父级盒的下标(该值不影响该元素文本的字体大小)。
    • super:垂直对齐文本的上标。把当前盒的基线提升到合适的位置作为父级盒的上标(该值不影响该元素文本的字体大小)
    • top:把元素的顶端与行中最高元素的顶端对齐
    • text-top:把元素的顶端与父元素字体的顶端对齐
    • middle:把此元素放置在父元素的中部。把当前盒的垂直中心和父级盒的基线加上父级的半x-height对齐。
    • bottom:把元素的底端与行中最低的元素的顶端对齐。
    • text-bottom:把元素的底端与父元素字体的底端对齐。
    • length:把当前盒提升(正值)或者降低(负值)这个距离。当值为0时等同于baseline。
    • %:把当前盒提升(正值)或者降低(负值)这个距离,百分比相对line-height计算。当值为0%时等同于baseline。
  6. resize:设置是否允许用户调整元素尺寸大小,需要 overflow 属性不是 visible
    • none:用户无法调整元素的尺寸
    • both:用户可调整元素的高度和宽度
    • horizontal:用户可调整元素的宽度
    • vertical:用户可调整元素的高度

元素内容属性

  1. height:设置元素内容区的高度。
    • auto:默认,浏览器计算实际的高度
    • length:绝对单位。
    • %:父元素的百分比
  2. width:设置元素内容区的宽度。
    • auto:默认,浏览器计算实际的宽度。
    • length:绝对单位。
    • %:父元素的百分比。
  3. max-height:设置元素内容区的最大高度。
  4. min-height:设置元素内容区的最小高度。
  5. max-width:设置元素内容区的最大宽度。
  6. min-width:设置元素内容区的最小宽度。
  7. overflow:当元素的内容溢出元素时,元素处理内容的方式。
    • visible:默认,对溢出内容不做处理,内容可能会超出容器。
    • hidden:隐藏溢出的内容且不出现滚动条。
    • scroll:隐藏溢出的内容,溢出的内容可以通过滚动呈现(无论内容是否溢出都会显示滚动条)。
    • auto:按需出现滚动条,即当内容没有溢出时不出现滚动条,当内容溢出时出现滚动条。<textarea> 元素的 overflow 属性的默认值是 auto
  8. overfolw-x:当元素的内容溢出容器时,元素在横轴上处理溢出内容的方式。
    • visible:默认,不剪裁内容,可能会显示在内容框之外。
    • hidden:隐藏溢出的内容且不出现滚动条。
    • scroll:隐藏溢出的内容,溢出的内容可以通过滚动呈现(无论内容是否溢出都会显示滚动条)。
    • auto:按需出现滚动条,即当内容没有溢出时不出现滚动条,当内容溢出时出现滚动条。
  9. overflow-y:当元素的内容溢出容器时,元素在纵轴上处理溢出内容的方式。
    • visible:默认,不剪裁内容,可能会显示在内容框之外。
    • hidden:隐藏溢出的内容且不出现滚动条。
    • scroll:隐藏溢出的内容,溢出的内容可以通过滚动呈现(无论内容是否溢出都会显示滚动条)。
    • auto:按需出现滚动条,即当内容没有溢出时不出现滚动条,当内容溢出时出现滚动条。

元素内边距属性

  1. padding: 2 3 4 5:复合属性,1~4个值,设置元素的内边距。
    • auto:浏览器计算下外边距。
    • length:绝对单位。
    • %:父元素的百分比。
  2. padding-top:设置元素的上内边距。
  3. padding-right:设置元素的右内边距。
  4. padding-bottom:设置元素的下内边距。
  5. padding-left:设置元素的左内边距。

元素边框属性

  1. border: 2 3 4:复合属性,设置元素边框。

  2. border-color:复合属性,设置边框的颜色,1~4个值,对应4个边框。

    color:颜色名。

    transparent:默认,透明。

  3. border-style:复合属性,设置边框样式,1~4个值,对应4个边框。

    • none:默认,无样式。

    • hidden:与none相同,用于解决边框冲突。

    • style:取值如下:

      dotted:点状框

      dashed:虚线

      solid:实线

      double:双线,宽度等于border-width的值

      groove:3D凹槽边框,效果取决于border-color的值

      ridge:3D垄状边框,效果取决于border-color的值

      inset:3Dinset边框,效果取决于border-color的值

      outset:3Doutset边框,效果取决于border-color的值

  4. border-width:复合属性,设置边框的宽度,1~4个值,对应4个边框。

    • thin:细边框。
    • medium:默认,中等宽度。
    • thick:粗边框。
    • length:自定义宽度。
  5. border-top:复合属性,1~3个值,设置顶部边框的颜色、样式、宽度。

  6. border-bottom:复合属性,1~3个值,设置底部边框的颜色、样式、宽度。

  7. border-left:复合属性,1~3个值,设置左边边框的颜色、样式、宽度。

  8. border-right:复合属性,1~3个值,设置右边边框的颜色、样式、宽度。

  9. border-top[right | bottom | left]-color:设置顶部(右边、底部、左边)边框的颜色。

  10. border-top[right | bottom | left]-style:设置顶部(右边、底部、左边)边框的样式。

  11. border-top[right | bottom | left]-width:设置顶部(右边、底部、左边)边框的宽度。

  12. border-radius: 13 14 15 16:设置边框的角的弧度,复合属性。

    x x x x / y y y y:分别对应上左角的水平半径和垂直半径、上右角的水平半径和垂直半径,下右角的水平半径和垂直半径,下左角的水平半径和垂直半径。若省略y值,则y默认与x相等。

  13. border-top-left-radius:设置边框上左角的水平半径和垂直半径。

  14. border-top-right-radius:设置边框上右角的水平半径和垂直半径。

  15. border-bottom-right-radius:设置边框下右角的水平半径和垂直半径。

  16. border-bottom-left-radius:设置边框下左角的水平半径和垂直半径。

  17. border-image:复合属性,使用图像设置边框的样式。

  18. border-image-outset:设置边框图像从边框边界向外的偏移量,默认为0,可以为负值。

    • length:1-4个值,对应上、右、下、左。
    • number:相对于border-width的倍数。
  19. border-image-repeat:设置图片如何填充边框,单值设置所有边框,双值分别设置水平和垂直边框。

    • stretch:默认值,拉伸图像来填充边框。
    • repeat:重复平铺图像来填充边框,超出时会剪裁。
    • round:重复平铺图像来填充边框,超出时会缩放图像。
    • space:重复平铺图像来填充边框,不能以整数次平铺时,用空白间隙均匀填充在图像周围。
  20. border-image-slice:1~5个值,设置切割图片的四条线距离图片上右下左的距离,和图像剪裁的中间部分是否作为元素背景图像使用。

    1、number:数值,单位是px,但不能写出px。 2、%:百分比,垂直和水平方向分别参照图片的宽度和高度。 3、fill:保留裁减后的中间区域,并将其作为元素背景,即background-image

  21. border-image-source:设置作为边框样式的图像,会替换border-style属性中设置的边框样式

    • none:不使用图像。
    • url():引入作为边框样式的图像。
  22. border-image-width:设置作为边框的图像的宽度,它只影响图像的宽度,不会影响边框的宽度,如果值小于border-width,图像会贴着边界外侧,无法填满边界;如果值大于border-width,图像会越过边框内边界,重叠在内边距或内容上。

    • length:使用绝对单位,不允许负值。
    • %:使用百分比,参照是元素边框的总宽度,等于:元素内容框的宽度 + 元素内边距的宽度 + 元素边框的宽度。
    • number:用浮点数,该值表示border-width的倍数。

元素轮廊属性:轮廊处在边框之外,外边距之内,与边框很相似,但轮廊不占据空间,可以是非矩形的。

  1. outline: 2 3 4 5:复合属性。

  2. outline-color:设置轮廊的颜色。

    • color:颜色名。
    • invert:反色,用于确认轮廊的显示,有些浏览器不支持。
  3. outline-style:设置轮廊线条的样式。

    • none:默认,无边框。
    • dotted:点状框
    • dashed:虚线
    • solid:实线
    • double:双线,宽度等于outline-width的值
    • groove:3D凹槽边框,效果取决于outline-color的值
    • ridge:3D垄状边框,效果取决于outline-color的值
    • inset:3Dinset边框,效果取决于outline-color的值
    • outset:3Doutset边框,效果取决于outline-color的值
  4. outline-width:设置轮廊线框的宽度。

    • length:自定义边框宽度

    • thin:细边框

    • medium:默认,中等的边框

    • thick:粗边框

  5. outline-offset:设置轮廓线框在border边缘外的偏移量。

    • length:长度值,允许负值。

元素外边距属性

  1. 外边距折叠:相邻元素之间。父元素与其第一个或最后一个子元素之间。空的块级元素。
  2. margin: 2 3 4 5:复合属性,1~4个值,设置元素的外边距。
    • auto:浏览器计算下外边距。
    • length:绝对单位
    • %:基于父元素的长度。
  3. margin-top:设置元素的上外边距。
  4. margin-right:设置元素的右外边距。
  5. margin-bottom:设置元素的下外边距。
  6. margin-left:设置元素的右外边距。

元素的列属性

  1. columns: 2 3:复合属性,设置元素的列宽和列数。
  2. column-width:设置元素的列宽。
    • length:用长度值定义。
    • auto:根据column-count数据自动分配宽度。
  3. column-count:设置元素的列数。
    • number:用整数值来定义列数。
    • auto:根据column-width数据自动分配宽度。
  4. column-gap:设置元素的列之间的间隙。
    • length:用长度值定义,不允许负值。
    • normal:与font-size大小相同。
  5. column-rule: 6 7 8:复合属性,定义元素的列的边框。
  6. column-rule-width:设置元素的列的边框的厚度。
    • length:用长度值来定义,不允许负值。
    • medium:默认厚度。
    • thin:比默认厚度细。
    • thick:比默认厚度粗。
  7. column-rule-style:设置元素的列的边框的样式。
    • none:无边框
    • hidden:隐藏边框
    • dotted:点状边框
    • dashed:虚线边框
    • solid:实线边框
    • double:双线边框,两条单线与其间隔的和等于指定的column-rule-width
    • groove:3D凹槽边框
    • ridge:3D凸槽边框
    • inset:3D凹边边框
    • outset:3D凸边边框
  8. column-rule-color:设置元素的列的边框的颜色。
    • color:颜色名
  9. column-span:设置在一个元素可以横跨父元素的多少列。
    • none:不横跨
    • all:横跨所有列
  10. column-fill:设置元素的列的高度是否同一。
    • auto:列的高度自适应内容。
    • blance:所有列的高度与高度最高的一列相同。

字体属性

概述

007

  • 上图从上到下四条线分别是顶线、中线、基线、底线,很像英语字母四线三格,vertical-align属性中top、middle、baseline、bottom,就是和这四条线相关。
  • 行高:上下两文本行的基线间的垂直距离。
  • 行距:上一行文本行底线到下一行文本行顶线的垂直距离。

属性

  1. font:复合属性,在一个声明中设置所有字体属性,按顺序来写的:font-style font-variant font-weight font-stretch font-size line-height font-family,使用 font 的简写形式时,font-sizeline-height属性之间必须放一个正斜杠。

  2. @font-face`:引入字体文件。示例:

    @font-face {
        src: url("myFont.ttf"); /*引入字体文件*/
        font-family: "myFont"; /*命名引入的字体*/
    }
    
  3. font-family:使用字体,多种字体使用逗号隔开,前面的优先级高于后面。

    • fontName:字体名称。
  4. font-size:设置字体的大小。

    • xx-samll/x-small/small/medium/large/x-large/xxlarge:把字体设置为不同的尺寸,默认为medium
    • number:使用绝对单位或相对单位。
  5. font-weight:设置字体线条的粗细。

    • normal:默认值,标准的字体线条。
    • bold:较粗的字体线条。
    • bolder:更粗的字体线条。
    • lighter:较细的字体线条。
    • 100 ~ 900400等于normal700等于bold
  6. font-variant:设置字体是否为小型的大写字母。

    • normal:默认值,标准的字体。
    • small-caps:小型大写字母的字体。
  7. font-style:设置字体是否为斜体。

    • normal:默认,标准字体样式。
    • italic:斜体字体样式。
    • oblique:倾斜的字体样式。
  8. font-stretch:定义元素的文字是否横向拉伸变形

    • normal:默认,正常文字宽度
    • ultra-condensed:比正常文字宽度窄4个基数。
    • extra-condensed:比正常文字宽度窄3个基数。
    • condensed:比正常文字宽度窄2个基数。
    • semi-condensed:比正常文字宽度窄1个基数。
    • semi-expanded:比正常文字宽度宽1个基数。
    • expanded:比正常文字宽度宽2个基数。
    • extra-expanded:比正常文字宽度宽3个基数。
    • ultra-expanded:比正常文字宽度宽4个基数。
  9. font-size-adjust:暂略。

文本属性

  1. color:设置文本的颜色。

    colorName:颜色名。

  2. direction:设置文本流的方向。

    • ltr:默认,从左到右。
    • rtl:从右到左。
  3. unicode-bidi:如何处理一块内容中同时包含ltrrtl文本流的文本。不应当随意修改此属性,暂略。

  4. writing-mode:设置文本的书写方向

    • horizontal-tb:默认,水平方向自上而下的书写方式。
    • vertical-rl:垂直方向自右而左的书写方式。
    • vertical-lr:垂直方向自左而右的书写方式。
  5. white-space:设置如何处理元素中的空白。参数如下:

    参数换行符空格和制表符文字转行
    normal默认合并合并转行
    nowrap合并合并不转行
    pre保留保留不转行
    pre-wrap保留保留转行
    pre-line保留合并转行
    break-spaces保留保留转行
  6. white-break:设置单词怎样断行。

    • normal:默认,浏览器的断行规则。
    • break-all:允许在单词内换行。
    • keep-all:只能在半角空格或连字符处换行。
    • break-word:与break-all相同,不同的地方在于它要求一个没有断行破发点的词必须保持为一个整体单位。
  7. overflow-wrap:是否允许过长的字符串断行。

    • normal:默认,在单词结束处换行。
    • break-word:内容将在边界内换行,如果需要,单词内部允许断行。
  8. word-spacing:设置单词间的间距,单词以空格为界。

    • normal:默认间距。
    • length:长度单位,允许负值。
  9. letter-spacing:设置字符间的间距。

    • normal:默认间距。
    • length:长度单位,允许负值。
  10. text-transform:设置文本的大小写。

    • none:默认,不对文本进行处理。
    • capitalize:将单词的第一个字母转换成大写。
    • uppercase:将单词转换成大写。
    • lowercase:将单词转换成小写
    • full-width:将所有字符转换成fullwidth形式。如果字符没有相应的fullwidth形式,将保留原样。
  11. text-align:设置文本的水平对齐方式。

    • left:默认,左对齐。
    • center:居中对齐。
    • right:右对齐。
    • justify:两端对齐,对最后一行无效。
    • justify-all:两端对齐,最后一行也两端对齐。
    • start:对齐内容开始的边界。
    • end:对齐内容结束的边界。
  12. text-align-last:内容最后一行的对齐方式。

    • auto:默认,左对齐。
    • left:左对齐。
    • right:右对齐。
    • center:居中对齐。
    • justify:两端对齐。
    • start:对齐内容开始的边界。
    • end:对齐内容结束的边界。
  13. text-justify:设置当text-align设置为justify时使用什么方式实现文本内容两端对齐。

    • auto:默认,浏览器齐行算法。
    • none:禁止两端对齐
    • inter-word:通过增加字之间的空格实现两端对齐。
    • inter-ideograph:表意字文本通过增加或减少表意字和词间的空格实现两端对齐。
    • inter-cluster:通过增加或减少词间的空格实现两端对齐。
    • distribute:通过增加或减少词间的空格实现两端对齐。
    • kashida:通过拉长字符实现两端对齐。
  14. text-indent:设置文本块的首行缩进量。

    • length:绝对单位。
    • %:相对单位,相对于包含块的宽度。
  15. text-overflow:设置文本溢出时,如何显示。只有容器的overflow不是visiblewidth 不是autowhite-spacenowrap时才生效。

    • clip:默认,当内容溢出块容器时,将溢出部分裁切掉。
    • ellipsis:当内容溢出块容器时,将溢出部分替换为...
  16. text-decoration: 17 18 19:复合属性,设置文本的装饰线。

  17. text-decoration-line:设置文本装饰线的位置。

    • none:默认,无装饰。
    • underline:下划线。
    • overline:上划线。
    • line-through:贯穿线。
  18. text-decoration-color:设置文本装饰线的颜色。

    • color:颜色名。
  19. text-decoration-style:设置文本装饰线的样式。

    • solid:实线
    • double:双线
    • dotted:点状线条
    • dashed:虚线
    • wavy:波浪线
  20. text-shadow:为文字添加阴影。

    • none:默认,无阴影。
    • 1 ~ 4:第一个值设置字体阴影的水平偏移值,可以为负值。第二个值设置字体阴影的垂直偏移值,可以为负值。第三个值设置对象的阴影模糊值,不允许负值。第四个值设置阴影的颜色。

内容生成属性

  1. content:用于在元素的伪元素::before::after中插入内容。

    • none:不会产生伪元素。
    • string:文本内容。
    • url():外部资源,图片等。
    • counter:计数器。
    • open-quote | close-quote:将quotes定义的引号作为插入内容。
    • no-open-quote | no-close-quote:不插入内容,但会改变引号层级。
  2. quotes:配合<q>元素使用,设置嵌套引用的引号类型。

    • nonecontent属性的open-quoteclose-quote不会展示引号。

    • [string string]+:成对的string用于设置引号类型,前面的是最外层引号,里面的是嵌套层引号。示例:

      <div id="ex">
          <q>one
              <q>two</q>
          </q>
      </div>
      <style>
          #ex {
              /*第一层嵌套引号为:+ -,第二层嵌套引号为:* / */
              quotes: "+" "-" "*" "/";
           /*  显示+one*two/-  */
          }
      </style>
      

背景属性

  1. background: 2 3 4 5 6 7 8 9:复合属性。

  2. background-color:设置颜色作为元素的背景。

    • transparent:默认,背景颜色是透明的。
    • color:颜色名。
  3. background-image:设置一个图像或多个堆叠图像作为元素的背景,多个图像之间用逗号分隔,前面的放在最上面。

    • url():使用图片设置背景。
    • linear-gradient():使用颜色渐变函数设置背景。
  4. background-position:设置背景图像在元素中的位置,位置是相对于由background-origin定义的位置图层的,为多重背景设置时用逗号分隔。

    • x y:默认left top,即左上角。xy取值如下:

      left:左边

      right:右边

      top:顶部

      bottom:底部

      center:中间

      length:长度,其中百分比的参照物是背景区域的宽度和高度。

  5. background-origin:设置元素的背景区域,background-position就是以这个区域作为参考点的,为多重背景设置时用逗号分隔。

    • padding-box:默认,padding + content区域作为背景区域。
    • border-boxborder + padding + content区域作为背景区域。
    • content-boxcontent区域作为背景区域。
  6. background-clip:设置元素的背景(背景图片或颜色)是否延伸到边框下面,为多重背景设置时用逗号分隔。

    • border-box:默认,背景延伸至边框外沿(但是在边框下层)。
    • padding-box:背景延伸至内边距(padding)外沿,不会绘制到边框处。
    • content-box:背景被裁剪至内容区(content box)外沿。
    • text:背景被裁剪成文字的前景色。
  7. background-size:设置背景图像的尺寸,为多重背景设置时用逗号分隔。

    • x y:设置背景图片宽度和高度,第一个值设置宽度,第二个值设置高度。如果只给出一个值,第二个值为auto(根据图片宽度保持比例计算出的高度)。其中百分比的参照单位是由background-origin定义的背景区域。
    • cover:保持比例缩放背景图片以完全覆盖背景区,可能背景图片部分看不见。
    • contain:保持比例缩放背景图片以完全装入背景区,当background-repeat:no-repeat时背景区可能留有空白。
  8. background-repeat:设置背景图像的重复方式,为多重背景设置时用逗号分隔。

    • x y:单值或双值,x表示在x轴方向应用样式,y代表在y轴方向应用样式。取值为:

      repeat-x:图像会重复以覆盖整个背景区域的横轴,图像可能会被裁剪,仅供单值语法使用。 repeat-y:图像会重复以覆盖整个背景区域的纵轴,图像可能会被裁剪,仅供单值语法使用。 repeat:默认,图像会重复以覆盖整个背景区域,图像可能会被裁剪。 space:图像会尽可能的重复, 但是不会裁剪,图像之间可能会留有间隙。 round:图像会重复以覆盖整个背景区域,所有图像都会被放入如背景区域,可能导致图像变形。 no-repeat:图像不会重复。

  9. background-attachment:设置背景图像的位置是在视口内固定,还是随着包含它的区块滚动,为多重背景设置时用逗号分隔。

    • scroll:背景相对于元素固定。
    • fixed: 背景相对于视口固定。
    • local:背景相对于元素内容固定。
  10. background-blend-mode:设置一个元素拥有多个背景图片和背景颜色时如何混合。

    • normal:默认值。设置正常的混合模式。
    • multiply:正片叠底模式。
    • screen:滤色模式。
    • overlay:叠加模式。
    • darken:变暗模式。
    • lighten:变亮模式。
    • color-dodge:颜色减淡模式。
    • color-burn
    • hard-light
    • soft-light
    • difference
    • exclusion
    • hue
    • saturation:饱和度模式。
    • color:颜色模式。
    • luminosity:亮度模式。

弹性盒子

概述

图中是一个 flex-direction 属性为 row 的弹性容器,意味着其内的弹性项目将根据既定书写模式沿主轴水平排列, 其方向为元素的文本流方向,在这个例子里,为从左到右。

  • 弹性盒子容器:用display="flex"定义弹性盒子的容器
  • 弹性盒子项目:弹性盒子容器的子元素称为弹性盒子项目
  • :弹性盒子有两个轴,主轴和侧轴,默认水平方向为主轴,即flex-direction="row"
  • 轴起点:默认主轴轴起点从左到右,侧轴从上到下,即flex-direction="row"

容器属性

  1. flex-direction:定义主轴方向。

    参数:

    • row:默认指,主轴为水平方向,从左到右。
    • row-reverse:主轴为水平方向,从右到左。
    • column:主轴为竖直方向,从上到下。
    • column-reverse:主轴为竖直方向,从下到上。
  2. flex-wrap:容器内容在一行排列溢出时,如何换行。

    • nowrap:默认值,不换行,这可能导致内容溢出。

    • wrap:换行,第一行在上方。

    • wrap-reverse:换行,第一行在下方。

  3. flex-flow: 1, 2:复合属性,默认值为 flex-flow: rwo nowarp

  4. justify-content:定义容器内容在主轴上的对其方式。

    • flex-start:默认值,在主轴方向的开头对齐。
    • flex-end:在主轴方向的末尾对齐。
    • center:在主轴居中对齐,第一个内容和最后一个内容与容器开头和结尾的间距相同。
    • space-between:第一个元素与主轴方向开头对齐,最后一个元素与主轴方向末尾对齐,元素之间保留相等间距。
    • space-around:元素之间保留相等间距。
  5. align-items:定义容器内容在侧轴上的对其方式。

    • flex-start:在侧轴方向的开头对齐。
    • flex-end:在侧轴方向的末尾对齐。
    • center:在侧轴居中对齐,第一个内容和最后一个内容与容器开头和结尾的间距相同。
    • stretch:默认值,如果项目未设置高度或设为auto,将占满整个容器的高度。
    • baseline:以内容的的第一行文字的基线对齐。
  6. align-content:定义多根轴线的对齐方式,如果项目只有一根轴线,该属性不起作用。

    • flex-start:与交叉轴的起点对齐。
    • flex-end:与交叉轴的终点对齐。
    • center:与交叉轴的中点对齐。
    • stretch:默认值,轴线占满整个交叉轴。
    • space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。
    • space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。

项目属性

  1. order:定义项目的排列顺序。数值越小,排列越靠前,默认为0。

  2. flex: 3,4,5:复合属性,默认值为 0 1 auto。后两个属性可选。建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。

  3. flex-grow:定义项目的放大比例,默认为0,此时即使存在剩余空间,也不放大。

    如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。

  4. flex-shrink:定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

    如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。负值对该属性无效。

  5. flex-basis:定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。

  6. align-self:允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。该属性可能取6个值,除了auto,其他都与align-items属性完全一致。

定位属性

  1. position:指定元素在文档中的定位方式。
    • static:默认,元素使用正常定位方式,此时toprightbottomleftz-index无效。
    • relative:元素使用相对定位方式,相对于正常位置定位,会为元素保留正常位置的空间(即在使用top等定位属性时会在元素的正常位置留下空白)。
    • absolute:元素使用相对定位,相对于第一个 position 属性不是 static 的父元素定位,不会为元素保留空间。
    • fixed:元素使用相对定位,相对于屏幕的视口定位,不会为元素保留空间。当元素祖先的 transformperspectivefilter属性不是none时,容器由视口改为该祖先。
    • sticky:元素使用相对定位,相对于最近的滚动祖先,不会为元素保留空间。
  2. z-index:相对定位元素重叠时,设置元素的堆叠顺序。
    • auto:默认,堆叠顺序与父元素相同。
    • number:整数,值越大堆叠层级越高。
  3. top:使用相对定位的元素,相对于其默认位置顶部的偏移量。
    • auto:默认,根据HTML默认规则。
    • length:使用长度定义偏移距离。
    • %:使用百分比定义偏移量,百分比高度参照包含块的高度。
  4. right:使用相对定位的元素,相对于其默认位置右边的偏移量。
    • auto:默认,根据HTML默认规则。
    • length:使用长度定义偏移距离。
    • %:使用百分比定义偏移量,百分比高度参照包含块的宽度。
  5. bottom:使用相对定位的元素,相对于其默认位置顶部的偏移量。
    • auto:默认,根据HTML默认规则。
    • length:使用长度定义偏移距离。
    • %:使用百分比定义偏移量,百分比高度参照包含块的高度。
  6. left:使用相对定位的元素,相对于其默认位置左边的偏移量。
    • auto:默认,根据HTML默认规则。
    • length:使用长度定义偏移距离。
    • %:使用百分比定义偏移量,百分比高度参照包含块的宽度。

布局属性

  1. display:定义元素的类型(块级元素和行内元素)和定义其子元素的布局(flexgrid)。
    • none:隐藏对象,且不为被隐藏的对象保留其物理空间。
    • inline:默认,定义元素为行内元素。
    • block:定义元素为块级元素。
    • inline-block:定义元素为行内块元素。
    • flex:定义元素为 flex 容器。
    • inline-flex:定义元素为行内块级 flex 容器。
    • grid:定义元素为 grid 容器。
    • list-item:定义元素为列表项目,相当于标签 <li>
    • run-in:指定元素根据上下文作为块级元素或行内元素。
    • table:指定元素作为块级元素的表格,相当于标签 <table>
    • inline-table:指定元素作为行内元素的表格,相当于标签 <table>
    • table-caption:指定元素作为表格标题,相当于标签 <caption>
    • table-row:指定元素作为表格行,相当于标签 <tr>
    • table-column:指定元素作为表格列,相当于标签 <col>
    • table-cell:指定元素作为表格单元格,相当于标签 <td><th>
    • table-row-group:指定元素作为表格行组,相当于标签 <tbody>
    • table-column-group:指定元素作为表格列组显示,相当于标签 <colgroup>
    • table-header-group:指定元素作为表格标题组,相当于标签 <thead>
    • table-footer-group:指定元素作为表格脚注组,相当于标签 <tfoot>
  2. float:定义元素为浮动布局。当 displaynone 或元素是绝对定位时,float 不生效。
    • none:默认,不浮动。
    • left:元素向左浮动。
    • right:元素向右浮动。
  3. clear:指定元素的哪边不允许出现浮动元素。
    • none:默认,元素两边都可以出现浮动元素。
    • left:元素左边不允许出现浮动元素。
    • right:元素右边不允许出现浮动元素。
    • both:元素两边都不允许出现浮动元素。
  4. visibility:显示或隐藏元素,且不改变文档的布局
    • visible:默认,显示元素。
    • hidden:隐藏元素,会为其保留空间。
    • collapse:用于 <table> 的行或者列时,与 display:none 效果一样,此时不保留隐藏项目的空间。对于其他元素与 hidden 相同。

列表属性

  1. list-style: 2 3:复合属性。
  2. list-style-image:将图片作为列表项标记。
    • none:不使用图像,使用 list-style-type 指定的列表项标记。
    • url():使用url()指定的图像作为列表项标记,若图像不可用则使用list-style-type指定的列表项标记。
  3. list-style-position:设置列表项标记的位置。
    • outside:标记在主块盒的外面,默认。
    • inside:标记在主块盒内部。
  4. list-style-type:设置列表标记项的样式。
    • none:不使用项目符号
    • disc:实心圆
    • circle:空心圆
    • square:实心方块
    • decimal:阿拉伯数字
    • lower-roman:小写罗马数字
    • upper-roman:大写罗马数字
    • lower-alpha:小写英文字母
    • upper-alpha:大写英文字母
    • armenian:传统的亚美尼亚数字
    • cjk-ideographic:大写中文
    • georgian:传统的乔治数字
    • lower-greek:基本的希腊小写字母
    • hebrew:传统的希伯莱数字
    • hiragana:日文平假名字符
    • hiragana-iroha:日文平假名序号
    • katakana:日文片假名字符
    • katakana-iroha:日文片假名序号
    • lower-latin:小写拉丁字母
    • upper-latin:大写拉丁字母

表格属性

  1. table-layout:设置表格的布局,<table> 属性。
    • auto:采用自动表格布局,表格和表格单元的宽度取决于包含的内容,默认。
    • fixed:表格和表格单元的宽度取决于第一行单元的宽度。
  2. border-collapse:表格单元格的边框是分开还是合并,<table>属性。
    • separate:表格表格单元格的边框分开,默认。
    • collapse:表格单元格的边框的边框合并。
  3. border-spacing:指定表格单元格边框间的距离,只有表格单元格的边框是分开的时才有效,<table>属性。
    • length:设置表格单元格水平和垂直的距离。
    • width height:分别设置表格单元格水平和垂直的距离。
  4. caption-side:设置表格标题<caption>的位置。
    • top:标题在表格上方,默认。
    • bottom:标题在表格下方。
  5. empty-cells:当表格单元格没有内容时,是否显示空单元格,<table>属性。
    • show:显示,默认。
    • hide:隐藏。

2D转换属性

  1. transform :将元素旋转、缩放、移动、倾斜等,横轴为 x轴,纵轴为 y轴 ,坐标的交点默认是元素的中心。
    • matrix(n, n, n, n, n, n):将元素旋转,缩放,平移。详情略去。
    • translate(x, y):以元素左上角为起点,沿着 x轴y轴 移动指定像素距离,如:translate(50px, 50px)
    • translateX(n) :以元素左上角为起点,沿着 x轴 移动指定像素距离,如:translateX(50px)
    • translateY(n) :以元素左上角为起点,沿着 y轴 移动指定像素距离,如:translateY(50px)
    • scale(x, y):以坐标轴交点为放大点,将元素在的 x轴 的长度各扩大 x 倍,将元素在的 y轴 的长度扩大 y 倍。xy 可以是小数点,如:scale(0.5, 2)
    • scaleX(n):以坐标轴交点为放大点,将元素在的 x轴 长度扩大 n 倍。
    • scaleY(n):以坐标轴交点为放大点,将元素在的 y轴 长度扩大 n 倍。
    • rotate(angle):以坐标轴交点为旋转点,以指定的度数顺时针旋转元素,如:rotate(45deg)
    • skew(x-angle, y-angle):表示 x轴y轴 的倾斜角度,正值表示逆时针,负值表示顺时针。
    • skewX(angle):值为正时, x轴 轴不动,y轴 沿逆时针倾斜之情角度;值为负时, x轴 轴不动,y轴 沿顺时针倾斜之情角度
    • skewY(angle):值为正时, y轴 轴不动,x轴 沿逆时针倾斜之情角度;值为负时, y轴 轴不动,x轴 沿顺时针倾斜之情角度
  2. transform-Origin:x y :更改转换元素的位置,即定义 x轴y轴 的交点位置,默认是元素的中点(即 center center)。
    • xleftcenterrightlength%
    • ytopcenterbuttomlength%

注意:可以认为 x轴 的长度与元素的宽相等,y轴 的长度与元素的高相等。

3D转换属性

  1. transform
    • matrix3d() :将元素在 3D 空间中旋转,缩放,平移。详情略去。
    • translate3d(x, y, z) :以元素左上角为起点,沿着 x轴y轴 移动指定像素距离,如:translate3d(50px, 50px, 50px)
    • translateX(x) :以元素左上角为起点,沿着 x轴 移动指定像素距离。
    • translateY(y) :以元素左上角为起点,沿着 y轴 移动指定像素距离。
    • translateZ(z) :以元素左上角为起点,沿着 z轴 移动指定像素距离。
    • scale3d(x, y, z) :以坐标轴交点为放大点,将元素在的 x轴 的长度各扩大 x 倍,将元素在的 y轴 的长度扩大 y 倍,将元素在的 z轴 的长度扩大 z 倍,xyz 可以是小数点,如:scale(0.5, 2, 1)
    • scaleX(n) :以坐标轴交点为放大点,将元素在的 x轴 长度扩大 n 倍。
    • scaleY(n) :以坐标轴交点为放大点,将元素在的 y轴 长度扩大 n 倍。
    • scaleZ(z) :以坐标轴交点为放大点,将元素在的 z轴 长度扩大 n 倍。
    • rotate3d(x, y, z, angle) :3D 旋转。
    • rotateX(angle) :沿 x轴 的 3D 旋转,正值向内旋转,负值向外旋转。。
    • rotateY(angle) :沿 y轴 的 3D 旋转,正值顺时针旋转,负值逆时针旋转。
    • rotateZ(angle) :沿 z轴 的 3D 旋转,正值顺时针旋转,负值逆时针旋转。
  2. transform-origin: x y z :更改转换元素的位置,即定义 x轴y轴 的交点位置,默认是元素的中心。
    • xleftcenterrightlength%
    • ytopcenterbuttomlength%
    • zlength
  3. transform-style :被嵌套元素在 3D 空间中怎样显示。
    • flat :所有子元素在 2D 平面呈现。
    • preserve-3d :所有子元素在 3D 空间中呈现。
  4. perspective :规定 3D 的透视效果。
    • number :元素距离视图的距离,以像素计。
    • none :默认值,与 0 相同,即不设置透视。
  5. perspective-origin: x y :规定 3D 元素的底部位置。
    • x :定义视图在 x轴 上的位置。默认为 50% 。可取 leftcenterrightlength%
    • y :定义视图在 y轴 上的位置。默认为 50% 。可取 topcenterbottomlength%
  6. backface-visibility :定义元素在不面对屏幕时是否可见。
    • vidible :背面是可见的。
    • hidden :背面是不可见的。

导航属性和光标属性

  1. nav-index:设置tab键导航的顺序
    • auto:浏览器决定元素导航顺序
    • number:数字,小的顺序靠前
  2. nav-down:设置tab键向下导航的方向。
    • auto:浏览器决定导航到哪个元素
    • id:规定被导航元素的id
  3. nav-left:设置tab键时向左导航的方向。
  4. nav-up:设置tab键时向上导航的方向。
  5. nav-right:设置tab键时向右导航的方向。
  6. cursor:设置鼠标在元素上时的光标的形状。
    • url():外部资源,自定义光标的形状。
    • default:默认,通常是一个箭头。
    • auto:浏览器设置的光标。
    • crosshair:十字线
    • pointer:链接的指针(一只手)
    • move:此光标指示某对象可被移动
    • e-resize:此光标指示矩形框的边缘可被向右(东)移动
    • ne-resize:此光标指示矩形框的边缘可被向上及向右移动(北/东)
    • nw-resize:此光标指示矩形框的边缘可被向上及向左移动(北/西)
    • n-resize:此光标指示矩形框的边缘可被向上(北)移动
    • se-resize:此光标指示矩形框的边缘可被向下及向右移动(南/东)
    • sw-resize:此光标指示矩形框的边缘可被向下及向左移动(南/西)
    • s-resize:此光标指示矩形框的边缘可被向下移动(北/西)
    • w-resize:此光标指示矩形框的边缘可被向左移动(西)
    • text:此光标指示文本
    • wait:此光标指示程序正忙(通常是一只表或沙漏)
    • help:此光标指示可用的帮助(通常是一个问号或一个气球)

计数器

  1. counter-reset: counter_name [start_value] :创建或者重置计数器。
    • counter_name:计数器的名字。
    • start_value:计数器的起始值,默认为0。
  2. counter-increment: counter_name [add_value]:递增计数器。
    • counter_name:计数器的名字。
    • add_value:计数器的增量,默认为1。
  3. content: value:与伪元素 ::before::after 配合使用,插入内容。
    • none:不插入任何内容。
    • counter():插入计数器的计数。
    • attr()
    • string:插入字符串。
    • url(url):插入媒体(图像、声音、视频等)。
    • inherit:从父属性继承插入内容。
  4. counter(counter_name [,counter_style]):返回计数器的值。
    • counter_name:计数器的名字。
    • counter_style:计数器的数字样式,可以是阿拉伯数字等。
  5. counters(counter_name [, string, counter_style]):返回嵌套计数器的值。
    • counter_name:计数器的名字。
    • string:连接嵌套计数的字符串。
    • counter_style:计数器的数字样式。

示例一 - 普通计数

<!--使用counter()-->
<div id="ex">
	<h5 class="one">动物</h5>
	<h6 class="two">大象</h6>
			
	<h5 class="one">昆虫</h5>
	<h6 class="two">蜘蛛</h6>
	<h6 class="two">蚂蚁</h6>
			
	<h5 class="one">植物</h5>
	<h6 class="two">杨树</h6>
	<h6 class="two">百合</h6>
    <h6 class="two">海藻</h6>
</div>
<style>
    #ex {/*在<div>元素下定义一个起始值为2的计数器one,用于计算<h5>出现的次数*/
        counter-reset: one 2;
	}
	.two {/*在<h6>元素下定义一个计数器,用于计算相邻的<h6>出现的次数*/
	    counter-reset: two;
	}
	.one::before {
	    counter-increment: one 2;/*计时器one每次递增2*/
		content: counter(one, upper-roman)"-";/*将计数器one的样式设为upper-roman样式,并加入到<h5>中*/
	}
	.two::before {
	    counter-increment: two;
		content: counter(one)"-"counter(two)"-";/*将计数作为<h6>的第一个子元素加入*/
	}
</style>
<!--注意,设置计数器时,计数器默认在元素断开时重新计数,若要计算不连续的元素,应把计数器放在它的父元素上。如示例中计算<h5>时计数器是放在父元素<div>上的。-->

示例二 - 嵌套计数

<!--使用counters()-->
<ul>
    <li>动物</li>
    <li>植物</li>
    <li>食物
        <ul>
            <li>玉米</li>
            <li>大米</li>
        </ul>
    </li>
    <li>鲜花</li>
    <li>水果
        <ul>
            <li>苹果</li>
            <li>呆瓜</li>
        </ul>
    </li>
</ul>
<style>
    ul {
        counter-reset: one;
    }
    li {
        counter-increment: one;
    }
    li::before {
        content: counters(one, "-")"+"
    }
</style>

动画属性

  1. @keyframes animationName {keyframes-selector {css-styles}}:创建一个动画

    animationName:动画的名字。

    keyframes-selector {css-styles}:动画持续时间的百分比keyframes-selector内的动画样式css-styles

  2. animation: animation-name | animation-duration |animation-timing-function | animation-delay |animation-iteration-count | animation-direction | animation-fill-mode | animation-play-state:复合属性,设置对象所应用的动画特效

  3. animation-name:设置对象所应用的动画名称 ,与@keyframes配合使用,动画名称由@keyframes定义。

  4. animation-duration:设置对象动画的持续时间。

  5. animation-timing-function:设置对象动画的延迟时间。

  6. animation-delay:设置对象动画的过渡类型。

    • ease:默认,由低到高,结束前变慢,平滑过渡。等同于贝塞尔曲线(0.25, 0.1, 0.25, 1.0)
    • linear:从开始到结束匀速,线性过渡。等同于贝塞尔曲线(0.0, 0.0, 1.0, 1.0)
    • ease-in:低速开始,由慢到快。等同于贝塞尔曲线(0.42, 0, 1.0, 1.0)
    • easw-out:低速结束,由快到慢。等同于贝塞尔曲线(0, 0, 0.58, 1.0)
    • ease-in-out:由慢到快再到慢。等同于贝塞尔曲线(0.42, 0, 0.58, 1.0)
    • step-start:等同于 steps(1, start)
    • step-end:等同于 steps(1, end)
    • steps(<integer>[, [ start | end ] ]?):接受两个参数的步进函数。第一个参数必须为正整数,指定函数的步数。第二个参数取值可以是start或end,指定每一步的值发生变化的时间点。第二个参数是可选的,默认值为end。
    • cubic-bezier(n, n, n, n):特定的贝塞尔曲线类型,4个数值需在[0, 1]区间内。
  7. animation-iteration-count:设置对象动画的循环次数。

    • n:有限次
    • infinite:无限次
  8. animation-direction:设置对象动画在循环中是否反向运动。

    • normal:默认,正常播放
    • reverse:反向播放
    • alternate:奇次正向,偶次反向
    • alternate-reverse:奇次反向,偶次正向
  9. animation-fill-mode:设置对象动画的状态,如鼠标点中时动画停止等。

    • paused:指定暂停动画
    • running:指定正在运行的动画
  10. animation-play-state:设置对象动画时间之外的状态。

    • none:默认值。不设置对象动画之外的状态
    • forwards:设置对象状态为动画结束时的状态
    • backwards:设置对象状态为动画开始时的状态
    • both:设置对象状态为动画结束或开始的状态

示例

<div id = "app">
    <span></span>
</div>
<style>
    #app {
        height: 50px;
        line-height: 50px;
    }
    #app span {
        display: inline-block;
        width: 20px;
        height: 20px;
        background: blue;
        position: relative;
    }
    @keyframes ex { /*定义动画*/
        0% {left:0%} /*动画持续时间百分之0时的样式*/
        50% {left: 5%; background: yellow}
        100% {left: 10%}
    }
    #app span { /*将动画ex应用到<span>元素上,并设置属性*/
        animation: ex 5s 2s linear infinite alternate both;
    }
    #app span:hover{ /*当鼠标悬指是停止动画*/
        animation: paused;
    }
</style>

过渡属性

概述:当元素的样式改变时的过渡效果。

  1. transition: 2,3,4,5 :复合属性。
  2. transition-property:指定应用过渡的 CSS 属性的名称。
  3. transition-duration:定义过渡效果花费的时间。默认为 0 ,此时没有过渡效果。
  4. transition-timing-function:定义过渡效果的时间曲线。
    • linear:匀速,等于 cubic-bezier(0, 0, 1, 1)
    • ease:由慢到快再到慢,等于 cubic-bezier(0.25, 0.1, 0.25, 1)
    • ease-in:慢速开始,等于 cubic-bezier(0.42, 0, 1, 1)
    • ease-out:慢速结束,等于 cubic-bezier(0, 0, 0.58, 1)
    • ease-in-out:慢速开始和结束,等于 cubic-bezier(0.42, 0, 0.58, 1)
    • cubic-bezier(n, n, n, n):贝塞尔曲线,详情略。
  5. transition-delay:定义过渡效果开始的时间,默认为 0 ,即立即开始。

示例

<!DOCTYPE >
<html>
	<head>
		<meta charset="utf-8" />
		<style>
		    .tran {
			    height:20px;
				width:40px;
				margin: 5px;
				border: 1px solid;
                transition: width 3s ease  1s, background 3s linear 1s;
			}
/*transition即可以放在过渡前的样式里面,也可以放在过渡后的样式里面,两边都有时以过渡后的为准*/
/*示例中one的过渡效果,以#one样式中的为准,two的以.tran样式中的为准*/
			#one:hover {
                /*悬浮在one上开启one的过渡效果*/
			    width: 200px;
				background: blue;
				transition: width 3s ease 1s, background 3s linear 1s;
			}
		</style>
	</head>
	<body>
	    <div class="tran" id="one">one</div>
		<div class="tran" id="two">two</div>
        <!--点击开启two过渡效果-->
		<button onclick="addStyle()">点击</button>
	</body>
<script>
    let two = document.getElementById("two")
	function addStyle(){
	    two.style.background = "red"
		two.style.width = "200px"
	}
</script>
</html>

媒体查询

语法

  1. 普通语法

    @media mediatype and | not | only (media feature) {CSS-Code}
    
  2. 使用媒体查询选择外联CSS样式表语法

    <link rel="stylesheet" media="mediatype and|not|only (media feature)" href="mystylesheet.css">
    
  3. 参数

    mediatype:媒体类型

    • all:所有设备。
    • print:打印机。
    • screen:显示屏。
    • speech:屏幕阅读器等发声设备。

    and | not | only:逻辑连接符。

    media feature:媒体特征,只有显示页面的媒体符合媒体特征才会应用当前媒体查询下的样式。

    • aspect-ratio:视窗(viewport)的宽高比,它是一个范围比,所以还可以使用前缀min-aspect-ratiomax-aspect-ratio来进行最大最小值查询。
    • orientation:视窗(viewport)的旋转方向,值为:portrait表示视窗处于纵向,即高度大于等于宽度;landscape表示视窗处于横向,即宽度大于高度。
    • height:视窗(viewport)的高度,包括横向滚动条的高度,它是一个范围值,所以可以使用前缀min-heightmax-height查询最小值和最大值。
    • width:视窗(viewport)的宽度,包括纵向滚动条的宽度,它是一个范围值,所以可以使用前缀min-widthmax-width查询最小值和最大值。
    • resolution:输出设备的像素密度(分辨率)。
    • scripting:探测脚本(例如 JavaScript)是否可用。
    • any-hover
    • any-pointer
    • color
    • color-index
    • display-mode
    • forced-colors
    • grid
    • hover
    • inverted-colors
    • light-level
    • monochrome
    • overflow-block
    • overflow-inline
    • pointer
    • prefers-color-scheme:探测用户是否倾向于选择亮色或者暗色的配色方案。
    • prefers-contrast:探测用户是否有向系统要求提高或降低相近颜色之间的对比度。
    • prefers-reduced-motion:用户是否希望页面上出现更少的动态效果。
    • prefers-reduced-transparency:用户是否倾向于选择更低的透明度。
    • scan:输出设备的扫描过程(适用于电视等)。
    • update:输出设备更新内容的渲染结果的频率。

链接

<!--iframe_ex1.html-->
<!DOCTYPE html>
<html lang="en">
  <head>
	<style>
      /*当视口宽度大于170px时,背景颜色为yellow*/
	  @media screen and (min-width: 170px) { div { background: yellow; } }
      /*当视口宽度大于140px小于170px时,背景颜色为pink*/
	  @media screen and (min-width: 140px) and (max-width: 170px) { div { background: pink; } }
      /*当视口宽度小于140px时,背景颜色为blue*/
	  @media screen and (max-width: 140px) { div { background: blue; } }    
	</style>
  </head>
  <body>
    <div>i am iframe</div>
  </body>
</html>
<!--index.html-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
  </head>
  <body>
    <label id="wl" for="w">width:200</label>
	<input id="w" type="range" min="100" max="200" step="5" value="150">
	<iframe id="iframe" src="iframe.html" style="width:200px; height:60px" >
	</iframe>
    <script>
	    const wl = document.getElementById("wl")
		const w = document.getElementById("w")
		const iframe = document.getElementById("iframe")
		w.addEventListener("input", function(){
		    wl.innerHTML = "width:" + w.value
			iframe.style.width = w.value + "px"
		})
	</script>
  </body>
</html>

CSS 布局

响应式布局

响应式布局就是一个网站能够兼容多个终端,可以根据屏幕的大小自动调整页面的的展示方式以及布局,我们不用为每一个终端做一个特定的版本。响应式网站的几个标志:

  1. 同时适配PC + 平板 + 手机等;

  2. 标签导航在接近手持终端设备时改变为经典的抽屉式导航;

  3. 网站的布局会根据视口来调整模块的大小和位置;

  4. 如图:

自适应布局

自适应布局是指网页能够在不同大小的终端设备上自行适应显示,也就是让一个网站在不同大小的设备上显示同一样的页面,让同一个页面适应不同大小屏幕,根据屏幕的大小,自动缩放。自适应布局的几个标志:

  1. 大多只是适配单个终端的主流N个主流视口;

  2. 当视口大小低于设置的最小视口时,界面会出现显示不全,并且出现横向滑动条;

  3. 总体框架不变,横线布局的版块太多会有所减少。

  4. 如图

移动端适配流程

  1. <head> 设置 width=device-widthviewport
  2. 在 css 中使用 px。
  3. 在适当的场景使用 flex 布局,或者配合 vw 进行自适应。
  4. 在跨设备类型的时候使用媒体查询。
  5. 在跨设备类型如果交互差异太大的情况,考虑分开项目开发。

屏幕适配

概念
  1. 英寸:屏幕对角线的长度,1英寸=2.54厘米1英寸=2.54厘米

  2. 像素:像素是一个小方块,具有特定的位置和颜色。

  3. 屏幕分辨率:一个屏幕由多少个像素点组成,如 720360720*360 指屏幕垂直每列有720个像素点,水平每行360个像素点。

  4. 图像分辨率:指图片有多少个像素点组成,如 10080100*80 指图像垂直每列100个像素点,水平每列80个像素点。

  5. PPI:每英寸包含的像素数。计算方法为:

    PPI=水平像素点2+垂直像素点2屏幕尺寸PPI=\frac{\sqrt{水平像素点数^2+垂直像素点数^2}}{屏幕尺寸}
  6. DPI:每英寸包含的点数,这个点数可以是像素点,也可以是打印机的墨点。在使用DPI描述屏幕和图片时DPI一般和PPI等价,DPI更常用于描述打印机,表示打印机每英寸可以打印的点数。

  7. 设备独立像素:在界面上显示的元素大小,简称DIPDP。设备独立像素是物理像素的集合,比如一个屏幕的一个独立像素包含10个物理像素,那么一张当这块屏幕渲染图片的时候就用会10个物理像素去渲染图片的一个像素,可以看到独立像素越高显示的图像越清晰。

    计算公式是:

    设备独立像素=物理像素设备像素比设备独立像素=\frac{物理像素}{设备像素比}

    设备的独立像素比可以用 window.devicePixelRatio 查看。

    在chrome开发工具中选择 iPhone X 显示的尺寸是 375812375*812 就是设备独立像素(它的物理像素要远大于这个数字)。

  8. px:CSS里面的 px 指的是设备独立像素,在设备像素比高的屏幕上会用多个像素点渲染 1px1px 问题也是由此来。

  9. 设备像素比:物理像素和设备独立像素的比值(device pixel ratio),简称DPR

    web中,浏览器提供了 window.devicePixelRatio 来获取 dpr

    css中,可以使用媒体查询 min-device-pixel-ratio 来区分 dpr,如:

    @media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2){ }
    
  10. 设计像素:一般情况下屏幕的物理像素的两个值与设备独立像素的两个值并不相应成比例,如iPhone8物理像素为 108019201080*1920 ,设备独立像素为 414736414*736 ,设备像素比为3,但 3[414736]3*[414*736] 却等于 124222081242*2208 ,这个 124222081242*2208 就是设计像素,这个手机内部机制会处理,它们把 124222081242*2208 个像素点塞进 108019201080*1920 个物理像素点来渲染,开发的过程中也是以这个设计像素为准,即可以放心使用设备像素比这个指标。

  11. 视口(viewport):表示当前可见的计算机图形区域,在浏览器中通常与浏览器的窗口相同,但不包括菜单栏等(只包括浏览的文档那一部分)。

  12. 布局视口(layout viewport):当我们以百分比来指定一个元素的大小时,它的计算值是由这个元素的包含块计算而来的,当这个元素是最顶级的元素时,就是根据视口来计算的。

    布局视口是网页布局的基准窗口,布局视口就等于当前浏览器的窗口大小(不包括bordersmargins、滚动条)

    在移动端,布局视口被赋予一个默认值,大部分是980px,这保证pc的网页可以在手机浏览器上呈现,但非常小。

  13. 视觉视口(visual viewport):用户通过屏幕真实看到的区域,视觉视口默认等于当前浏览器的窗口大小(包括滚动条)。当用户对浏览器进行缩放时,不会改变布局视口的大小,所以布局是不变的,但缩放会改变视觉视口的大小。

    例如:用户将浏览器窗口放大了200%,这时浏览器窗口中的CSS像素会随着视觉视口放大,这时一个CSS像素会跨越更多的物理像素。

  14. 理想视口(ideal viewport):网站页面在移动端展示的理想大小。在浏览器调试移动端时页面上给定的像素大小就是理想视口大小,它的单位是设备独立像素。理想视口与屏幕挂钩,不会改变。

  15. 页面缩放系数:在CSS中,常用单位px(即CSS像素)中,当页面缩放比例为100%时,1px等于一个设备独立像素。但是CSS像素很容易改变,对用户对浏览器进行了放大,CSS像素就会被放大,这时一个CSS像素会跨越更多的物理像素。

    页面的缩放系数 = CSS像素 / 设备独立像素

    当页面缩放比例为100%时,CSS像素 = 设备独立像素,理想视口 = 视觉视口

    页面的缩放系数 = 理想视口宽度 / 视觉视口宽度

开发方案
  1. <meta>:元数据信息,可以借助它的viewport属性来设置视口、缩放等,让移动端得到更好的展示效果。如:

    <meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">
    <!--
    width:正整数或device-width,以pixels(像素)为单位,定义布局视口的宽度。
    height:正整数或device-height,以pixels(像素)为单位, 定义布局视口的高度。
    initial-scale:取值0.0 - 10.0,定义页面初始缩放比率。
    minimum-scale:取值0.0 - 10.0,定义缩放的最小值;必须小于或等于maximum-scale的值。
    maximum-scale:取值0.0 - 10.0,定义缩放的最大值;必须大于或等于minimum-scale的值。
    user-scalable:一个布尔值(yes或者no),如果设置为 no,用户将不能放大或缩小网页。默认值为 yes。
    -->
    
  2. 移动端适配:为了在移动端让页面获得更好的显示效果,必须让布局视口、视觉视口都尽可能等于理想视口。

    device-width就等于理想视口的宽度,所以设置 width=device-width 就相当于让布局视口等于理想视口。

    由于initial-scale = 理想视口宽度 / 视觉视口宽度,所以我们设置initial-scale=1;就相当于让视觉视口等于理想视口。

    这时,1个CSS像素就等于1个设备独立像素,而且我们也是基于理想视口来进行布局的,所以呈现出来的页面布局在各种设备上都能大致相似。

    注意:布局视口会取理想视口和视觉视口的最大值。

  3. 获取浏览器的大小

    • window.innerHeight:获取浏览器视觉视口高度(包括垂直滚动条)。

    • window.outerHeight:获取浏览器窗口外部的高度。表示整个浏览器窗口的高度,包括侧边栏、窗口镶边和调正窗口大小的边框。

    • window.screen.Height:获取获屏幕取理想视口高度,这个数值是固定的,`设备的分辨率/设备像素比

    • window.screen.availHeight:浏览器窗口可用的高度。

    • document.documentElement.clientHeight:获取浏览器布局视口高度,包括内边距,但不包括垂直滚动条、边框和外边距。

    • document.documentElement.offsetHeight:包括内边距、滚动条、边框和外边距。

    • document.documentElement.scrollHeight:在不使用滚动条的情况下适合视口中的所有内容所需的最小宽度。测量方式与clientHeight相同:它包含元素的内边距,但不包括边框,外边距或垂直滚动条。

    • 如图

  4. 适配方案:

    vh、vw方案:详情见响应式与自适应。

1px问题

在设备像素比DPR大于1的屏幕上,用1px实现一条一像素的线时,屏幕会使用用于1个物理像素的像素去渲染,使1px像素的线看上去略粗。比如在DPR=2的屏幕上实现1px像素的线,其css应设置为0.5px,但这在安卓系统上无法实现。

解决方案:

  1. border-image:将边框设置为1px透明,找一个2px的图片作为边框(上部1px为透明色,下部1px为需要的颜色),这样在DPR=2的屏幕中,使用两个像素渲染时图片边框时,由于一个像素是透明色,看起来就只剩了不透明的,间接达到了1px线框。例:

    .class{  //正常屏幕的下边框
        border-bottom: 1px solid #000;
    }
    //使用媒体查询,给PDR=2的屏幕使用图片边框
    @media only screen and (-webkit-min-device-pixel-ratio:2){
        .class{
            //设置下边框为1px,颜色为透明
            border-bottom: 1px solid transparent;
            //设置下边框图片,即图片重复方式
            border-image: url('./1px.png') 0 0 2 0 repeat;
        }
    }
    

    注:这种方法修改线框颜色麻烦,线框圆角处理麻烦。

  2. svg:使用svg图片代替border-image中的图片。例:

    .class { border: 1px solid transparent; border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='2px'%3E%3Crect fill='yellow' width='100%25' height='50%25'/%3E%3C/svg%3E") 2 2 stretch; }
    
  3. box-shadow:利用阴影处理模拟0.5px效果,几乎可以满足所有场景,但边框有阴影,颜色变浅。

    .class {
      box-shadow: inset 0px -1px 1px -1px #c8c7cc;
    }
    
  4. 伪类 + transform:原理是把原先元素的 border 去掉(假如有的话),然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。例:

    .class{
      position: relative;
      border:none;
    }
    .class:before{
        content: '';
        position: absolute;
        top: 0;
        height: 1px;
        width: 100%;
        background-color: #000;
        transform-origin: 50% 0%;
    }
    @media only screen and (-webkit-min-device-pixel-ratio:2){
        .class:before{
         transform: scaleY(0.5);
        }
    }
    @media only screen and (-webkit-min-device-pixel-ratio:3){
        .class:before{
            transform: scaleY(0.33);
        }
    }
    
  5. 通过设置缩放,让CSS像素等于正在的物理像素。例如,当设备DPR=3时,将页面缩放1/3倍,这时1px等于一个真正的屏幕像素。

    当DPR = 2时:

    <meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
    

    当DPR = 3时:

    <meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">
    

移动端适配示例

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
    <!--将布局视口宽度等于理想视口宽度,视觉视口等于理想视口-->
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>响应式布局</title>
	<style>
		* {
			margin: 0;
			padding: 0;
		}
		#main {
			width: 750px;
			margin: 0 auto;
			background-color: #f7f7f7;
		}
		#header #nav {
			height: 40px;
			line-height: 40px;
		}
		#header #menu {
			float: right;
			display: none;
			padding: 0 20px 0 0;
		}
		#header ul{
			float: right;
		}
		#header li {
			float: left;
			list-style-type: none;
			padding: 0 10px;
		}
		#header h3 {
			text-align: center;
			padding: 0 0 15px;
		}
		#content {
			display: flex;
			flex-flow: row wrap;
		}
		#content img {
			width: 230px;
			flex-grow: 1;
			padding: 5px 5px;
			border-radius: 5px;
		}
		#footer {
			padding: 20px 0 10px;
			text-align: center;
			font-size: 12px;
			color: #cccccc;
		}

		@media screen and (max-width: 750px) {
			#main {
				width: 95%;
			}
		}
        /*当屏幕宽度小于425px时应用媒体查询*/
		@media screen and (max-width: 425px) {
			#main {
				width: 95%;
			}
			#header #menu {
				display: inline;
			}
			#header ul {
				display: block;
				width: 95%;
				position: absolute;
				top: -200px;
				z-index: 10;
				background-color: #f7f7f7;
			}
			#header li {
				text-align: center;
				width: 100%;
				padding: 0;
			}
		}
		
	</style>
</head>

<body>
	<div id="main">
		<div id="header">
			<div id="nav">
				<ul>
					<li>首页</li>
					<li>日记</li>
					<li>周记</li>
					<li>月记</li>
					<li>笔记</li>
				</ul>
				<span id="menu">菜单</span>
			</div>
			<h3>响应式布局</h3>
		</div>
        <!--content采用弹性布局-->
		<div id="content">
			<img src="001.jpg">
			<img src="002.jpg">
			<img src="003.jpg">
			<img src="004.jpg">
			<img src="005.jpg">
			<img src="007.jpg">
		</div>
		<div id="footer">
			<a>aioverg</a>
		</div>
	</div>
</body>
<script>
    let menu = document.getElementById("menu")
	let nav_ul = document.getElementById("nav").getElementsByTagName("ul")[0]
	menu.addEventListener("click", display)
	nav_ul.addEventListener("click", hidden)
	function display(){
		let top = -200
		for(top; top<=0; top+=0.5)
		nav_ul.style.top = top + "px"
	}
	function hidden(){
		nav_ul.style.top = -200 + "px"
	}

</script>

</html>

JavaScript

JavaScript 是一门跨平台、面向对象的脚本语言,它使网页可交互。

Class 类

  1. 类默认使用严格模式。
  2. 不存在变量提升,即不能在类声明前使用类。

基本内容

  1. new 关键字

    创建类的实例,做了以下事情:

    1、创建一个空对象(即 {}

    2、为空对象添加属性 __proto__,将该属性指向构造函数的原型对象

    3、将创建的对象作为 this 的上下文,执行构造函数(为这个对象添加属性)。

    4、判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。

  2. class 关键字

    定义类,例:

    class one{
        a = "hello";
        b = "world";
        f = function(){console.log(this.a)};
        g = function(){console.log(this.b)}
    }
    var ex = new one  //创建实例
    ex.f()  //输出:hello
    ex.g()  //输出:world
    
  3. constructor 构造方法

    类的默认方法,通过 new 命令生成对象实例时,自动调用该方法。一个类必须有 constructor 方法,如果没有显示定义,JS 将默认创建一个空的 constructor 方法。

    constructor 方法默认返回实例对象(即 this ),也可以指定返回另外一个对象,例如:

    class one{
        constructor(){
            return Object.create(null)
            // 默认return Object.create(this)
      }
    }
    new one() instanceof one  // 输出:false
    // new one instanceof one  // 输出:true
    
  4. extends 继承

    继承父类,如:

    class parent {
        a = "hello";
        f = function(){console.log(this.a)}
    }
    class child extends parent {
        a = "world";
        g = function(){console.log(this.a)}
    }
    var ex = new child
    ex.f()  //输出:world
    ex.g()  //输出:world
    
  5. super关键字

    即可以作为函数使用也可以作为对象使用。

    当作为函数调用时,代表父类的构造函数。

    当作为对象时,在普通方法中指向父类的原型对象;在静态方法中指向父类。

  6. new.target 属性

    判断函数是否作为构造函数被调用。如:

    function Obj(){
        if(new.target){
            console.log('将我作为构造方法调用了')
        }else{
            console.log('将我作为普通方法调用了')
        }
    }
    

示例

  1. 创建类

    class One {  //类不存在变量提升
        args = null  //实例属性
        static a = 0  //类的静态属性,不会被类的实例继承
        constructor(args){//构造方法,每个类必须有
            this.args = args  //实例化时可以为属性args重新赋值
        }
        f(arg){ console.log(arg, this.args) }
        get g(){ console.log('get取值关键字')}
        set g(arg){ console.log('set存值关键字', arg) }
        static h(){console.log('静态方法')}  //类的静态方法,不会被类的实例继承,但能被子类继承
    }
    const ex1 = new One([1,2])  //创建One类的实例ex1
    ex1.args  //实例属性,重新赋值为[1, 2]
    ex1.f(1)  //使用实例方法
    One.prototype  //查询类的原型对象
    ex1.__proto__  //查询实例的原型对象
    One.prototype.constructor === One  //原型的constructor属性指向类本身
    One.prototype  ===  ex1.__proto__  //类的原型对象与实例的原型对象相等
    Object.keys(One.prototype)  //查询对象中所有可枚举属性的名字,类内部定义的方法都是不可枚举的,而ES5使用One.prototype.f = function(){}定义的方法是可枚举的。
    Object.getOwnPropertyNames(One.prototype)  //查询原型中所有的非继承的属性的名字
    ex1.hasOwnProperty('args')  //this定义的属性都是实例自身的属性,所以返回true
    ex1.hasOwnProperty('f')  //实例的方法定义在原型上,所以返回false,类的所有实例共享一个原型
    ex1.g  //调用get关键字定义的g(),输出:get取值关键字
    ex1.g = 33  //调用set关键字定义的g(),输出:set存值关键字
    
  2. 继承类

    class Two extends One {
        args = null  //父子同名属性父属性会被覆盖
        constructor(x, args){
            super(x)  //调用父类One的构造函数,每个继承的类必须有,super()做函数使用时指向父类的构造函数
            this.args = args
        }
        f(arg){  //父子同名方法父方法会被覆盖
            super.f(arg)  //调用父类中的f方法,super作为对象时,在普通方法中指向父类的原型对象,在静态方法中,指向父类。
            console.log(arg, this.args)
        }
    }
    const ex2 = new Two("One", "Two")  //创建One类的实例ex2
    Object.getPrototypeOf("Two")  //返回类Two的原型对象,可以判断Two是否继承自One
    Two.__proto__ === One  //子类的__proto__指向父类
    Two.prototype  //子类的原型对象
    Two.prototype.__proto__ === One.prototype  //子类的原型对象的原型对象指向父类的原型对象
    

构造函数

在 JS 中使用 new 关键字调用的函数就称为构造函数,任何函数都可以成为一个构造函数。

对象(实例):使用构造函数创建的对象(实例),例如:var a = new f()a 就是构造函数 f() 的一个对象(实例)。

构造函数与普通函数的区别

  1. 构造函数约定首字母大写。

  2. 调用方式不一样,构造函数使用 new 关键字调用,普通函数直接调用。

  3. 作用不一样,构造函数用于创建实例,以达到复用代码的作用。

  4. 构造函数使用 this 创建属性和方法,这样可以达到代码复用的目的,因为 this 会指向实例本身。

  5. 构造函数的执行流程:

    • 立即在堆内存中创建一个新的对象,这个对象就是构造函数的实例(构造函数的实例之间互不影响)。
    • 将新建的对象设置为函数中的 this
    • 逐个执行构造函数中的代码。
    • 将新建的对象作为返回值。
  6. 普通函数没有返回值,例:

    function f(){console.log("hello")}
    var fx=f()
    console.log(fx) //返回: "undefined"
    
  7. 构造函数会创建一个新对象,并将该对象作为返回值返回,例:

    function F(){console.log("hello")}
    var fx=new F()
    console.log(fx) //返回: F {}
    fx instanceof F //instanceof可以检查一个对象是否是一个类的实例。注意,所有的对象都是Object对象的实例。
    

对象

  1. 接受变量作为属性,如:

    const a = "hello"
    const obj = {a}  //等同于const obj = {a: "hello"}
    
  2. 接受函数作为方法,如:

    const obj = {
        a(){
            alert("hello")
        }
    }
    //等同于
    const obj = {
        a: function(){
            alert("hello")
        }
    }
    
  3. 表达式作为属性名:变量作为属性名时,需要用 [ ] 括起来,如:

    const a = "hello"
    const obj = { [a]: "a", ["wor"+"ld"]: "b" }
    obj //输出:{hello: "a", world: "b"}
    

属性的遍历

  1. for···in :遍历对象自身和继承的可枚举属性。

  2. Object.keys(obj):返回一个数组,包含对象自身(不包含继承的)的所有可枚举(不包含Symbol属性)属性的键名。

  3. Object.getOwnPropertyNames(obj) :返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,不包含继承的,但是包括不可枚举属性)的键名。

  4. Object.getOwnPropertySymbols(obj) :返回一个数组,包含对象自身的所有 Symbol 属性的键名。

  5. Reflect.ownKeys(obj) :返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。

    注意:以上属性遍历的次序准守一下规则:

    1. 首先遍历所有数值键,按照数值升序排列。
    2. 其次遍历所有字符串键,按照加入时间升序排列。
    3. 最后遍历所有 Symbol 键,按照加入时间升序排列。

super关键字:指向当前对象的原型对象。例如:

const one = {a: "hello"}
const two = {
    a: "world",
    f(){//简写方法
        console.log(super.a)
    }
}
Object.setPrototypeOf(two, one)  //将one绑定为two的原型
two.f()  //输出:hello

注意:super 关键字只能用在对象的方法中,且方法必须为简写方法。

函数

函数参数默认值:可以为函数的参数设置默认值。例如:

function f(x, y=5){
    console.log(x + y)
}
f(3)  //输出:8

length:函数属性,返回函数没有指定默认参数的参数个数。例如:

function f(x, y=5){
    console.log(x+y)
}
console.log(f.length)  //输出:1

参数作用域:当设置了参数的默认值时,在函数初始化时参数会形成一个单独的作用域,等到初始化结束,这个作用域会消失。例如:

let x = 1
function f(x, y = x){
    console.log(y)
}
f(2)  //输出:2

rest:参数(形式为 ...变量名 ),用于获取函数的多余参数。这样就不需要使用arguments对象。例如:

function add(...values){
    let sum = 0;
    for (let value of values){
        sum += value
    }
	return sum
}
console.log(add(1, 2, 3))  //输出:6

name:函数属性,返回函数的函数名。

箭头函数

  1. 语法:var f = (参数) => {语句}

  2. 特点

    • 箭头函数没有自己的 this,它的 this 是最近一层非箭头函数的函数的 this ,若没有外层函数则指向全局对象 window 对象。例如:

      const a = {
          one: function(){
              (() => {console.log(this)})()
          }
      }
      a.one()  //输出:a对象,此时箭头函数的this是外层函数的this。
      const b = {
          one: {
              two: () => {console.log(this)}
          }
      }
      b.one.two()  //输出:window,此时箭头函数外层没有非箭头函数,所有this指向window。
      
    • 箭头函数不能做为构造函数。

    • 箭头函数不能使用 arguments 对象,该对象在函数体内不存在,可以使用 rest 参数代替。

    • 箭头函数不能使用 yield 命令,因此箭头函数不能用作 Generator 函数。

立即执行函数

  1. 概念:立即执行函数可以让函数在创建后立即执行,这种模式的本质是函数表达式在创建后立即执行。

  2. 写法:

    //写法一
    (function(){...})()
    
    //写法二
    (function(){...}())
    
    //错误写法
    function(){...}()
    //报错Uncaught SyntaxError: Unexpected token (
    //报错的原因是JS引擎看到function关键字后,认为后面跟的是函数定义语句,但在一条语句后面加上()会被当做分组操作符,而分组操作符里必须要有表达式,所以报错。
    
  3. 作用:立即执行函数会创建一个独立的作用域,作用域里面的变量外面无法访问,避免了环境污染。

letconst

代码块:在 {} 中的代码。

let:声明一个变量,该变量作用域是它所处的代码块。特点:

  • 不存在变量提升:变量提升指变量会在声明时提到代码块的顶端,这时候可以在声明变量之前使用变量而不会报错,不存在变量提升则代表不能在变量声明前使用变量,例如:

    console.log(a)  //输出undefined,变量提升
    console.log(b)  //报错变量b未定义,不存在变量提升
    var a = "hello" //变量提升
    let b = "world" //不存在变量提升
    
  • 暂时性死区:只要块级作用域存在 let 命令,该代码块就会绑定一个作用域,不受外部作用域的影响,例如:

    var a = "hello"
    {
        console.log(a)  //输出 hello
        let b = "world"
    }
    console.log(b)  //报错,变量 b 未定义,由于暂时性死区。
    
  • 不允许重复声明:不允许在同一个作用域中重复声明同一个变量。

const:声明一个只读的常量,一旦声明不允许修改。注意,const 一旦声明变量就必须立即初始化,不能留在以后赋值。例如:

const a = "hello"
const b //报错,变量b未赋值。

特点:const 声明变量对于简单数据类型来说就是指向数据本身,对于复合型数据来说是指向数据的引用地址,引用地址不能改变,但数据可以改变。

this

this 指的是函数运行时所在的环境。

绑定:

  1. 默认绑定:没有其他绑定规则存在时的默认规则。通常是独立函数调用。例如:

    function f(){alert(this)}
    f()  //  [object Window]
    //调用f()时应用了默认绑定,this指向全局对象(非严格模式下)。
    //在严格模式下this指向undefined,undefined上没有this对象,会抛出错误。
    
  2. 隐式绑定:函数的调用是在某个对象上触发的,即调用位置上存在上下文对象。

    function f(){alert(this)}
    var obj = {f: f}
    obj.f()  //  [object Object]
    //f()是在obj对象下调用的,所以this指向obj。
    

    隐式绑定的陷阱一

    function f(){alert(this)}
    var obj = {f: f}
    var ff = obj.f
    ff()  //  [object Window]
    //注意obj.f是引用属性,赋值给ff实际上就是将f函数的指针赋值给ff,此时ff指向f函数本身,那么实际的调用关系是通过ff找到f函数进行调用,整个调用没有通过其他对象,此时f函数指向全局对象。
    

    隐式绑定陷阱二,函数传参,参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值。

    var a = 10; // a 是全局对象的属性 
    function f(){console.log(this.a)} 
    function g(callback) {// callback其实引用的是f, 
        callback() // <-- 调用位置!
    } 
    var obj ={
        a: 2,
        f: f
    }
    g( obj.f ) //输出10
    
  3. 显示绑定:通过 call , apply , bind 的方式,显式的指定 this 所指向的对象。

    • function.call(object, args···):将函数 function 作为对象 object 的方法调用,args 作为参数传递给函数。

    • function.bind(object, args):返回一个新函数,该函数会作为 object 的方法调用,args 是旧函数 function 的参数。例:

    • function.apply(object, args):将函数 function 作为对象 objec t的方法调用,args 作为参数传递给函数,注意,apply 的参数 args 只能是数组。例:

  4. new 绑定:this 指向的就是对象本身。

    function F(name){this.name = name}
    var ff = new F("hello")
    ff.name  // hello
    var fff = new F("world")
    fff.name  //  world
    

    使用new调用函数时,执行了如下过程:

    • 创建(或者说构造)一个全新的对象。
    • 这个新对象会被执行 [[ 原型 ]] 连接。
    • 这个新对象会绑定到函数调用的 this
    • 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。

绑定优先级:如果同时应用了多种规则,四种绑定的优先级为:new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定。

例外

  1. null 或者是 undefined 作为 this 的绑定对象传入 callapply 或者是 bind ,这些值在调用时会被忽略,实际应用的是默认绑定规则。
  2. 箭头函数没有自己的 this ,它的 this 继承于外层代码中的 this

对象属性的描述符

概念JavaScript 对象的属性在创建的时候都带有一些特征值,这些特征值使用方括号 [[]] 括起来,且仅供内部使用,在外部不能直接访问,这些特征值被分为两类,分别是数据属性和选择器属性,统称为对象属性的描述符。

注意,一个对象的属性的描述符只能有数据属性和访问器属性中的一个。

数据属性:属性的数据属性一共有四个,分别是:

  • [[Value]]:表示这个属性的值,如上例 obj.name 的数据属性 [[Value]]hello
  • [[Writable]]:表示这个属性的可写性(即这个属性的值是否可被改变),默认情况下为 true
  • [[Enumerable]]:表示这个属性的可枚举性,默认情况下为 true
  • [[Configurable]]:表示这个属性的可配置性(即对象的属性属性是否可删除,和[[Enumerable]][[Configurable]]是否可以被修改),默认情况下为 true

访问器属性:属性的访问器属性也有四个,分别是:

  • [[Get]][[Get]] 是一个函数,在读取属性时自动调用,将函数的返回值作为属性的值,默认值为 undefined
  • [[Set]][[Set]] 是一个函数,在写入属性时自动调用,将写入的属性传入函数,并将函数传出来的值作为属性的值,默认值为 undefined
  • [[Enumerable]]:表示这个属性的可枚举性,默认情况下为 true
  • [[Configurable]]:表示这个属性的可配置性,默认情况下为 true

操作对象属性描述符的方法

  1. Object.getOwnPropertyDescriptor(obj, 'prop'):返回对象 objprop 属性的属性描述符。

  2. Object.getOwnPropertyDescriptors(obj):查看对象 obj 所有属性的属性描述符。

  3. Object.defineProperty(obj, prop, descriptor):定义或修改对象(obj) 的 属性(prop) 的描述符(descriptor)。

    //修改obj.name的属性描述符,且设置为不可修改
    Object.defineProperty(obj, 'name', {
        value: 'world',
        writable: false
    })
    obj.name //输出:world
    //在obj上新增属性,并设置描述符,当对象没有指定属性时会为其新增这个属性
    Object.defineProperty(obj, 'add', {
        value: 'hello',
        writable: false
    })
    obj.add //输出:hello
    
  4. Object.defineProperties(obj, props):定义或修改对象(obj)的一个或多个属性及其描述符(props) 。

    //修改对象obj原有的两个属性,新增一个属性
    Object.defineProperties(obj, {
        'name': {value: 'world', writable: false},
        'say': {value: function(){console.log(this.add)}},
        'add': {value: 'hello', writable: false}
    })
    obj.say //输出:hello
    
  5. 示例:定义多种访问器属性。

    //定义对象属性,且two的对象属性为访问器属性
    var mix = {}
    Object.defineProperties(mix, {
        'one': {value: 'hello'},
        '_two': {value: 'world', writable: true},
        'two': {
            get: function(){return this._two},
            set: function(arg){this._two = arg}
        }
    })
    

Iterator迭代器

概念:Iterator 迭代器是一个接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署了Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

工作流程

  1. 创建一个指针对象,指向当前数据结构的起始位置。

  2. 第一次调用指针对象的 next 方法,将指针指向数据结构的第一个成员,并返回第一个成员的信息,是一个包含 valuedone 属性的对象,value 是成员的值,done 是一个布尔值,表示遍历是否结束。

  3. 第二次调用指针对象的next方法,将指针指向数据结构的第二个成员,并返回第二个成员的信息。

  4. 不断调用指针对象的 next 方法,直到指向数据结构的结束位置。

  5. 例如:

    //一个遍历器函数
    function makeIterator(array) {
      var nextIndex = 0;
      return {
        next: function() {
          return nextIndex < array.length ?
            {value: array[nextIndex++], done: false} :
            {value: undefined, done: true};
        }
      }
    }
    var it = makeIterator(['a', 'b']);
    it.next() // {value: "a", done: false}
    

for...of:当使用for...of循环遍历某种对象时,该循环会自动去找 Iterator 接口。

默认Iterator接口:默认的 Iterator 接口部署在数据结构的 Symbol.iterator 属性上,只要有这个属性的数据结构就都是可遍历的,原生具备这个接口的数据结构有:ArrayMapSetStringTypedArray、函数的 arguments 对象、NodeList 对象。

XMLHttpRequest

概念:XMLHttpRequest 对象是 JavaScript 定义的用于与服务器通信的对象。所有的浏览器都有内建的 XMLHttpRequest 对象。

构造函数:XMLHttpRequest()

示例

let xhr = new XMLHttpRequest()  //创建XMLHttpRequest对象
xhr.timeout = 0  //设置请求超时时间
xhr.onload = function(res){...}  //请求成功时触发回调函数
xhr.onloadend = function(res){...}  //请求结束时触发函数
xhr.onerror = function(res){...}  //请求出错回调函数
xhr.ontimeout = function(res){...}  //请求超时回调函数
xhr.onreadystatechange = function(){
    //如果请求成功返回请求内容
    if(xhr.readyState == 4 && xhr.status ==200){
        return xhr.response
    }
}
xhr.open(method=请求方法, url=请求地址, async=是否异步) //初始化请求
xhr.responseType = ""  //设置期望返回的数据类型
xhr.setRequestHeader()  //设置请求头
xhr.send()  //发送求情

词法作用域

概念:词法作用域就是定义在词法阶段的作用域。词法作用域中,作用域由写代码时变量和函数的位置来决定的,因此当词法分析器处理代码时会保持作用域不变(大部分情况下是这样的)。注意词法作用域中,函数的作用域由函数的书写位置来决定,而不是函数的调用位置。如:

var a=1
function f(){
    var a = 2
    setTimeout(function(){console.log(a)},1000)
}
f()//输出2,因为函数定义在f内部,查找变量a时先在f内查找,未找到再去上层找

var a = 1
function g(){console.log(a)}
function f(){
    var a = 2
    setTimeout(g,1000)
}
f()//输出1,因为g定义在f外部,查找变量a时不会到f内部查找

闭包:当函数可以记住并访问所在的词法作用域时,就产生了闭包。例如:

function f(){
    var a = 1
    function g(){console.log(a)}
    return g
}
var gg = f()
gg()//输出1,此时f()在它所在的词法作用域以外执行,但依然访问到了它所在的词法作用域,可以称为产生了闭包

延迟函数的回调会在循环结束时执行,如:

for (var i=1; i<=5; i++) {
    setTimeout(function f(){console.log( i )}, i*1000 )
}
//输出5次6,虽然函数f是在五次迭代中分别定义的,但共享一个作用域,这个作用域中只有一个i,固每次都会打印出相同的值。

//使用创建词法作用域和闭包,使循环函数输出1-6
for (var i=1; i<=5; i++) {
    (function(){//每次循环都会创建一个新的匿名函数,将形成一个新的作用域,达到循环输出的目的。
        var j = i
        setTimeout(function f(){console.log(j)}, i*1000 )
    })()
}

动态作用域

this
  1. this 在任何情况下都不指向函数的词法作用域。例如:

    function g(){console.log(this.a)}
    function f(){
        var a = 2
        g()//g函数试图通过this引用f的词法作用域。
    }
    f()//输出undefined,因为this在任何情况下都不指向函数的词法作用域。
    
  2. this 不指向函数自身。

  3. this 是在运行时绑定的,而不是在编写时绑定的(箭头函数除外),它的指向取决于函数在哪里调用。

  4. 调用栈和调用位置

    function baz() {// 当前调用栈是:baz     // 因此,当前调用位置是全局作用域 
        console.log( "baz" )
        bar(); // <-- bar 的调用位置
    }
    function bar() {// 当前调用栈是 baz -> bar// 因此,当前调用位置在 baz 中
        console.log( "bar" )
        foo(); // <-- foo 的调用位置
    }
    function foo() {// 当前调用栈是 baz -> bar -> foo// 因此,当前调用位置在 bar 中
        console.log( "foo" )
    }
    baz(); // <-- baz 的调用位置
    
  5. this 的绑定规则

    • 默认绑定
    • 隐式绑定
    • 显示绑定
    • new 绑定

数据类型及检验方法

JS 的内置类型,可以分为基本类型和引用类型,如下:

  1. 基本类型:String、Number、Bollean、Null、Undefined、Symbol
  2. 引用类型:Array、Object、Function、Date、RegExp、Error、Arguments 等都属于引用类型。

注意,JS 中变量没有类型,它的值才有类型。

检验方法:

  1. typeof

    能判断:

    • String(返回 string
    • Number(返回 number
    • Boolean(返回 boolean
    • undefined(返回 undefined
    • function(返回 function
    • Symbol(返回 symbol

    不能判断:

    • 对象类型都返回 object,不会更细化,如: typeof [] 返回 object
    • null 返回 object
    • NaN 返回 number
  2. instanceof

    用来判断对象是否为某一数据类型的实例,不能判断基本数据类型(StringNumberBolleanNullUndefinedSymbol)。

  3. constructor

    返回创建此对象的构造函数的引用,不能判断 nullundefined 其它都可以(因为 nullundefined 没有构造函数)。

    使用方法:(1).constructor === Number ,返回 true

  4. Object.prototype.toString

    返回一个表示该对象的字符串,可以判断所有类型。

    使用方法:Object.prototype.toString.call(null),返回 [object Null]

解构赋值

数组(变量与解构数组顺序一致)

  1. 普通解构:只要两边的相对应的项的模式大致相同就能结构赋值(大致相同指左边的嵌套层数不能比右边多),左边比右边多时,左边多的赋值为 undefined ,左边比右边少时,右边多的值被省略。

    let [a, b, c] = [1, [2]]  //前面需要使用let、var、const或者用()括起来
    console.log(a)  //输出1
    console.log(b)  //输出[2]
    console.log(c)  //输出undefined
    
  2. 默认值解构:右边的值能够带有默认值,当左边值不够或严格等于 undefined 使用默认值。

    let [a, b=2, c=3, d=4] = [1, "hello", undefined]
    console.log(a)  //输出1
    console.log(b)  //输出hello
    console.log(c)  //输出3
    

对象(变量与解构对象的名字相同,无关顺序)

  1. 简写解构:需要两边的对象名字相同,无法匹配的赋值为 undefined

    let {a, b, c} = {b: "world", a: "hello", d: "no"}
    console.log(a)  //输出hello
    console.log(b)  //输出world
    console.log(c)  //输出undefined
    

    注意,当解构不成功时变量会被赋值为 undefined

  2. 默认值解构:右边的值能够带有默认值,当两边无法匹配或匹配值严格等于 undefined 使用默认值。

    let {a="one", b="world"} = {a: "hello"}
    console.log(a)  //输出hello
    console.log(b)  //输出world
    
  3. 一般解构:

    真实解构情况:let {a: aa, b: bb} = {a: "hello", b: "world"},左右两边的 ab 作为匹配标准,使 aahello 匹配、bbworld 匹配。生成{aa: "hello", bb: "world"}

    默认解构情况:let {a: a, b: b} = {a: "hello", b: "world"}

    简化为:let {a, b} = {a: "hello", b: "world"}

    对象解构的真实情况是将解构变量赋值给变量右边的值。

    let {a: aa, b: bb} = {a: "hello", b: "world"}
    console.log(aa)  //输出hello
    console.log(a)   //输出变量a未定义
    

字符串解构:字符串是一个类数组,可以遍历,所以也能用来解构

let [a, b, c] = 'hel'
console.log(a)  //h
console.log(b)  //e
console.log(c)  //l

函数的参数解构赋值

//数组一般解构
function add([x, y]){console.log(x+y)}
add([1,2])  //输出3
//数组默认值解构
function add([x=1, y=2]){console.log(x+y)}
add([2])  //输出4

//对象一般解构
function add({x, y}){console.log(x+y)}
add({x:1, y:2})  //输出3
//对象的默认值解构
function add({x=1, y=2}){console.log(x+y)}
add({x:2})  //输出4

用途

  1. 交换变量的值

    let x = 1
    let y = 2
    [x, y] = [y, x]
    
  2. 取出函数返回的多个值,函数一次只能返回一个值,所以返回多个值一般放在数组或对象中

    function ex1(){return ["hello", "world"]}
    let [a, b] = ex1()
    
  3. 给函数的参数赋值

    function ex1([x, y]){}
    ex1(["hello", "world"])
    
  4. 提取解构后的 JSON 数据

原型原型链

原型

  1. 原型:每个构造函数创建出来的时候系统会自动给这个构造函数创建并关联一个空的对象,这个空对象就是原型,访问构造函数的原型的方法:构造函数名.prototype

  2. 构造函数创建出来的对象,都会默认和构造函数的原型关联,即原型中定义的方法跟属性,会被这个构造函数创建出来的对象所共享。

  3. 访问构造函数的原型:构造函数名.prototype

  4. 访问构造函数实例的原型:实例._proto_

  5. 访问与原型关联的构造函数:原型.constuctor

  6. 如图:

    003

原型链

  1. 原型链:对象有原型,原型本身又是一个对象,所以原型也有原型,这样就会形成一个链式结构的原型链。

  2. 如图:

    004

属性的搜索原则

  1. 先去对象自身属性中找,如果找到直接使用。
  2. 如果没找到去自己的原型中找,如果找到直接使用。
  3. 如果没找到,去原型的原型中继续找,找到直接使用。
  4. 如果没有会沿着原型不断向上查找,直到找到null为止。

事件

事件流和事件冒泡、事件捕获

  1. 事件流:指从页面中接收事件的顺序,根据不同的实现方式分为事件冒泡流和事件捕获流。
  2. 冒泡:指事件开始由具体的元素接收,然后逐级向上传播到不具体节点。
  3. 捕获:指事件开始由不具体的节点接收,然后逐级向下传播到具体节点。

相关方法

  1. addEventListener():用于改变事件流,默认为冒泡。

    el.addEventListener(event, function, [boolean])
       event:事件类型名称,不包括on
       function:事件处理函数
       boolean:事件流类型为捕获还是冒泡,默认为false冒泡。
    
  2. event.preventDefault():阻止浏览器执行当前事件关联的默认操作。如复选框的点击事件的默认操作是选中复选框,例,阻止复选框被选中:

    <p>点击:<input type="checkbox" id="ex1"></p>
    
    document.getElementById("ex1").addEventListener("click", e => {
        alert("复选框不会被选中")
        e.preventDefault()
    })
    
  3. event.stopPropagation():阻止事件在捕获、冒泡阶段进行传播。

  4. event.stopImmediatePropagation():类似于 stopPropagation( ) ,除此之外,它还阻止注册在这个元素上的一个事件其它处理程序。当一个元素上一个事件绑定了多个处理程序时,程序会逐个执行, stopImmediatePropagation() 会阻止其它事件的执行。例:

    <button id='ex1'>点击</button>
    
    const ex1 = document.getElementById("ex")
    ex1.addEventListener("click", () => alert("点击一"))
    ex1.addEventListener("click", () => alert("点击二"))
    ex1.addEventListener("click", e => {
        alert("到此为止")
        e.stopImmediatePropagation()
    })
    ex1.addEventListener("click", () => alert("不会被执行"))
    
  5. return false:相当于

    • event.preventDefault()
    • event.stopPropagation()
    • 停止回调函数执行并立即返回

    三者合一,除非清楚使用的目的要谨慎使用。

事件委托

事件委托是将元素的事件委托给它的父级或者更外层的元素去处理,它本身通过冒泡的机制去触发事件,这样只操作了一次 DOM,提高了程序性能。

注意,事件监听回调函数中的 e.target 指向的是触发这个事件的元素,而不是父元素。

async示例

function one(args){
    return new Promise(resolve => {
        resolve(args)
    })
}
function two(args){
    return new Promise(resolve => {
        resolve(args)
    })
}
async function example(args){
    const aa = await one(args)  //await后面是Promise对象对象时,返回该对象的结果,如果有一个Promise对象为rejected则代码停止执行;如果不是直接返回值
    const bb = await two("world")//
    return aa + bb  //return的返回值是then方法的回调函数的参数
}
example("hello")
    .then(res => console.log(res))  //async函数返回一个Promise对象
    .catch(error => console.log(res))  //捕获async内部错误

Generator生成器示例

示例一:

function* example(args){  //function关键字与函数名之间的*号是Generator的标志
    console.log(args)
    yield args  //yield、return关键字指定函数的内部状态,调用next()方法每次移动一个状态
    console.log('two')
    let arg = yield 'two'  //无论 yield 是否有返回值,下一个 yield 的 next 传入的参数会作为本次yield的返回值
    console.log(arg)
    yield 'thr'  //可以向next()传入参数,参数会作为上一个yield的返回值。
    return 'ending'  //next()方法走到这里终止,状态不再改变
}
const ex1 = example('one')  //传入参数,并运行Generator
ex1.next( res => {console.log(res)})  //执行一个yield之前的代码,并接受yield的返回值
ex1.next()  //向yield传参数
ex1.next('thr')  //可以向next传参,参数作为上一个yield表达式的返回值。
for(let i of ex1){console.log(i)}  //可以遍历yield执行

示例二:

function* example(){
    console.log("one")
    yield 'one'
    try{
        console.log("two")
        yield 'two'
    }catch(error){
        console.log('内部捕获错误', error)
    }
    console.log("thr")
    yield 'thr'
}
const ex1 = example()
ex1.next()  //throw抛出的错误若要被Generator内部捕获,必须执行一次next()
ex1.throw('错误')  //抛出错误,会执行一次next(),且将Generator变为执行完毕。抛出错误时,若Generator内部没有try...catch代码块,错误会被外部try...catch捕获,或默认错误程序捕获。
try{  //内部不定义try...catch时外部定义的try...catch,当二者同时存在时优先被外部捕获。
    ex1.throw('错误')
}catch(error){
    console.log('外部捕获错误', error)
}

实现斐波那契:

function* fibonacci() {
  let [prev, curr] = [0, 1];
  for (;;) {
    yield curr;
    [prev, curr] = [curr, prev + curr];
  }
}

for (let n of fibonacci()) {
  if (n > 1000) break;
  console.log(n);
}

Promise 示例

const ex2 = Promise.resolve([args]) //返回一个resolved是fulfiled状态的Promise对象
const ex3 = Promise.reject([args])  //返回一个resolved是rejected状态的promise对象
const ex1 = new Promise((resolve, reject) => {
    if(true){
        resolve('成功')  //将Promise变为fulfiled的resolved状态,并返回值被then中的回调函数接收
    }
    else{
        reject('失败')  //将Promise变为rejected的resolved状态,并返回值被then中的回调函数接收
    }
}).then(  //then在当前所有的同步任务执行完后立即执行,先于计时器函数。then会在状态变为resolved时自动执行
    success => {
        console.log(a)  //打印一个不存在的变量a,使错误被catch接收
        console.log(success)  //打印resolved状态的返回值
    }, 
    error => {
        console.log(b)  //打印一个不存在的变量b,使错误被catch接收
        console.log(error)  //打印rejected状态的返回值
    }
)
.catch(error => console.log(error))  //接收代码中出现错误,也可以在then中没有接收rejected状态的回调函数的时候,接收rejected状态的返回值。
.finally(console.log("end"))  //不管状态如何都会执行,回调函数不接受任何参数

const ex4 = Promise.all([ex1, ex2, ex3])  //将多个Promise实例包装成一个,当所有的实例状态都变为fulfilled的resolved时,将所有实例的返回值组成的数组传递给then的回调函数。当有一个实例的状态变为rejected的resolved时,ex4的状态就变为rejected的resolved,将那个实例的返回值传递给ex4回调函数。

const ex5 = Promise.race([ex1, ex2, ex3])  //将多个Promise实例包装成一个,当其中一个实例的状态改变时,ex5就跟着起改变,并将这个实例的返回值传递给回调函数。

const ex6 = Promise.allSettled([ex1, ex2, ex3])  //将多个Promise实例包装成一个,当所有的实例状态都变为resolved时,将所有结果组成的数组给回调函数

异步编程

进程与线程

  • 进程:进程是一个具有独立功能的程序关于某个数据集合的一次运行活动,是系统进行资源分配和调度的基本单位。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。可以在计算机的任务管理器中查看进程,如:

    005

  • 线程:是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。可以在计算机的任务管理器中查看线程数,如:

    006

  • 进程和线程:进程是线程的容器,一个进程中可以拥有多个线程,这些线程共用进程中的资源,如数据、内存等;一个程序运行时计算机会为其分配进程(一个程序可以有多个进程),进程中的线层进行逻辑运算以实现程序的效果。

浏览器:

  • 浏览器进程:浏览器是多进程的,其主要进程有:

    1. Browser进程:浏览器的主进程,只有一个,主要用来:
      • 负责浏览器页面显示,与用户交互(就浏览器本身的功能)。
      • 负责各个页面的管理,创建和销毁其它进程。
      • 将浏览器渲染进程得到的结果绘制到用户界面上。
      • 网络资源的管理、下载等。
    2. 第三方插件进程:每种类型的插件对应一个进程,仅在插件使用时才会创建。
    3. GPU进程:最多一个,用于3D绘制等。
    4. 浏览器渲染进程:默认每个页面一个进程,这样可以保证各页面间互不影响,可以达到一个页面崩溃了不会影响其他页面等。
  • 浏览器渲染进程:也称浏览器内核,是多线程的,主要包含以下线程:

    1. GUI渲染线程

      • 负责浏览器界面渲染,如解析HTML、CSS、构建DOM数和RenderObject树、布局、绘制等。
      • 当界面需要重绘或某种操作引发回流时,该线程就会执行。
      • GUI渲染线程与JS引擎线程是互斥的,即当JS引擎执行时GUI渲染线程会被挂起,GUI更新会被保存在一个队列中等待JS引擎空闲时立即被执行。
    2. JS引擎线程

      • JS引擎线程也成JS内核,负责处理JavaScript脚本程序。
      • 一个页面(Renderer进程)中无论何时都只有一个JS线程处理JavaScript程序,这也是为什么JavaScript被称为单线程的原因。
      • 注意,由于JS引擎线程与GUI选软线程是互斥的,所以如果JS执行过长会造成页面渲染阻塞。
    3. 事件触发线程

      • 归属于浏览器而不是JS引擎,JS引擎的协助线程,当JS引擎执行代码块如setTimeout时(也可以说是浏览器渲染进程的其它线程,如鼠标点击事件、AJAX异步请求等),会将对应的任务添加到事件触发线程中,当对应的事件符合触发条件时,事件触发线程会将事件添加到处理队列的末尾,等待JS引擎处理。例如:

        function one(){console.log(1)}
        function two(){console.log(2)}
        function thr(){console.log(3)}
        function fou(){console.log(4)}
        one()                  //two会被读取放入事件触发线程中
        setTimeout(two, 30)    //当过30ms后会将two放入处理队列末尾,等待JS引擎来执行
        setTimeout(thr(), 40)  //注意thr()会立即执行
        fou()
        输出:1,3,4,2
        
    4. 定时器触发线程

      • setInterval与setTimeout所在的线程,浏览器中的的定时计数器不是由JS引擎线程计数的(JS引擎线程是单线程的,如果用来计数会导致线程堵塞),当JS引擎线程执行setInterval与setTimeout所在的代码块时,定时器触发线程开始计时,等计时结束后将任务添加到处理队列末尾。
    5. 异步HTTP请求线程

      • XMLHttpRequest连接成功后浏览器会新开的一个线程,当检测到状态变更时,如果设置有回调函数,异步HTTP请求线程会产生状态变更事件,将这个回调函数放入事件队列末尾。
  • 浏览器渲染页面的流程

    1. Browser进程收到用户请求,获取加载页面需要的内容,然后将任务通过浏览器渲染进程接口传递给浏览器渲染进程。

    2. 浏览器渲染进程接收到消息后进行渲染,最后将结果传回Browser进程。浏览器渲染进程分为以下几步:

      • 解析HTML建立DOM树

      • 解析CSS构建render树

      • 将DOM树与render树结合

        注意:CSS加载不会阻塞DOM树解析,但会阻塞最终DOM树与render树的结合。

    3. Browser进程接收到浏览器渲染进程的结果,然后将结果发送给GPU进程

    4. GPU进程将结果合成,显示在屏幕上。然后出发load事件。

    5. 然后处理页面的JS程序

JS的运行机制:

  • JS执行任务时将任务分为同步任务和异步任务,任务进入执行栈时会判断任务是同步任务还是异步任务,若是同步任务则进入主线程直接执行,若是异步任务的话会进入事件触发线程,并注册相应的回调函数,当事件触发后将任务放入事件任务列队,当主线程的任务执行完毕后执行事件任务列队中的任务。JS引擎存在一种机制,会不断检查主线程是否为空,一旦主线程为空就会检查任务队列是否有待执行的任务。

  • 流程图

    007

异步与同步

  • 同步模式:按照任务列队依次执行任务的模式。例如:

    function one(){console.log(1)}
    function two(){console.log(2)}
    function thr(){console.log(3)}
    one()
    two()
    thr()
    //函数会从上向下一次执行,输出1,2,3
    
  • 异步模式:不按照任务列队执行任务的模式。

    function f(){console.log("异步执行")}
    function one(){console.log(1)}
    function two(){
        console.log(2)
        setTimeout(f, 30)
    }
    function thr(){console.log(3)}
    one()
    two()
    thr()
    //执行流程:
    //执行one()
    //执行two(),执行two()内的console.log(2),发现setTimeout()是任务任务,放入任务列队等待执行
    //执行thr()
    //此时主线程任务全部执行完毕,查看任务列队是否有任务待执行,发现任务,执行setTimeout()
    //所以输出:1,2,3,异步执行
    
  • 单线程:JavaScript的执行环境是单线程的,按理论来说JS不可能存在异步模式,事实上也是如此,但浏览器是多线程的,所以可以利用浏览器的多线程使JS看起来像是多线程。

  • 异步实现

    1. 单线程:JavaScript的执行环境是单线程的。
    2. 理论:JS是单线程的这个前提一直没有改变,但可以依靠浏览器的多线程实现异步,JS引擎执行任务时会判断任务是同步任务还是异步任务,若是同步任务则直接执行,异步任务则放入另一个列队,等同步任务全部执行完毕,再去执行异步任务,如setTimeout()就是异步任务,在执行同步任务时会被识别,等同步任务全部执行完毕后执行,所以若想生成异步则需要想办法让任务被识别为异步任务。
  • 异步实现方法

    1. 回调函数

      • 回调函数:回调函数就是一个通过函数指针调用的函数。把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就称这个函数是回调函数。

        注意:从回调函数的定义可以看出,回调函数跟异步并没有必然关系(回调函数就是一个普通的函数)。只是执行异步操作的大多都是回调函数,这时回调函数才和异步产生了联系。例如:

        a、同步回调

        function f(){console.log("同步回调")}
        function one(){console.log(1)}
        function two(y){
            console.log(2)
            y()
        }
        function thr(){console.log(3)}
        one()
        two(f)  //此时two(f)中的f就是回调函数
        thr()
        //输出:1,2,同步回调,3
        

        b、异步回调

        function f(){console.log("异步回调")}
        function one(){console.log(1)}
        function two(y){
            console.log(2)
            setTimeout(y, 30)
        }
        function thr(){console.log(3)}
        one()
        two(f)  //此时two(f)中的f就是回调函数
        thr()
        //输出:1,2,3,异步回调
        //这时f()作为回调函数被异步调用了
        

        从上面两个例子看出,异步与回调并没有必然关系,回调函数只是将函数作为参数使用的一种方法,回调函数是否能异步与调用它的函数是否是异步有关。在同步回调例子中调用回调函数的函数是同步函数,所以回调函数同步执行;在异步回调的例子中调用回调函数的函数是异步函数,所以回调函数异步执行。

      • 回调函数的优点:

        a、代码拆分,提高代码的复用性

        b、实现异步调用,因为有些操作需要异步执行,这时可以利用回调函数在某个事件触发的时候来调用函数

      • 回调函数的缺点:

        a、丢失线性性(回调地狱),多层回调函数会导致嵌套的层数过深,使代码纵向发展,不宜阅读和理解

        b、缺乏可信任性,控制反转导致的一系列信任问题。

        • 控制反转指调用回调函数的代码是第三方的代码,不在你的直接控制之下,如$.ajax()就是第三方的代码,当无法控制的第三方代码执行回调函数的时候,会存在一些问题,如:

          1、调用回调过早,2、调用回调过晚,3、调用的次数过多或过少,4、未能把所需要的参数传递给回调函数等,5、吞掉可能出现的错误或异常。

          这就会导致信任链断裂,如果没有采取措施解决这些控制反转导致的信任问题,代码中就会隐藏Bug。

    2. 事件监听

    3. Promise

    4. Generator

    5. Async/Await

几个异步 API 优劣

  • 回调 不是异步Api,是一种异步编程的实现手段。
  • Promise 解决 回调 的回调地狱。
  • Generator 可以交出函数的执行权。
  • Async 是 Generator 语法糖,解决了 Promise 链式调用的不直观性,可读性接近于同步代码。

模块化

模块化是随着前端项目越来越大,代码越来越多,为了解决命名冲突、提高代码复用性和维护性等问题而产生的技术。

常用的有以下方案:

  1. IIFE:利用立即执行函数和闭包。

  2. CJS:即 common.js 规范(社区标准),在 node.js 中它是标准规范。

    使用 module.exportsexports (两者不能同时存在,前者优先级较高)导出,require 导入。

    exports 相当于 module.exports={},不能直接赋值(exports={a: 1} 这样不行),需要这样 exports.a = 1

    module.exports 不仅可以导出对象,还能导出函数等。

    特点:

    1. 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果(运行时加载),由于导出的数据是拷贝的,导致模块内的修改不会影响拷贝值,代码出错不容易排查。
    2. 以同步方式加载模块,并且模块加载的顺序,按照其在代码中出现的顺序,不会将模块中require提升到顶部。
    3. require 可以放在块级作用域或条件语句中。

    由于 CJS 规范的模块加载是同步(只有加载完成后,才执行后面的操作),这在 node.js 中没有问题,但在浏览器端,由于加载模块都是依赖于网络的,所以就有了新的规范。

  3. AMD:异步加载模块的一个比较流行的方案。主要用于浏览器端,其中最具代表性的就是 require.js,它的核心原理是通过动态 script 脚本来异步引入模块,然后对每个脚本的 load 事件进行监听,如果每个脚本都加载完成了,再调用回调函数。

    AMD 方案可以异步加载,依赖前置(依赖的模块全部加载完毕才会运行当前模块)。

    使用 define 定义模块并使用 exports 导出,使用require 导入模块(详细语法 可以看require.js 的文档。)

  4. CMD:异步加载模块的一个比较流行的方案。主要用于浏览器端,其中最具代表性的就是 sea.js

    CMD方案可以异步加载,按需加载(即当需要用到某模块依赖的时候才会去加载)。

    使用 define 方法利用 require 参数导入模块,使用 exportsmodule.exports 导出模块,使用 seajs.use 使用模块,(详细语法 可以看sea.js 的文档。

  5. ESM:是 JavaScript 官方的标准化模块系统,在 ES6 开始支持,当下几乎所有浏览器都已经提供了支持。

    使用 exportexport default 导出数据,import 导入数据。

    export default 导出的数据能直接使用,且一个模块中只能有一个。

    export 导出的数据在一个对象上,一个模块中不限制数量。

    特点:

    1. 不像 CJS,ESM模块导入的值不是拷贝是引用。
    2. ESM标准模块加载器是异步的,读取到脚本后不会立即执行,而是先进入编译阶段进行模块解析,检查模块上调用了 importexport 的地方,并以此类推的把依赖模块一个个异步、并行地进行下载。在此阶段 ESM 加载器不会执行任何依赖模块代码,只检查语法错误、确定模块依赖关系、确定模块输出和输入的变量。最后 ESM 会进入执行阶段,按照顺序执行各模块脚本。所以 import 会自动提升到代码的顶层。
    3. ESM 默认使用严格模式(use strict),因此在 ESM 模块中的 this 不指向全局 window对象,而是undefined,且变量在声明前无法使用。
    4. import 不可以放在块级作用域或条件语句中。如果要动态导入,需要使用到 import()
  6. UMD:通用模块定义,它是对 CJS、AMD、CMD 的兼容,使得各个版本都能正常运行。

    核心代码:

    ((root, factory) => {
      if (typeof define === 'function' && define.amd) {
        // AMD
        define(factory);
      } else if (typeof define === 'function' && define.cmd){
        // CMD
        define(function(require, exports, module) {
          module.exports = factory()
        })
      } else if (typeof exports === 'object') {
        // CommonJS
        module.exports = factory();
      } else {
        // 都不是直接挂载在全局对象上
        root.umdModule = factory();
      }
    })(this, () => {
      // return 需要定义的模块
      return {
        name: 'randy'
      }
    });
    

    可以看到,defineAMD/CMD 语法,而 exports 只在 CommonJS 中存在,它在定义模块的时候会检测当前使用环境和模块的定义方式,如果匹配就使用其规范语法,全部不匹配则挂载再全局对象上,可以看到传入的是一个 this ,它在浏览器中指的就是 window ,在服务端环境中指的就是 global ,使用这样的方式就能兼容各种模块了。

算法相关名词

算法:算法是为了解决问题如何设计程序的思想,不是程序本身,如 数组求和,可以使用循环的方式去编写程序解决问题,这个循环就是算法。

时间复杂度:描述一个算法在运行时的所花费的时间度量,用 O 表示,具体来说就是程序中所有代码行数执行的时间,然后求极限,如:

const a = 1  // 运行时间 T, T 是一行代码的运行时间,由于它在不同环境下可能不同,所以使用 T 表示
const b = 2  // 运行时间 T
// 合计运行时间 2T,常量求极限为 2T,时间复杂度记为 O(T) 
let a = 0 // T
for(let i; i < n; i++){ // Tn + T
    a += i // Tn
}
// 合计运行时间 2T + 2Tn, 根据 n 求极限为 2Tn,时间复杂度记为 O(n)

空间复杂度:描述一个算法在运行过程中临时占用的存储空间度量,用 O 表示,具体来说就是程序中所有代码执行时所申请的存储空间,然后求极限,如:

const a = 1  // 临时空间 S
const b = 2  // 临时空间 S
// 合计临时空间是 2S,常量求极限为 2S,空间复杂度记为 O(S)
const arr = new Array(n) // 临时空间是 Sn
for(let i; i < n ; i++){
    arr[i] = i
}
// 合计临时空间是 Sn,根据求极限为 Sn,空间复杂度记为 O(n)