cosyer's Blog

Blog


  • 首页

  • 友链

  • 留言板

  • 归档

  • 关于

  • 搜索
9月
08
更新于
9月08
2020
知识

主流浏览器的内核和渲染方式解读

发表于 2018-07-05 | 热度 ℃
| 字数统计: 969 (字) | 阅读时长: 4 (分钟)

浏览器内核

  • Trident:IE,360,搜狗

  • Gecko:firefox

  • webkit:safari,旧版chrome

  • presto:旧版opera

  • blink(webkit的一个分支):新版chrome,新版opera

浏览器的渲染方式

  1. 构建DOM树 浏览器请求到html代码后,在生成DOM的最开始阶段,并行发起css、图片、js的请求。(解码->令牌化->词法分析->dom树创建)

  2. 构建CSSOM css文件加载完成,开始构建CSSOM(CSSOM只输出包含有样式的节点)

  3. 生成渲染树(Render Tree) CSSOM构建结束后,和DOM一起生成Render Tree

  4. 计算渲染树布局(Layout) 有了Render Tree,浏览器已经能知道网页中有哪些节点,各个节点的CSS定义以及他们的从属关系。依照盒子模型,计算出每个节点在屏幕中的位置及尺寸。

  5. 将布局Paint绘制到屏幕上 布局之后,浏览器知道哪些节点要显示,每个节点的CSS属性是什么,每个节点在屏幕中的位置。所以接下来按照算出来的规则,通过显卡,把内容画在屏幕上。

render

CSS阻塞渲染:由于CSSOM负责存储渲染信息,浏览器就必须保证在合成渲染树之前,CSSOM是完备的,这种完备是指所有的CSS(内联、内部和外部)都已经下载完,并解析完,只有CSSOM和DOM的解析完全结束,浏览器才会进入下一步的渲染。CSS阻塞渲染意味着,在CSSOM完备前,页面将一直处理白屏状态,这就是为什么样式放在head中,仅仅是为了更快的解析CSS,保证更快的首次渲染。 JS阻塞页面:JS可以操作DOM来修改DOM结构,可以操作CSSOM来修改节点样式,这就导致了浏览器在解析HTML时,一旦碰到script,就会立即停止HTML的解析,也阻塞了其后的CSS解析,整个解析进程必须等待JS的执行完成才能够继续。从性能角度上讲,将script放在页面底部,也就合情合理了。

重绘(Repaint):

当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来后,浏览器便把这些元素都按照各自的特性绘制了一遍,于是页面的内容出现了,这个过程称之为repaint。

  • 重绘(repaint): 当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要UI层面的重新像素绘制,因此 损耗较少。

触发重绘

  1. DOM改动
  2. CSS改动

重排(Reflow):

DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式来计算并根据计算结果将元素放到它该出现的位置,这个过程称之为reflow。

  • 回流(reflow): 当元素的尺寸、结构或触发某些属性时,浏览器会重新渲染页面,称为回流。此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。

触发重排

  1. 当增加、删除、修改DOM节点时,会导致reflow或repaint
  2. 当移动DOM的位置,或是插入动画的时候
  3. 当修改CSS样式的时候
  4. 当Resize窗口的时候,或是滚动的时候
  5. 当修改网页的默认字体时

最小化重绘和重排

  1. 避免频繁使用 style,而是采用修改class的方式。

  2. 批量修改DOM:使用文档片段创建一个子树,然后再拷贝到文档中(document.fragment)使用createDocumentFragment进行批量的 DOM 操作。

  3. 缓存布局信息

  4. 对于 resize、scroll 等进行防抖/节流处理。

9月
07
更新于
9月07
2020
知识

js判断数据类型

发表于 2018-10-31 | 热度 ℃
| 字数统计: 541 (字) | 阅读时长: 3 (分钟)

typeof

typeof一般只能返回如下几个结果:number,boolean,string,function,object,undefined字符串

对于Array,null等特殊对象使用typeof一律返回object,这正是typeof的局限性。

