Yapei Li

专注于前端领域

0%

定义

什么是伪

  1. 不是真实的但有其外观;伪装的;假的或欺骗的;骗人的。
  2. 差不多,很接近,或尽可能一样。

    为什么引入伪类,伪元素

    css 引入伪类和伪元素概念是为了格式化文档树以外的信息。

    也就是说,伪类和伪元素是用来修饰不在文档树中的部分,比如,一句话中的第一个字母,或者是列表中的第一个元素

什么是 伪类

伪类用于当已有元素处于的某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的。虽然它和普通的 css 类相似,可以为已有的元素添加样式,但是它只有处于 dom树无法描述的状态下才能为元素添加样式,所以将其称为伪类

伪类是一个冒号(:)后跟伪类的名字构成的,有时候名字后面还会有一个放在括号里的值(:nth-child)

什么是 伪元素

伪元素是一种虚拟的元素CSS把它当成普通HTML元素看待。之所以叫伪元素,就因为它们在文档树DOM中并不实际存在。换句话说,我们不会在HTML中包含伪元素,只会通过CSS来创建伪元素

阅读全文 »

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
52
53
54
55
/* 清除内外边距 */
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */
dl, dt, dd, ul, ol, li, /* list elements 列表元素 */
pre, /* text formatting elements 文本格式元素 */
fieldset, lengend, button, input, textarea, /* form elements 表单元素 */
th, td { /* table elements 表格元素 */
margin: 0;
padding: 0;
}

/* 设置默认字体 */
body,
button, input, select, textarea { /* for ie */
/*font: 12px/1 Tahoma, Helvetica, Arial, "宋体", sans-serif;*/
font: 12px/1 Tahoma, Helvetica, Arial, "\5b8b\4f53", sans-serif; /* 用 ascii 字符表示,使得在任何编码下都无问题 */
}

h1 { font-size: 18px; /* 18px / 12px = 1.5 */ }
h2 { font-size: 16px; }
h3 { font-size: 14px; }
h4, h5, h6 { font-size: 100%; }

address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */
code, kbd, pre, samp, tt { font-family: "Courier New", Courier, monospace; } /* 统一等宽字体 */
small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */

/* 重置列表元素 */
ul, ol { list-style: none; }

/* 重置文本格式元素 */
a { text-decoration: none; }
a:hover { text-decoration: underline; }

abbr[title], acronym[title] { /* 注:1.ie6 不支持 abbr; 2.这里用了属性选择符,ie6 下无效果 */
border-bottom: 1px dotted;
cursor: help;
}
q:before, q:after { content: ''; }

