# 前端爱好者学习周刊:第8期

20200328

html
css
js

# 1.redux-devtools

chrome中下载redux-devtools

在项目中配置:

import { applyMiddleware, combineReducers, createStore, } from 'redux'
import { routerReducer } from 'react-router-redux'
import reducers from '../reducers'
import { composeWithDevTools } from 'redux-devtools-extension'

const store = createStore(
    combineReducers({
        ...reducers,
        routing: routerReducer
    }),
    composeWithDevTools(applyMiddleware(thunkMiddleware))
)

export default store

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

redux-devtools (opens new window)

# 2.redux-logger

import { applyMiddleware, createStore } from 'redux';
 
// Logger with default options
import {createLogger} from 'redux-logger'

const store = createStore(
  reducer,
  applyMiddleware(logger)
)
1
2
3
4
5
6
7
8
9

配置项:

{
  predicate, // if specified this function will be called before each action is processed with this middleware.
  collapsed, // takes a Boolean or optionally a Function that receives `getState` function for accessing current store state and `action` object as parameters. Returns `true` if the log group should be collapsed, `false` otherwise.
  duration = false: Boolean, // print the duration of each action?
  timestamp = true: Boolean, // print the timestamp with each action?
 
  level = 'log': 'log' | 'console' | 'warn' | 'error' | 'info', // console's level
  colors: ColorsObject, // colors for title, prev state, action and next state: https://github.com/evgenyrodionov/redux-logger/blob/master/src/defaults.js#L12-L18
  titleFormatter, // Format the title used when logging actions.
 
  stateTransformer, // Transform state before print. Eg. convert Immutable object to plain JSON.
  actionTransformer, // Transform action before print. Eg. convert Immutable object to plain JSON.
  errorTransformer, // Transform error before print. Eg. convert Immutable object to plain JSON.
 
  logger = console: LoggerObject, // implementation of the `console` API.
  logErrors = true: Boolean, // should the logger catch, log, and re-throw errors?
 
  diff = false: Boolean, // (alpha) show diff between states?
  diffPredicate // (alpha) filter function for showing states diff, similar to `predicate`
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 3.分享开发多个线上项目后总结的 HTTP 接口设计方案 (opens new window)

虽然更多的应该后台看,但是感觉看了后,能够增加自己和后台沟通的自信

  • url原则:path部分——系统/模块/操作(app/account/create-user)
  • 空值处理:在数据传输中,如果某个字段是空值,则直接省略此字段不传,减少网络开销
  • 嵌套>平铺:
{
	id:'1',
	name:'zhangsan'
	creator:{
		id:'1',
		name:'aaf',
		avatar:''
	}
}
1
2
3
4
5
6
7
8
9
  • 响应体:
code:'ok',
message:'',
data:{},
error:{
	title:'输入重复'
}
1
2
3
4
5
6

想起前几天的一个需求,后台要给我返回名称重复的校验,按我们的框架,可以将error写在data下面

# 4. 判断是数组的几种方法

JS判断是否是数组的四种做法 (opens new window)

最完整方法:

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}
1
2
3
4
5

# 1.Array.isArray([])

隐患: ES5之前可能会存在不支持此方法

# 2.Object.prototype.toString.call([])

# 3.[] instanceof Array

instanceof运算符用于检验构造函数的prototype属性是否出现在对象的原型链中的任何位置,返回一个布尔值

隐患:

  • prototype属性是可以修改的;所以不一定准确
  • 脚本拥有多个全局环境,例如html中拥有多个iframe对象,instanceof的验证结果可能不会符合预期
//为body创建并添加一个iframe对象
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
//取得iframe对象的构造数组方法
xArray = window.frames[0].Array;
//通过构造函数获取一个实例
var arr = new xArray(1,2,3); 
arr instanceof Array;//false
1
2
3
4
5
6
7
8

导致这种问题是因为iframe会产生新的全局环境,它也会拥有自己的Array.prototype属性,让不同环境下的属性相同很明显是不安全的做法,所以Array.prototype !== window.frames[0].Array.prototype,想要arr instanceof Array为true,你得保证arr是由原始Array构造函数创建时才可行。

# 4.[].constructor === Array

隐患

存在多个全局环境的问题,导致的问题与instanceof相同

//为body创建并添加一个iframe标签
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
//取得iframe对象的构造数组方法
xArray = window.frames[window.frames.length-1].Array;
//通过构造函数获取一个实例
var arr = new xArray(1,2,3); 
arr.constructor === Array;//false
1
2
3
4
5
6
7
8

# 5. 浏览器进程

浏览器主要包含哪些进程:

  • 1.Browser 进程:浏览器的主进程,只有一个,负责创建和销毁其它进程、网络资源的下载与管理、浏览器界面的展示、前进后退等。

  • 2.GPU 进程:用于 3D 绘制等,最多一个。

  • 3.第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建。

  • 4.浏览器渲染进程(浏览器内核):内部是多线程的,每打开一个新网页就会创建一个进程,主要用于页面渲染,脚本执行,事件处理等。

浏览器的进程个数是怎么计算的:

  • 不管打开一个或多个新的空白窗口,都只计算为打开了一个Browser进程
  • 在新的空白窗口中加载一个网页,计算为一个浏览器渲染进程
  • 其他进程如果有用到,则相应计数加一

“构建 DOM、构建 CSSOM、构建 Render Tree”这三点任何一点的改变都有可能会重复执行“Layout、Painting”(回流和重绘)——————此即属于进程4(浏览器渲染进程)——然后用多个线程来处理

浏览器渲染树

首先,浏览器会根据HTML文件生成DOM树,载入CSS文件构建CSS Object Model。然后,在DOM树和CSS Object Model上建立渲染树(render tree):渲染树就是渲染时用到的树。渲染树其实就是DOM树和CSS的组合,和DOM树相同的是每个HTML标签对应一个渲染树节点,不同的是,文本节点比较特殊,每一行文本对应一个渲染树节点,并且,由于渲染树识别CSS,<head>标签以及设置为{display: none}的标签不在DOM树上。除此之外,渲染树上的每个节点该是什么样式也已经计算出来了,此时就涉及CSS选择器的优先级了:浏览器默认样式<外部样式表<style内部样式表,同一样式表内部又有#id > .class > tagName > a:hover,important的样式优先级最高。最后,渲染树建立之后,就可以在屏幕上开始绘制(paint)节点。

# 6. vscode 文档浏览

  • code . 可以在终端中输入直接在vscode中打开当前目录
  • code test1.html没有的话,会自动创建
  • code /Users/tlm/Documents/web-front/test/real-test/test1.html /Users/tlm/Documents/web-front/test/real-test/test2.html -d -n 直接打开两个文件进行对比模式;-n是打开一个新的VS Code会话窗口而不是使用之前的会话窗口
  • code test.html -r 强制在上一个激活窗口中打开文件或文件夹