typeof表示是对某个变量类型的检测,基本数据类型除了null都能正常的显示为对应的类型,引用类型除了函数会显示为’function’,其它都显示为object。

1
2
3
var fn = new Function ('a', 'b', 'return a + b')

typeof fn // function

instanceof

instanceof适用于检测对象,它是基于原型链运作的。

instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。换种说法就是如果左侧的对象是右侧对象的实例, 则表达式返回true, 否则返回false 。

instanceof对基本数据类型检测不起作用,因为基本数据类型没有原型链。可以准确的判断复杂数据类型。

1
2
3
4
5
6
7
8
9
10
11
[1, 2, 3] instanceof Array // true 
/abc/ instanceof RegExp // true
({}) instanceof Object // true
(function(){}) instanceof Function // true

// 基于constructor
a.constructor === Array;
// 基于Object.prototype.isPrototypeOf
Array.prototype.isPrototypeOf(a);
// 4.基于getPrototypeOf
Object.getPrototypeOf(a) === Array.prototype;

Object.prototype.toString.call

可以检测各种数据类型,推荐使用。

1
2
3
4
5
6
7
8
9
10
Object.prototype.toString.call([]); // => [object Array] 
Object.prototype.toString.call({}); // => [object Object]
Object.prototype.toString.call(''); // => [object String]
Object.prototype.toString.call(new Date()); // => [object Date]
Object.prototype.toString.call(1); // => [object Number]
Object.prototype.toString.call(function () {}); // => [object Function]
Object.prototype.toString.call(/test/i); // => [object RegExp]
Object.prototype.toString.call(true); // => [object Boolean]
Object.prototype.toString.call(null); // => [object Null]
Object.prototype.toString.call(); // => [object Undefined]
1
2
3
4
5
6
7
8
9
let isType = type => obj => {
return Object.prototype.toString.call( obj ) === '[object ' + type + ']';
}

var isString = isType( 'String' );
var isArray = isType( 'Array' );
var isNumber = isType( 'Number' );

console.log( isArray( [ 1, 2, 3 ] ) ); //true

constructor

constructor也不是保险的,因为constructor属性是可以被修改的,会导致检测出的结果不正确。

1
2
3
4
5
6
7
8
9
10
11
12
console.log([].constructor === Array)   // true
function a() {}
console.log(a.constructor === Function) // true
console.log(12.constructor === Number) // true
console.log('22'.constructor === String) // true
console.log([] .constructor === Array) // true
console.log({a: 1}.constructor === Object) // true
console.log(true.constructor === Boolean) // true
console.log(json.constructor === Object) // true
console.log((new Date()).constructor === Date) // true
console.log(reg.constructor === RegExp) //true
console.log(error.constructor === Error) // true
9月
07
更新于
9月07
2020
JS

EventLoop

发表于 2019-06-16 | 热度 ℃
| 字数统计: 2,091 (字) | 阅读时长: 9 (分钟)

描述事件队列的过程?

  • js是单线程的,会出现阻塞问题,因此有了任务队列的出现
  • 主线程同步执行任务,异步的工作一般会交给其他线程完成,然后回调函数会放到任务队列中
  • 等候主线程执行完毕后再执行任务队列中的操作

event-queue

同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;

异步任务指的是,不进入主线程、而进入”任务队列”(task queue)的任务,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。只要异步任务有了运行结果,就在”任务队列”之 中放置一个事件。

task-queue 任务队列中存着的是异步任务,这些异步任务一定要等到执行栈清空后才会执行。

同步就是发出一个请求后什么事都不做,一直等待请求返回后才会继续做事;异步就是发出请求后继续去做其他事,这个请求处理完成后会通知你,这时候就可以处理这个回应了。


阅读全文 »
9月
03
更新于
9月03
2020
知识

网页埋点相关知识

发表于 2018-07-25 | 热度 ℃
| 字数统计: 1,062 (字) | 阅读时长: 4 (分钟)