/* 清除浮动 */
.clearfix:after{
content: "020";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.clearfix {
zoom: 1;
}

html,body {
width: 100%;
height: 100%;
}
阅读全文 »

BFC的定义

BFC(Block formatting context)直译为”块级格式化上下文“。

它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。

它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用

FC

formatting context的首字母缩写,直译过来是格式化上下文,它是页面中的一块渲染区域,有一套渲染规则,决定了其子元素如何布局,以及和其他元素之间的关系和作用

常见的FC有BFCIFC(行级格式化上下文),还有GFC(网格布局格式化上下文)和FFC(自适应格式化上下文)

block-level box(块级盒子)

Alt text

盒子是由marginborderpaddingcontent组成的,实际上每种类型的四条边定义了一个盒子,分别是分别是content boxpadding boxborder boxmargin box,这四种类型的盒子一直存在,即使他们的值为0。

决定块盒在包含块中与相邻块盒的垂直间距的便是margin-box

Box之间的距离虽然也可以使用padding来控制,但是此时实际上还是属于box内部里面,而且使用padding来控制的话就不能再使用border属性了。

三种文档流的定位方案(控制元素的布局)

常规流 (normal flow)

在普通流中,元素按照其在 HTML 中的先后位置至上而下布局

也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定

  • 在常规流中,盒一个接着一个排列;
  • 在块级格式化上下文里面, 它们竖着排列;块级元素则会被渲染为完整的一个新行,除非另外指定,否则所有元素默认都是普通流定位
  • 在行内格式化上下文里面, 它们横着排列,直到当行被占满然后换行
  • positionstaticrelative,并且floatnone时会触发常规流;
  • 对于静态定位(static positioning),position: static,盒的位置是常规流布局里的位置;
  • 对于相对定位(relative positioning),position: relative,盒偏移位置由top、bottom、left、right属性定义。即使有偏移,仍然保留原有的位置,其它常规流不能占用这个位置。

浮动 (float)

  • 左浮动元素尽量靠左、靠上,右浮动同理
  • 这导致常规流环绕在它的周边,除非设置 clear 属性
  • 浮动元素不会影响块级元素的布局
  • 但浮动元素会影响行内元素的布局,让其围绕在自己周围,撑大父级元素,从而间接影响块级元素布局
  • 最高点不会超过当前行的最高点、它前面的浮动元素的最高点
  • 不超过它的包含块,除非元素本身已经比包含块更宽
  • 行内元素出现在左浮动元素的右边和右浮动元素的左边,左浮动元素的左边和右浮动元素的右边是不会摆放浮动元素的
浮动会造成文本环绕 和 行内元素环绕
1
2
3
4
5
6
7
<div style="border: 2px solid #ccc;">
<div style="width: 100px;height: 100px;float: left;background: red;"></div>
<span>span会环绕红色div</span>
<span>span会环绕红色div</span>
<span>span会环绕红色div</span>
文字也会环绕红色div
</div>

Alt text

1
2
3
4
5
6
<div style="float: left; width: 100px; height: 100px; background: #000;">
</div>
<div style="height: 200px; background: #AAA;">
<div style=" width: 30px; height: 30px; background: red;"></div>
<p>content</p> <p>content</p> <p>content</p> <p>content</p> <p>content</p>
</div>

Alt text

问题:为什么 div 的左上角被覆盖了,而文本却没有被覆盖,float不是应该跟普通流不在一个层级吗?是因为float属性不生效吗?

float的定义和用法:

浮动元素会生成一个块级框,而不论它本身是何种元素

float当初设计的时候就是为了使文本围绕在浮动对象的周围

绝对定位 (absolute positioning)

  • 绝对定位方案,盒从常规流中被移除,不影响常规流的布局;
  • 它的定位相对于它的包含块,相关CSS属性:topbottomleftright
  • 如果元素的属性positionabsolutefixed,它是绝对定位元素;
  • 对于position: absolute,元素定位将相对于上级元素中最近的一个relativefixedabsolute,如果没有则相对于body

触发BFC

  • 【1】根元素,即HTML元素
  • 【2】浮动元素,float的值不为none
  • 【3】overflow的值不为visible (为hiddenautoscroll)
  • 【4】display的值为inline-blocktable-celltable-caption;(与浮动的效果类似)
  • 【5】定位元素,position的值为absolutefixed

display:table也可以生成BFC的原因在于Table会默认生成一个匿名的table-cell,是这个匿名的table-cell生成了BFC

BFC布局规则:

  • 1、内部的Box会在垂直方向,一个接一个地放置。(与常规流中的块级元素及行内元素相同)
  • 2、内部的Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Boxmargin会发生重叠
  • 3、每个元素的margin box的左边, 与包含块(父级块)border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此(这说明BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界)
  • 4、BFC的区域不会与float box重叠
  • 5、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
  • 6、计算BFC的高度时,浮动元素也参与计算

Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠

1
2
3
4
5
6
7
8
9
10
11
12
<head>
div{
width: 100px;
height: 100px;
background: lightblue;
margin: 100px;
}
</head>
<body>
<div></div>
<div></div>
</body>

Alt text

因为两个div 元素都处于同一个 BFC 容器下 (这里指 body 元素) 所以第一个 div 的下边距和第二个 div 的上边距发生了重叠,所以两个盒子之间距离只有 100px,而不是 200px

这不是 CSS bug,这是·的一种规范,如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中(详见 BFC的作用4)。

每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此

1
2
3
4
5
<div class="par">
<div class="child"></div>
<!-- 给这两个子div加浮动,浮动的结果,如果没有清除浮动的话,父div不会将下面两个div包裹,但还是在父div的范围之内。-->
<div class="child"></div>
</div>

左浮是子div的左边接触父div的borderbox的左边,右浮是子div接触父div的borderbox右边,除非设置margin来撑开距离,否则一直是这个规则

BFC的区域不会与float box重叠

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="aside"></div>
<div class="text">
<div class="main"></div>
</div>
<!--下面是css代码-->
.aside {
width: 100px;
height: 150px;
float: left;
background: #f66;
}
.main {
height: 200px;
overflow: hidden;//触发main盒子的BFC
background: #fcc;
}
.text{
width: 500px;
}

上面aside盒子有一个浮动属性,覆盖了main盒子的内容,main盒子没有清除aside盒子的浮动。只做了一个动作,就是触发自身的BFC,然后就不再被aside盒子覆盖了。所以:BFC的区域不会与float box重叠。

Alt text

BFC有哪些作用:

  • 1、自适应两栏布局
  • 2、可以阻止元素被浮动元素覆盖
  • 3、可以包含浮动元素——清除内部浮动
  • 4、分属于不同的BFC时可以阻止margin重叠
  • 5、阻止因为浏览器因为四舍五入造成的多列布局换行的情况

自适应两栏布局

BFC的区域不会与float box重叠,因此会根据包含块(父div)的宽度,和aside的宽度,自适应宽度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="aside"></div>
<div class="main"></div>
<!--下面是css代码-->
.aside {
width: 100px;
height: 150px;
float: left;
background: #f66;
}
.main {
height: 200px;
overflow: hidden;//触发main盒子的BFC
background: #fcc;
}

Alt text

分属于不同的BFC时可以阻止margin重叠

1
2
3
4
5
6
<div class="container">
<p></p>
</div>
<div class="container">
<p></p>
</div>
1
2
3
4
5
6
7
8
9
.container {
overflow: hidden;
}
p {
width: 100px;
height: 100px;
background: lightblue;
margin: 100px;
}

这时候,两个盒子边距就变成了 200px

可以包含浮动元素——清除内部浮动

清除浮动原理:触发父divBFC属性,使下面的子div都处在父div的同一个BFC区域之内

阻止因为浏览器因为四舍五入造成的多列布局换行的情况

有时候因为多列布局采用小数点位的width导致因为浏览器因为四舍五入造成的换行的情况,可以在最后一列触发BFC的形式来阻止换行的发生。比如下面栗子的特殊情况

1
2
3
4
5
6
<div class="container">
<div class="column1">column 1</div>
<div class="column2">column 2</div>
<div class="column3">column 3</div>
</div>
<button>TOGGLE BLOCK FORMATTING CONTEXT</button>
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
.container {
min-height: 200px;
}

.column1,.column2 {
width: 31.3%;
background-color: green;
float: left;
min-height: 100px;
margin: 0 1%;
}

.column3 {
width: 31.3%;
background-color: green;
min-height: 100px;
margin: 0 1%;
}

.bfc {
overflow: hidden;
}


button {
margin-top: 30px;
}
1
2
3
4
5
6
7
8
9
var btn = document.querySelector("button"),
column3 = document.querySelector(".column3");
btn.addEventListener(
"click",
function() {
column3.classList.toggle("bfc");
},
false
);

BFC 与 Layout

IE 作为浏览器中的奇葩,当然不可能按部就班的支持 BFC 标准,于是乎 IE 中有了 Layout 这个东西。

LayoutBFC 基本是等价的,为了处理 IE 的兼容性,在需要触发 BFC 时,我们除了需要用触发条件中的 CSS 属性来触发 BFC

还需要针对 IE 浏览器使用zoom: 1来触发 IE 浏览器的 Layout

总结

1、Class 可以通过extends关键字实现继承,继承父类的所有属性和方法
2、父类子类没有部署任何代码,这两个类完全一样,等于复制了一个父类
3、子类必须在constructor方法中调用super方法,否则新建实例时会报错

  • 子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法
  • 如果不调用super方法,子类就得不到this对象
  • ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this)
  • ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this
  • 如果子类没有定义constructor方法,super方法会被默认添加
  • 在子类的构造函数中,只有调用super之后,才可以使用this关键字

