BFC 浅谈
写在前面
Block formatting context (块级格式化上下文)
一块独立的渲染区域、内部元素的渲染不会影响边界以外的元素
页面文档由块block
构成 每个block
在页面上占据自己的位置
使用新的元素构建BFC overflow:hidden | auto | scroll; 只要不为visible
新的空间
告诉浏览器,外面的环境影响不到我了 我重新来进行Block formatting 布局和定位
核心:
新的BFC,给出了新的不受外界影响的块级格式化环境
block 块级-> 页面的基础
formatting context 格式化-> 渲染
浏览器构建文档树的时候 布局和定位元素
网页的定位(大) 文档流正常,浮动,定位,flex,table
广义的定位 块级元素的定位 垂直的定位;行内元素 左右定位 通过内容来确定
狭义的定位:
float 浮动元素,在一行的开始或者结束
flex 弹性布局
position
BFC 在正常的文档流里面重建一个新的上下文环境
BFC的约束规则
stylus之变量与mixin
混合书写(Mixins)
变量
- 在
stylus
中 可以将常用的样式像表达式中变量赋值一样保存给一个变量、如下: bg_color = #123456; box_size = 100px;
.box background-color bg_color width box_size height box_size
|
编译后:.box { background-color: #123456; width: 100px; height: 100px; }
|
- 属性查找
Stylus有另外一个很酷的独特功能,不需要分配值给变量就可以定义引用属性。下面是个很好的例子,元素水平垂直居中对齐(典型的方法是使用百分比和margin负值),如下:#logo position: absolute top: 50% left: 50% width: w = 150px height: h = 80px margin-left: -(w / 2) margin-top: -(h / 2)
|
在stylus
中可以不使用这里的变量w和h, 而是简单地前置@
字符在属性名前来访问该属性名对应的值:#logo position: absolute top: 50% left: 50% width: 150px height: 80px margin-left: -(@width / 2) margin-top: -(@height / 2)
|
混合书写
- 混合书写和函数定义方法一致,但是应用却大相径庭。
例如,在书写Css3
样式时我们经常要进行兼容性处理,需要在属性前加上相应的前缀,下面有定义的border-radius(n)方法,其却作为一个mixin(如,作为状态调用,而非表达式)调用。
bg_color = #123456; box_size = 100px;
border-radius(n) -webkit-border-radius n -moz-border-radius n -ms-border-radius n -o-border-radius n border-radius n .box background-color bg_color width box_size height box_size border-radius(5px) ``` 进一步,我们可以利用arguments这个局部变量,传递可以包含多值的表达式,这样就可以給属性传递多个值。 ```css border-radius() -webkit-border-radius arguments -moz-border-radius arguments -ms-border-radius arguments -o-border-radius arguments border-radius arguments
|
Stylus
支持通过使用{}字符包围表达式来插入值,其会变成标识符的一部分。例如,-webkit-{‘border’ + ‘-radius’}等同于-webkit-border-radius
.
再进一步,在stylus中我们还可以对border-radius再做进一步的处理 类似与js中的函数封装 ,如下(这样对于任何需要做兼容性处理的属性 我们只需要调用两次mixin出入所需参数,大大的简化了一下琐碎代码工作):
vendor(prop,args) -webkit-{prop} args -moz-{prop} args -ms-{prop} args -o-{prop} args {prop} args
border-radius(n) vendor('border-radius',arguments) box-shadow(n) vendor('boa-shadow',arguments) .box background-color bg_color width box_size height box_size border-radius(5px)
|
编译后:
.box { background-color: #123456; width: 100px; height: 100px; -webkit-border-radius: 5px; -moz-border-radius: 5px; -ms-border-radius: 5px; -o-border-radius: 5px; border-radius: 5px; -webkit-box-shadow: 1px 1px 10px rgba(0,0,0,0.5); -moz-box-shadow: 1px 1px 10px rgba(0,0,0,0.5); -ms-box-shadow: 1px 1px 10px rgba(0,0,0,0.5); -o-box-shadow: 1px 1px 10px rgba(0,0,0,0.5); box-shadow: 1px 1px 10px rgba(0,0,0,0.5); }
|
如何手动实现一个New操作
写在前面
在所有的前端面试中常常喜欢考面试者如何手写一个new操作符,作为在准备秋招的大三党,我也要考虑这些。
那么我们先看看new操作符都干了什么事情,有哪些操作?通过下面的代码来进行思考:
function Otaku(name, age) { this.name = name; this.age = age; this.habit = 'pk'; }
Otaku.prototype.strength = 60; Otaku.prototype.sayYourName = function () { console.log('I am ' + this.name); }
const person = new Otaku('乔峰',5000); person.sayYourName(); console.log(person); ``` ![控制台打印结果](http://p9utic4op.bkt.clouddn.com/new.png)
## 解析
从控制台打印出来的结果我们可以看出new操作符大概做了一下几件事情:
1. 返回(产生)了一个新的对象 2. 访问到了类Otaku构造函数里的属性 3. 访问到Otaku原型上的属性和方法 并且设置了this的指向(指向新生成的实例对象) 通过上面的分析展示,可以知道new团伙里面一定有Object的参与,不然对象的产生就有点说不清了。 先来边写写:
```js
const person = new Otaku('乔峰',5000); const person1 = objectFactory(Otaku, '鸠摩智', 5000);
function objectFactory(obj, name, age) {}
function objectFactory() { console.log(arguements); const Constructor = [].shift.call(arguments); const args = arguments; let obj = new Object(); Constructor.call(obj,...args); return obj; }
```
- 上面的代码注释太多,剔除注释以后的代码:
```js function objectFactory() { let Constructor = [].shift.call(arguments); const obj = new Object(); obj.__proto__ = Conctructor.prototype; Constructor.call(obj,...arguments); return obj; } ``` - 还有另外一种操作:
```js function myNew(Obj,...args){ var obj = Object.create(Obj.prototype); Obj.apply(obj,args); return obj; }
|
React Hook学习
Hooks 在React 16.8 以上的版本中才可以使用
eslint-plugin-react-hooks
Hook 定义
Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数
。
React中的Refs
Refs
官方说明: Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素
。
在React开发中、想要操作元素的状态一般是修改State、或者是修改传入的props。但是有时候一些效果不能通过如此操作实现,例如开发中常常碰到的:
- 输入框的焦点获取、比如打开登录界面登录框自动获取焦点
- 动态的根据一个元素的大小/距离 计算另外一个元素的大小
使用 Ref
目前的React版本(16.11.0)中 Refs
的用法如下:
import React form 'react'; class MyComponent extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); }
render() { return <div ref={this.myRef} />; } }
|
对于节点的访问:
const node = this.myRef.current;
|
说明:
- 1.通过调用 React.createRef 创建了一个 React ref 并将 DOM节点的引用current赋值给 this.myRef 变量。
- 指定 ref 为 JSX 属性,将this.myRef 传入; ref 和 key 一样不属于 props属性,二者都会被 React 特殊处理和维护。
- ref 挂载以后,ref.current 指向 ref 所在节点
如果之前用过 React,你可能了解之前的 ref 可以通过 this.refs.inputRef 来访问 DOM 节点、如下所示,这个 ref 是字符串类型的,在使用上来说似乎更加方便。现在官方版本不建议再使用它,因为 string 类型的 refs 存在问题。它属于过时
API 并可能会在未来的版本被移除。
import React form 'react'; class MyInput extends React.Component { componentDidMount() { this.refs.inputRef.focus(); } render() { return <input ref="inputRef" />; } }
|
Ref的值
官方文档中有说明,ref 的值根据节点的类型不同而有所不同:
- 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 对象 接收底层 DOM 元素作为其 current 属性。可以访问元素的宽高等属性、input框还可以调用focus方法实现自动聚焦
- 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性。即可以通过 current
调用组件中的方法
不能在函数组件上使用 ref 属性,因为他们没有实例。
回调 Refs
更加精细的控制 refs 的传递, 可以达到类似 props 的传递效果,在需要的地方传入inputRef
function CustomTextInput(props) { return ( <div> <input ref={props.inputRef} /> </div> ); }
class Parent extends React.Component { render() { return ( <CustomTextInput inputRef={el => this.inputElement = el} /> ); } }
|
官方说明:
如果 ref 回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数 null,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。
Refs 转发
ref Hook
useRef() 是 React 提供的在 Hooks 中获取 DOM 元素的方法。
使用方法如下:
import React, { useRef} from 'react'; function RefDemo(){ const inputEl = useRef(null); const onButtonClick=()=>{ inputEl.current.value="Hello, Ref"; console.log(inputEl); }; return ( <> {/*保存input的ref到inputEl */} <input ref={inputEl} type="text"/> <button onClick = {onButtonClick}>展示</button> </> ); } export default RefDemo;
|
官方文档
数组
数组
定义:
一个存储元素的线性集合, 元素可以通过索引(通常为数字)来任意存取。
数字索引在内部被转换为字符串类型、这是因为在javaScript中对象的属性名必须是字符串。而数组只是一种特殊的对象
创建数组
- 通过
构造函数
<!-- 传入一组元素进行数组初始化 --> var arr = New Array(1, 2, 3, 4, 5); print(arr.length); <!-- 只传一个元素,声明数组的初始化长度, 其中每个元素初始化为 undefined --> var arr1 = new Array(10); print(arr1.length);
|
JS 基本数据类型和引用类型
Js 基本数据类型
js基本数据类型包括:undefined
, null
, number
, boolean
, string
, symbol
, bigInt(新增)
。基本数据类型是按值访问的,就是说我们可以操作保存在变量中的实际的值
1.基本数据类型的值是不可改变的
任何方法都无法改变一个基本类型的值是不可改变的,比如一个字符串:
var name = "change"; name.substr(); console.log(name);
var s = "hello"; s.toUpperCase() console.log(s)
|
通过这两个例子, 我们原来发现定义的变量 name 的值始终没有发生改变,而调用 substr() 和 toUpperCase() 方法后返回的是一个新的字符串,跟原先定义的变量 name 并没有关系
按值访问
按值进行访问,操作的是保存在变量中实际的值
不可添加方法属性
基础类型的比较是值的比较
基础类型存放在栈区 变量标识符 + 变量值
引用类型
同时保存在栈区和堆区中
栈区保存变量标识符和指向堆区的方法
基本包装类型(包装对象)
性能优化之浏览器篇
把 Css 放在head 中加载
在浏览器解析完head 部分后、让浏览器知道需要引入哪些css文件,开始并行的去下载css资源,一边下载Css文件一边解析Html, 能够使页面更早的开始渲染
- 让页面更早的开始渲染、避免闪屏 (DOM 结构先加载出来,css慢了一拍 页面重新渲染)
- 最好能包含关键渲染路径的样式、首页的样式应该尽快的完成加载、提高用户体验
JS放在 body 标签结束前加载
js 资源的加载会阻塞 HTML 的解析 和 Css的渲染
不使用CSS 表达式
在css属性后使用 expression() 连接一段JavaScript表达式,css属性的值是JavaScript表达式的结果。
background-color: expression((new Date()).getHours()%2?"#FFFFFF": "#000000" );
|
看似强大, 实际性能开销很大,可能导致页面卡顿
表达式的问题就在于它的计算频率要比我们想象的多。不仅仅是在页面显示和缩放时,就是在页面滚动、乃至移动鼠标时都会要重新计算一次。给 CSS 表达式增加一个计数器可以跟踪表达式的计算频率。在页面中随便移动鼠标都可以轻松达到 10000 次以上的计算量。
calc() 性能待验证
移除无匹配的样式
移除无匹配的样式,有两个好处:
用外链的方式引入css 和 js
- 通过使用外链可以减少html 文件的体积
- 作为外链文件、Css/Js 可以作为静态资源、通过合理的利用浏览器的缓存对需要的文件进行缓存; 在第二次访问时可以加快页面的加载速度
不要重复加载JS
- 在IE中,例如在加载一个jquery以后再加载一个jquery,仍然是算作两个不同的请求,不能发挥缓存的优势
- 重复加载js意味着更长的JS执行时间
用 Get 方式发起 Ajax 请求
- Get 方式可以缓存
- 如果是获取信息 Get 更加语义化
如果是提交数据 使用Post 更加语义化
组件延迟加载
规划页面中引用的姿态资源加载顺序、优先级的能力
保障关键页面资源的优先加载: 浏览器的并发数限制
在同一个域名下面,一般现代浏览器的并发数为6
按需加载 Lazyload 典型: 电商网站
在图片比较多的电商网站中,lazyload 十分实用 data-src -> src
避免在页面中使用iFrame
- 会阻塞父文档的
onload
事件
- 即使是空白iFrame 也比较耗时
减少COOKIE体积
- COOKIE每次请求都会全都带上
COOKIE了解更多
每次请求跟主文档相关的信息,所有的cookie都会带上
减少 JS 中的 DOM 访问
JS中对DOM 的访问是不可避免的, 但可以进行一下优化
- 对于查找到的元素, 先将其缓存在变量中
- 节点增加时合理利用
DocumentFragment
- 不要用JS 去频繁修改样式
使用常见的图片优化手段
相比代码, 图片的体积很大
不要在HTML中缩放图片
在实际中使用什么尺寸的图片就提供多大尺寸的图片
- 徒增渲染开销, 提供适当尺寸即可
不要把图片的src置空
- 在主流浏览器中 IE、Chrome、FireFox 都会引发指向当前主文档的额外请求
参考文档
高性能 CSS