埋点的需求:一个网站上线,开发者除了保证网站功能正常,体验优好之外,还有一项重要的工作是数据收集,通过收集用户的行为数据可以帮助了解网站的功能是否满足用户的需求,导流方式是否有效,新功能上线后是否效果是否达到设计初衷,根据数据指引有效优化产品体验以及发现新的产品方向是产品经理的必备技能,而如何采集准确并且足够的网站数据则应该是开发者的责任.在大数据处理能力越来越强下,以及机器学习等依赖数据哺育的工具进化下,采集足够多的数据往往是网站向着良性方向进化的必备条件


阅读全文 »
9月
03
更新于
9月03
2020
知识

\[1,2,3\]是JSON吗?

发表于 2018-11-21 | 热度 ℃
| 字数统计: 815 (字) | 阅读时长: 3 (分钟)

A: “这个接口我传个 JSON 给你,格式是这样的 ‘[1, 2, 3]’”

B: “等下,这不是数组吗,JSON 应该有键啊,类似这样才行’{ “key”: [1, 2, 3] }’”

A: “不,这就是 JSON 格式的数据”

B: “啊,是吗?” 你是否也有这样的疑惑? wappalyzer chrome网页分析插件


阅读全文 »
9月
03
更新于
9月03
2020
CSS

前端动画的实现方式总结

发表于 2020-04-30 | 热度 ℃
| 字数统计: 1,362 (字) | 阅读时长: 6 (分钟)