4、父类的静态方法,也会被子类继承
5、Object.getPrototypeOf(),用来从子类上获取父类
6、super 关键字既可以当作函数使用,也可以当作对象使用

  • super作为函数调用,代表父类的构造函数 super()
    • ES6 要求,子类的构造函数必须执行一次super函数
    • super内部的this指的是子类的实例

      super虽然代表了父类A的构造函数,但是返回的是子类B的实例

      super内部的this指的是B的实例,因此super()在这里相当于A.prototype.constructor.call(this)

      super()执行时,它指向的是子类B的构造函数

    • super()只能用在子类的构造函数之中
  • super作为对象时 super.xxx
    • super作为对象在子类普通方法中,指向父类的原型对象(可以获取公有属性)
      • super.p()就相当于A.prototype.p()
      • 定义在父类实例上的方法或属性无法通过super调用(无法获取私有属性)
      • super可以取到定义在父类原型(父类.prototype.xxx)对象上的属性
      • 子类普通方法中通过super调用父类的方法时,方法内部的this指向当前的子类实例
      • 通过super对某个属性赋值,是赋值的子类实例的属性
    • super作为对象在子类静态方法之中,指向父类
      • 子类的静态方法中通过super调用父类的方法时,方法内部的this指向当前的子类,而不是子类的实例
  • 使用super的时候,必须显式指定是作为函数、还是作为对象使用(就是super后边必须跟东西),否则会报错
  • 可以在任意一个对象中,使用super关键字
    阅读全文 »

