前端知识理解的笔记

html语义化的作用

  • 根据内容的结构使用适当的标签,便于开发者阅读和代码的结构优雅
  • 语义化标签会让网络爬虫和机器更好的解析页面,从而暴露给爬虫更多的有效数据。有利于seo
  • 语义化标签提高用户体验,比如title和alt属性,label标签的表单控制
  • 方便其他设备解析渲染网页,屏幕阅读器
  • 便于维护和开发。


react的diff算法理解

react利用虚拟dom和diff算法,进行新dom和旧dom的差异计算,再进行对应dom片段的真实dom更新,其算法有三个级别:tree(树)、component(组件)、element(元素),性能依次增强。

  • tree级别的diff算法,顾名思义,对一棵树进行diff算法,react必须检索整棵树,然后计算出差异片段,react利用先添加后删除的实现方法,更新整个dom,tree级别的diff影响性能,因此我们尽量避免在页面上有dom树层面的改动
  • component级别的diff算法,react的dom片段单位就是组件,定义一个class,就是定义了一个虚拟dom组件。组件进行diff算法,如果新的dom与旧的dom的组件不是同一个class,那么react认为其无法复用,直接删除旧组件,添加新的组件。因为我们定义的每一个class都有不同的dom结构,react不需要去检索dom结构。
  • element级别的diff算法,element级别的算法,同一等级的元素需要有唯一的key进行关联,让react可以新旧dom进行匹配。此级别中,react有三种行为:
    •   新的element不存在于旧dom中,插入新element
    •   旧element不存在新dom中,删除旧element
    •       新element存在旧dom,顺序发生改变,则进行移动dom

   在dom更新时,react会遍历一遍新的dom判断与旧dom的差异,diff算法的巧妙就在于,如果element只是位置发生了变化,如果进行删除增加的方法,影响性能。所          以react制定了一个规则去将旧dom排序。

    排序规则如下: 如果element在旧dom中的位置比新dom中的位置小,就将element右移,如果element在旧dom中的位置比新dom中的位置一样或者大,不改变它      的位置, react只需要改动前者,就会将位置差异的dom排列完成。

    比如一个dom列表为  A B C D , 将要渲染的dom列表变成了 B A D C , react会将B右移, D右移。从不会将A、C左移的操作。

react中的key的重要作用

在遍历插入组件时,我们常会设置一个key值给组件,这便是react的diff算法时需要的key,如果没有了这个key值,react没法进行新dom与旧dom中element的匹配,从而没法进行判断element是否只是位置发生了变化,因此只能进行删除和插入的操作,对dom的删除插入,因此降低性能。

vue和angular的双向数据绑定的实现

1. angular的双向数据绑定 - 脏检查机制

angular的$scope挂在了所有的双向数据绑定的属性,在页面渲染完毕后,angular会将所有的可能改变数据模式的行为进行监听,如事件、ajax请求、timeout等。一旦有这些行为需要触发,angular在每一个行为完成后都会进行$digist循环,来进行脏值检查,如果有新的值,那么angular就发布更新,使得响应到视图。

由于这个特性,因此我们用原生js或者jqeury等外部的行为改变数据模型的值,angular并无法检测,因此无法进入脏值检查阶段,这时候我们就需要$apply方法手动进入$digist循环,它会检查所有监听的内容。

2. vue的双向数据绑定  - 数据劫持

vue的双向数据绑定离不开Object.defineProperty方法,此方法无法兼容ie9以前,因此vue不兼容老版本ie浏览器。

vue在实例化过程中,保存了所有data中的属性,并且给每一个属性定义监听器,在定义监听器同时,会创建一个发布器,该发布器会添加订阅者到该属性下,当某一时刻,数据模型发生了改变,该发布器会触发响应,通知所有订阅者引起更新,通过订阅/发布模式来进行交互。

Promise的语法笔记

Promise纳入了es6标准之前,angular、jquery等的类Promise的实现,并非标准的 Promise,这里记录一下Promise的标准语法

1. Promise对象

var p = new Promise(function (resolve, reject) {
   setTimeout(function () {
       var ra = Math.random()
       ra < 0.5 ? resolve() : reject()  
    }, 1000)
})

p.then(function () {
  console.log('成功')
}, function () {
  console.log('失败')
})

new Promise() 构造函数建立一个Promise对象

其最常见的就是then方法,then方法可接收3个函数,一般传递2个,最常见传递1个。

分别为 成功回调、失败回调、完成回调

如果只想定义失败回调可以这样定义

var p = new Promise(function (resolve, reject) {
  // ...
})

p.then(null, function () {
  console.log('失败')
})

promise对象还有一个方法是catch,捕捉异常。利用这个方法改进上面方法

var p = new Promise(function (resolve, reject) {
  // ...
})

p.catch(function (err) {
  console.log('失败')
})

catch来处理所有的失败情况。

then方法可以多个调用,return不会终止then方法继续调用,如果需要终止then方法的往下执行,throw抛出异常。

var p = new Promise(function (resolve, reject) {
  // ...
})

p.then(function () {
  console.log('第一次then')
  //  未成功阻止
  return false
}).then(function (falg) {
  console.log('第二次then, falg = ' + flag)  // false
  throw new Error('终止')
}).then(function (){
  console.log('执行不到')
}).catch(function () {
  console.log('失败')
})

then方法中所有的return值都会传递给下一个then,就像一个加工流水线,一个一个往下传。一个then中执行一类操作。

2. 返回新的Promise对象

then方法中可以返回新的promise对象

p.then(function (res) {
  console.log('第一个Promise')
  //  未成功阻止
  return new Promise(function () {
    // ...
  })
}).then(function (res) {
  console.log('第二个Promise对象')

}).catch(function () {
  console.log('失败')
})

第一个then中return的Promise内,resolve的值会传递给第二个then的res参数。

3. Promise.all 并行执行所有promise对象

var arr = []
arr[0] = new Promise(function (resolve, reject) {
  // ...
})
arr[1] = new Promise(function (resolve, reject) {
  // ...
})

Promise.all(arr).then(function (resArr) {
  // ..
}).catch(function (err) {
  // ..
})

执行所有Promise对象,resArr保存着相对应的结果

4. Promise.resolve()

Promise.resolve().then(function () {
  console.log('开始')
}).catch(function (err) {
  // ..
})

console.log('最后')

//  最后 
//  开始

Promise.resolve方法直接返回一个发布成功的Promise,此方法用来将then方法延迟,如上。then方法会延迟到当前函数栈调用的最后,因此改变了console.log的顺序

原文地址:https://www.cnblogs.com/xujiazheng/p/6854962.html