通常在前端中,实现动画的方案主要有6种:

  • js 直接实现

  • SVG(可伸缩矢量图形

  • CSS3 transition

  • CSS3 animation

  • Canvas动画

  • requestAnimationFrame


阅读全文 »
8月
31
更新于
8月31
2020
知识

微信小程序面试题

发表于 2018-06-18 | 热度 ℃
| 字数统计: 2,085 (字) | 阅读时长: 8 (分钟)

简单描述下微信小程序的相关文件类型?

答:微信小程序项目结构主要有四个文件类型,如下: 一、WXML (WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。内部主要是微信自己定义的一套组件。 二、WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式, 二、js 逻辑处理,网络请求 三、json 小程序设置,如页面注册,页面标题及tabBar。 四、app.json 必须要有这个文件,如果没有这个文件,项目无法运行,因为微信框架把这个作为配置文件入口,整个小程序的全局配置。包括页面注册,网络设置,以及小程序的window背景色,配置导航条样式,配置默认标题。 五、app.js 必须要有这个文件,没有也是会报错!但是这个文件创建一下就行 什么都不需要写以后我们可以在这个文件中监听并处理小程序的生命周期函数、声明全局变量。 六、app.wxss


阅读全文 »
8月
31
更新于
8月31
2020
Ng

angular7详解

发表于 2018-12-19 | 热度 ℃
| 字数统计: 1,277 (字) | 阅读时长: 6 (分钟)

开始准备

  1. 安装nodejs

    1
    npm -v
  2. 安装@angular/cli

    1
    npm i -g @angular/cli
  3. CLI命令建立项目

    1
    ng new ng7demo

    选择是否加入路由模块以及哪种css预处理器

可ctrl+c取消自动安装node_modules,手动进入项目npm install node-sass安装不上可切换淘宝镜像库或者用cnpm安装

  1. npm config set registry https://registry.npm.taobao.org npm install

or

  1. npm install -g cnpm cnpm install

  2. 启动项目

    1
    ng serve --open // 自动打开浏览器 http://localhost:4200/

阅读全文 »
8月
31
更新于
8月31
2020
JS

javascript设计模式

发表于 2019-12-18 | 热度 ℃
| 字数统计: 3,498 (字) | 阅读时长: 15 (分钟)

概念

设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢 的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。

设计原则(5个)

S – Single Responsibility Principle 单一职责原则

  • 一个程序只做好一件事
  • 如果功能过于复杂就拆分开,每个部分保持独立

O – OpenClosed Principle 开放/封闭原则

  • 对扩展开放,对修改封闭
  • 增加需求时,扩展新代码,而非修改已有代码

L – Liskov Substitution Principle 里氏替换原则

  • 子类能覆盖父类
  • 父类能出现的地方子类就能出现

I – Interface Segregation Principle 接口隔离原则

  • 保持接口的单一独立
  • 类似单一职责原则,这里更关注接口

D – Dependency Inversion Principle 依赖倒转原则

  • 面向接口编程,依赖于抽象而不依赖于具
  • 使用方只关注接口而不关注具体类的实现

设计模式的类型

如果从作用上来划分,JavaScript设计模式大概分为五种设计类型:

创建型设计模式 结构型设计模式 行为型设计模式 技巧型设计模式 架构型设计模式
简单工厂模式 外观模式 模板方法模式 链模式 同步模块
工厂方法模式 适配器模式 观察者模式 委托模式 异步模块模式
抽象工厂模式 代理模式 状态模式 数据访问对象模式 Widget模式
建造者模式 装饰者模式 策略模式 节流模式 MVC模式
原型模式 桥接模式 职责链模式 简单模板模式 MVP模式
单例模式 组合模式 命令模式 惰性模式 MVVM模式
享元模式 访问者模式 参与者模式
中介者模式 等待者模式
备忘录模式
迭代器模式
解释器模式

阅读全文 »
8月
31
更新于
8月31
2020
知识

实现前端路由

发表于 2018-11-24 | 热度 ℃
| 字数统计: 1,788 (字) | 阅读时长: 8 (分钟)

现代的前端框架react/vue/angular都有路由router的概念,通过手写实现可以帮助我们更好地了解它的工作原理。它们都推荐单页面应用 SPA 开发模式,在路由切换时替换 DOM Tree 中最小修改的部分 DOM,来减少原先因为多页应用的页面跳转带来的巨量性能损耗。它们都有自己的典型路由解决方案,@angular/router、react-router、vue-router等。

一般来说,这些路由插件总是提供两种不同方式的路由方式: Hash 和 History,有时也会提供非浏览器环境下的路由方式 Abstract(支持所有 JavaScript 运行 环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式)。

实现路由的2种方式

  1. hash模式 状态保存需要另行传递
  2. history模式 原生提供了自定义状态传递的能力

缺点

hash: 地址栏会多出一个#号,对url造成影响,在某些场景下如微信支付有坑。 history: 兼容性差,直接访问报404,需要服务器做处理。

基本原理

  • hash 主要原理是通过监听 # 后的 URL 路径标识符的更改而触发的浏览器 hashchange 事件(当 location.hash 发生改变时,将触发这个事件)

注意: Hash 方法是利用了相当于页面锚点的功能,所以与原来的通过锚点定位来进行页面滚动定位的方式冲突,导致定位到错误的路由路径,因此需要采用别的办法。

  • history 则基于 pushState 和 popState replaceState

Hash 模式是使用 URL 的 Hash 来模拟一个完整的 URL,因此当 URL 改变的时候页面并不会重载。History 模式则会直接改变 URL,所以在路由跳转的时候会丢失一些地址信息(只是动态的通过js操作window.history来改变浏览器地址栏里的路径,并没有发起http请求),在刷新或直接访问路由地址的时候会匹配不到静态资源。因此需要在服务器上配置一些信息,让服务器增加一个覆盖所有情况的候选资源。

history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。


阅读全文 »
1…456…16
陈宇(cosyer)

陈宇(cosyer)

不去做的话永远也做不到。

159 日志
10 分类
51 标签
RSS
GitHub Twitter E-Mail FB Page
推荐阅读
  • Callmesoul
  • JsTips
  • Personal Site
  • Resume
© 2021 陈宇(cosyer)
终于等到你(UV):   |   欢迎再来(PV):
Blog总字数: 312.5k字
苏ICP备17005342号-1