Class、实例new Class()、子类extends
1、ES6的constructor方法,就是构造方法,而constructor中的this关键字则代表实例对象
2、类本身就指向构造函数,Point === Point.prototype.constructor
3、类的所有方法都定义在类的prototype属性上面
4、constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法
5、一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加
6、constructor方法默认返回实例对象(即this
7、实例的私有属性都是显式定义在其本身(即定义在constructor中的this对象上)
8、实例的公有属性都是定义在原型上(即定义在class.prototype上)
9、在“类”的内部可以使用getset关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为
10、立即执行的 Class,const MyClass = new class {}(‘张三’)
11、类不存在变量提升,必须保证子类在父类之后定义,这一点与 ES5 完全不同
12、类的方法内部如果含有this,它默认指向类的实例,但是,必须非常小心,一旦单独使用该方法(调用时不是跟在实例后面),很可能报错,this指向该方法运行时所在的环境
13、在构造方法中(constructor)绑定(bind)this
14、在constructor中使用箭头函数定义方法(这个方法是私有的)
15、如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”
16、在实例上调用静态方法,会抛出一个错误,表示不存在该方法
17、静态方法中的this指的是类;静态方法可以与非静态方法重名
18、父类的静态方法,可以被子类继承
19、子类可以从super对象上调用父类的静态方法
20、实例属性可以定义在类的最顶层(实例属性一般定义在constructor()方法里面)
21、静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性
22、ES6 明确规定,Class 内部只有静态方法,没有静态属性
23、new.target一般用在构造函数之中,返回new命令作用于的那个构造函数
24、如果构造函数不是通过new命令或Reflect.construct()调用的,new.target会返回undefined
25、子类继承父类时,new.target会返回子类

阅读全文 »

语法:Object.defineProperty(obj, prop, descriptor)

1
Object.defineProperty(obj, prop, descriptor)

参数

参数名 是否必须 作用
obj 必需 目标对象
prop 必需 要定义或修改的属性的名称
descriptor 必需 将被定义或修改的属性描述符

返回值:被传递给函数的对象。即第一个参数obj

属性描述符有两种使用形式:数据描述和存取器描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//数据描述
Object.defineProperty(obj,"key",{
configurable:true | false,
enumerable:true | false,
value:任意类型的值,
writable:true | false
});

//存取器描述
Object.defineProperty(obj,"newKey",{
configurable: true | false
enumerable: true | false
get:function (){return xxx} | undefined,
set:function (value){} | undefined
});

数据描述符和存取描述符均具有

configurable:是否可以被删除或是否可以再次修改特性(writable, configurable, enumerable)

enumerable:是否可枚举

描述符 作用 属性值 默认值
configurable 目标属性是否可以被删除或是否可以再次修改特性(writable, configurable, enumerable)。 true,false false
enumerable 是否可枚举 当且仅当该属性为 true 时,目标属性才可以被枚举。 true,false false

数据描述符 独具

value:该属性对应的值

writable:value是否可以重写

描述符 作用 属性值 默认值
value 该属性对应的值 任何有效的 JavaScript 值(数值,对象,函数等) undefined
writable value是否可以重写 true,false false

存取描述符 独具

get当访问该属性时,该方法会被执行(必须return)

set当属性值修改时,触发执行该方法

当使用了get或set方法,不允许使用writable和value这两个属性

描述符 作用 属性值 默认值
get 一个给属性提供 getter 的方法,当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。 函数 undefined
set 一个给属性提供 setter 的方法,当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值 函数 undefined

直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

该方法允许精确添加或修改对象的属性。

通过赋值操作添加的普通属性是可枚举的,能够在属性枚举期间呈现出来(for...in Object.keys 方法), 这些属性的值可以被改变,也可以被删除。

这个方法允许修改默认的额外选项(或配置)比如是否只读不可以写;是否可以被for..inObject.keys()遍历。

默认情况下,使用 Object.defineProperty() 添加的属性值是不可修改的。

阅读全文 »

面向对象是编程思想,JAVAPHPC#C++.net(dot net)JS…这些都是面向对象编程的

面向过程编程思想:C语言是面向过程的

html、css:是标记语言不是编程语言,没有所谓的面向对象编程

less、sass:属于css预编译语言,旨在把css变为编程语言(面向对象的编程语言)

面向对象

JS本身就是基于面向对象创造出来的语言,而非是面向对象的语言

JS可以模拟实现继承封装,但是无法模拟实现多态,所以我们说JS是一门基于对象的语言,而非是面向对象的语言

JavaScript是通过原型(prototype)来实现面向对象编程

面向对象的三大特性:

1、封装

隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性

2、继承

提高代码复用性;继承是多态的前提。

3、多态

父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。

阅读全文 »

在很久以前JS中都是值类型的,没有引用数据类型,如果创建的变量或者函数名和之前的一样,会把之前存储的值替换掉;

真实项目中团队协作开发,如果是这样来处理,经常会导致相互代码冲突:‘全局变量污染’‘全局变量冲突’

后来js中诞生了对象数据类型,解决了上面出现的污染或冲突问题:把描述同一件事物的特征或者属性,进行归纳汇总,以此来避免全局变量之间的冲突

单例设计模式(Singleton Pattern)

我们把对象数据类型实现 把描述同一件事物的特征或者属性,进行"分组、归类"(存储在同一堆内存空间中)以此来避免全局变量之间的冲突问题**的方式和思想叫做:单例设计模式**

在真实项目中,为了实现模块化开发或者团队协作开发,我们经常应用单例模式(一般业务逻辑部分的代码都是依托单例模式设计规划的)

1、表现形式:

singleton不仅仅是对象名了,在单例模式中,singleton称之为“命名空间(nameSpace)

1
2
3
4
5
//单例模式
//singleton不仅仅是对象名了,在单例模式中,singleton称之为“命名空间(nameSpace)”
var singleton={
xxx:xxx
}

把描述同一件事物的属性或者方法存放在同一个命名空间下,多个命名空间中的属性和方法是互不干扰的

2、作用

把描述同一件事物的特征或者属性,进行"分组、归类"(存储在同一堆内存空间中)因此避免了全局变量之间的冲突和污染

3、单例模式的由来

每一个命名空间都是JS中Object这个内置类的实例,而实例之间是相互独立互不干扰的,所以我们称它为“单例:单独的实例”

阅读全文 »

this

指当前函数执行的主体(谁执行的函数this就是谁)

函数外面的this是window,我们一般都研究函数内的this指向问题

this是谁和它在哪定义的和它在哪执行的都没有任何关系

阅读全文 »

作用域【scope】又叫 【栈内存】

全局作用域:window

私有作用域:函数执行形成私有作用域

块级作用域:使用let 创建变量存在块级作用域

作用域链:当前作用域代码执行的时候遇到一个变量我们首先看一下它是否属于私有变量
如果是当前作用域的私有变量,那么以后再私有作用域中再遇到这个变量都是操作私有的(闭包:私有作用域保护私有变量不受外界干扰);
如果不是私有变量,向其上级作用域查找,也不是上级作用域私有的,继续向上查找,一直找到window全局作用域为止,我们把这种向上一级级查找的机制叫做作用域链
如果全局下有这个变量,操作的就是全局的;
如果全局下没有这个变量:1、设置:给全局对象window增加了属性名;2、获取:报错

查找私有变量

js中有且只有两种私有变量

1. 在私有作用域变量提升阶段声明过的变量或者函数
2. 形参也是私有变量
阅读全文 »