时光机

笔记


  • 首页

  • 关于

  • 标签

  • 分类

  • 前端笔记

  • 碎碎念

  • 归档

  • 搜索

redux知识点

发表于 2021-06-20 | 分类于 前端笔记

avatar

  1. store

    掌管整个应用的状态, 整个应用只能有一个store。通过store.getState() 获取应用某个时间点的快照(状态),通过store.dispatch 分发action.Redux 规定: 一个 State 对应一个 View。只要 State 相同,View 就相同。你知道 State,就知道 View 是什么样,反之亦然。

  2. reducer

    当store收到action ,就要生成一个新的state, 这个计算过程就是reducer。reducer是一个纯函数,即相同的输入,一定得到相同的输出。

  3. action

    用户不能直接修改state, state的变化必须是View 导致的, action 就是View 发出的一个通知,表示action 的名称。

redux 重要API

  1. createStore函数:用来生成store。

    1
    const store = createStore(reducer, initialState, enhancer)
  2. bindActionCreators:将 action 包装成直接可被调用的函数,用户感知不到dispatch的存在。

    1
    2
    const mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);
    return connect(mapStateToProps, mapDispatchToProps)(Node);
  3. combineReducers:一个复杂的应用往往state 比较庞大,导致 Reducer 函数也比较庞大,因此如果能把reducer拆分成一个个独立的子Reducer, 最后再把他们合成一个大的reducer,处理起来就比较方便。而combineReducers就是做这件事的,该函数根据state的key去执行响应的子Reducer,并将结果合并到最终的state对象里。

    1
    2
    3
    4
    5
    6
    7
    8
    import { combineReducers } from 'redux';
    import { storeReducer } from './store/reducer';
    import { reserveReducer } from './reserve/reducer';

    export const settingReducer = combineReducers({
    store: storeReducer,
    reserve: reserveReducer,
    });
  4. applyMiddleware:applyMiddleware(…middlewares) 引入中间件,比如我们经常使用的用于处理异步action的redux-thunk 中间件。

  5. compose:是一个返回依次执行参数里面的方法的函数, 其内部是通过Array.prototype.reduceRight 函数实现的,一般redux项目使用多个中间件时会用到。

    react-redux API

  6. Provider:
    Provider其实是一个React 组件,其原理是通过React组件的context 属性实现store 的传递, 进而拿到整个应用的state。

    1
    2
    3
    4
    5
    6
    7
    const App = () => {
    return (
    <Provider store={store}>
    <Comp/>
    </Provider>
    )
    };
  7. connect:函数是把 redux 的 dispatch 和 state 映射为 react 组件的 props中,将页面里的组件与应用的状态state真正连接起来。

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
const mapStateToProps = (state, ownProps) => {
// state 是 {userList: [{id: 0, name: '王二'}]}
return {
user: _.find(state.userList, {id: ownProps.userId})
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
increase: (...args) => dispatch(actions.increase(...args)),
decrease: (...args) => dispatch(actions.decrease(...args))
}
}

class MyComp extends Component {
static PropTypes = {
userId: PropTypes.string.isRequired,
user: PropTypes.object
};
render(){
const {count, increase, decrease} = this.props;
return (<div>
<div>用户名:{this.props.user.name}</div>
<div>计数:{this.props.count}次</div>
<button onClick={increase}>增加</button>
<button onClick={decrease}>减少</button>
</div>)
}
}

const Comp = connect(mapStateToProps, mapDispatchToProps)(MyComp);

使用middleWare背景:我们知道redux中数据流是同步的,不支持异步action更新或获取数据,但是在实际项目中异步请求数据绝对是高频出现,并且可以说占据了9成以上的业务场景(初始数据列表、获取商品信息、添加购物车等等),因此redux中间件诞生了

redux-saga

redux-saga 就是用来处理上述副作用(异步任务)的一个中间件。它是一个接收事件,并可能触发新事件的过程管理者,为你的应用管理复杂的流程.
redux-saga 的优点:
(1)声明式 Effects:所有的操作以JavaScript对象的方式被 yield,并被 middleware 执行。使得在 saga 内部测试变得更加容易,可以通过简单地遍历 Generator 并在 yield 后的成功值上面做一个 deepEqual 测试。
(2)高级的异步控制流以及并发管理:可以使用简单的同步方式描述异步流,并通过 fork 实现并发任务。
(3)架构上的优势:将所有的异步流程控制都移入到了 sagas,UI 组件不用执行业务逻辑,只需 dispatch action 就行,增强组件复用性。

redux-thunk

redux-thunk 的主要思想是扩展 action,使得 action 从一个对象变成一个函数。

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
// redux-thunk example
import {applyMiddleware, createStore} from 'redux';
import axios from 'axios';
import thunk from 'redux-thunk';

const initialState = { fetching: false, fetched: false, users: [], error: null }
const reducer = (state = initialState, action) => {
switch(action.type) {
case 'FETCH_USERS_START': {
return {...state, fetching: true}
break;
}
case 'FETCH_USERS_ERROR': {
return {...state, fetching: false, error: action.payload}
break;
}
case 'RECEIVE_USERS': {
return {...state, fetching: false, fetched: true, users: action.payload}
break;
}
}
return state;
}
const middleware = applyMiddleware(thunk);

// store.dispatch({type: 'FOO'});
// redux-thunk 的作用即是将 action 从一个对象变成一个函数
store.dispatch((dispatch) => {
dispatch({type: 'FETCH_USERS_START'});
// do something async
axios.get('http://rest.learncode.academy/api/wstern/users')
.then((response) => {
dispatch({type: 'RECEIVE_USERS', payload: response.data})
})
.catch((err) => {
dispatch({type: 'FECTH_USERS_ERROR', payload: err})
})
});

redux-thunk 的缺点:
(1)action 虽然扩展了,但因此变得复杂,后期可维护性降低;
(2)thunks 内部测试逻辑比较困难,需要mock所有的触发函数;
(3)协调并发任务比较困难,当自己的 action 调用了别人的 action,别人的 action 发生改动,则需要自己主动修改;
(4)业务逻辑会散布在不同的地方:启动的模块,组件以及thunks内部。

大美新疆

发表于 2021-03-21 | 更新于 2021-04-26 | 分类于 碎碎念

Day1:北京–乌鲁木齐–国际大巴扎

Day2:乌鲁木齐-五彩浅谈-住宿布尔津

Day3:布尔津-喀纳斯-登钓鱼台-住喀纳斯景区小木屋

Day4:七点起来看晨雾-回游客中心吃早饭-徒步三湾-下午去禾木村-白桦林

Day5:预计看日出(第一缕阳光)由于下雪没阳光,下午出发去布尔津的魔鬼城,到那刚好下午七点,风沙也大,没进去,门口待了回看了看夕阳,本想第二天一早来

Day6:赛里木湖-住宿清水河(薰衣草基地)

Day7:清水河-巴音布鲁克草原

react+ant design

发表于 2021-02-03 | 更新于 2021-03-16 | 分类于 前端笔记

使用react+ant design+d3 构建自己的项目

1.先装脚手架

注意:如果您以前create-react-app通过进行了全局安装npm install -g create-react-app,建议您使用npm uninstall -g create-react-app或卸载软件包,yarn global remove create-react-app以确保npx始终使用最新版本。

1
2
3
4
cnpm install create-react-app
create-react-app my-app
cd my-app
npm start

2.下载依赖

1.1 -S就是–save的简写,将包的名称及版本号放在package.json的dependencies里面;(elementui、echarts这些插件在实际运行中也是需要的)

1.2 -D就是–save-dev 这样安装的包的名称及版本号就会存的devDependencies(开发环境下如babel,sass-loader,gulp、babel、webpack这些压缩代码、打包的工具)

1
npm i -S dager-d3 d3 ant-design

Mac上安装 Windows10

发表于 2020-07-01 | 分类于 前端笔记

1.查看你的Mac是不是支持Windows10系统 传送门

2.安装教程 传送门

3.安装之后缺少wifi驱动:下载驱动精灵网卡版,用U盘拷到windows系统,解决电脑联网问题

4.蓝牙找不到的修复方法(右下角蓝牙模块很容易消失,在控制面板里也找不到,设备管理器里也可能找不到):

upload successful
upload successful
upload successful

5.双系统切换(默认)启动 传送门

6.默认系统是windows企业版

typescript

发表于 2020-06-02 | 分类于 前端笔记

接口(interface)和类型别名(type alias)interface只能定义对象类型,type声明的方式可以定义组合类型,交叉类型和原始类型。如果用type alias 声明的方式,会导致一些功能的缺失。

  1. interface方式可以实现接口的extends/implements,而type 不行
  2. interface可以实现接口的merge,但是type不行

算法

发表于 2020-05-31 | 更新于 2021-06-20 | 分类于 前端笔记

冒泡排序

1
2
3
4
5
6
7
8
9
10
11
12
13
function bubbleSort1(arr){
for(var i=0;i<arr.length;i++){
for(var j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
var val=arr[j];
arr[j]=arr[j+1];
arr[j+1]=val;
}
}
}
return arr
}
console.log(bubbleSort1([4,5,21,5,4,1,12,5,4,1,2]))

快速排序

1
2
3
4
5
6
7
8
9
10
11
12
13
var bubbleSort2=function(arr){  
for(var i=0;i<arr.length-1;i++){
for(var j=i+1;j<arr.length;j++){
if(arr[i]>arr[j]){
var temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
return arr;
}
console.log(bubbleSort2([4,5,21,5,4,1,12,5,4,1,2]))

解析地址栏参数

1
2
3
4
5
6
7
8
9
10
11
12
13
var url = "http://www.taobao.com/index.php?key0=0&key1=1&key2=2";

function parseQueryString(url){
var str = url.split("?")[1]; //通过?得到一个数组,取?后面的参数
items = str.split("&");
var arr,name,value;
for(var i=0; i<items.length; i++){
arr = items[i].split("="); //["key0", "0"]
name = arr[0];
value = arr[1];
this[name] = value;
}
}

去重

1
2
3
4
5
6
7
8
9
10
11
12
Array.prototype.quchong=function(){
var arr=[];
var json={};
for(var i=0;i<this.length;i++){
if(!json[this[i]]){
arr.push(this[i]);
json[this[i]]=1;
}
}
return arr
}
var arr1 = [112,112,34,'你好',112,112,34,'你好','str','str1'];

git命令

发表于 2020-05-28 | 分类于 前端笔记

upload successful
upload successful
upload successful

  1. git add :作用就是将我们需要提交的代码从工作区添加到暂存区
  2. git commit:主要是将暂存区里的改动给提交到本地的版本库
  3. git push:将本地版本库推送到远程服务器
  4. git pull:将更改从远程应用到本地
  • git diff:显示暂存区和工作区的代码差异
  • git diff HEAD:显示工作区与当前分支最新commit之间的差异

axios

发表于 2020-05-27 | 更新于 2021-02-03

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

  1. 执行 GET 请求

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 为给定 ID 的 user 创建请求
    axios.get('/user?ID=12345')
    .then(function (response) {
    console.log(response);
    })
    .catch(function (error) {
    console.log(error);
    });

    // 上面的请求也可以这样做
    axios.get('/user', {
    params: {
    ID: 12345
    }
    })
    .then(function (response) {
    console.log(response);
    })
    .catch(function (error) {
    console.log(error);
    });
  2. 执行 POST 请求

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
    })
    .then(function (response) {
    console.log(response);
    })
    .catch(function (error) {
    console.log(error);
    });
  3. 全局的 axios 默认值

    1
    2
    3
    axios.defaults.baseURL = 'https://api.example.com';
    axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
    axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
  4. 自定义实例默认值

    1
    2
    3
    4
    5
    6
    7
    // 创建实例时设置配置的默认值
    var instance = axios.create({
    baseURL: 'https://api.example.com'
    });

    // 在实例已创建后修改默认值
    instance.defaults.headers.common['Authorization'] = localStorage.getItem("token");
  5. 添加Token:token是客户端频繁向服务器端请求数据,服务器频繁的去数据库查询用户名和密码进行对比,判断用户名和密码正确与否,并作出相应的提示,在这样的背景下,token便应运而生了。

    • 登录后接口返回token,并使用localStorage保存token
    • 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
      	var ecpkey = genrKey(timestamp, num, options.url);
      return new Promise((resolve, reject) => {
      const instance = axios.create({ //instance创建一个axios实例,可以自定义配置,可在 axios文档中查看详情
      //所有的请求都会带上这些配置,比如全局都要用的身份信息等。
      headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'timestamp': timestamp + "-" + num,
      'ecpkey': ecpkey,
      'token': localStorage.getItem("token")
      },
      //后面数组中的函数必须返回一个字符串
      transformRequest: [function (data) {
      return Qs.stringify(data);
      }]
      });
      instance(options)
      .then(response => { //then 请求成功之后进行什么操作
      if (response.status === 200) {
      if (response.data.accCheck === "1") {
      localStorage.clear();
      sessionStorage.clear();
      store.commit('login', false);
      router.push({
      path: '/'
      });
      }

      resolve(response); //把请求到的数据发到引用请求的地方
      }
      })
      .catch(err => {
      if(options.url=='/user/logout'){
      localStorage.clear();
      sessionStorage.clear();
      router.push({
      path:"/"
      })
      }
      })
      });
      }
      、

总结

发表于 2020-05-26 | 更新于 2021-06-23 | 分类于 前端笔记

箭头函数于普通函数的区别

  1. 函数的this代表不一样:

    • 箭头函数,this代表上层对象,若无自定义上层,则代表window。 this 永远指向其上下文的 this ,任何方法都改变不了其指向,如 call() , bind() , apply(),call()和apply()都会立即执行,而bind()会先创建一个函数实例,然后手动的去执行;

      • 函数.call(对象,arg1,arg2….)
      • 函数.apply(对象,[arg1,arg2,…])
      • var ss=函数.bind(对象,arg1,arg2,….)
    • 普通函数,this代表当前对象。

let、const、var区别

  1. var声明变量存在变量提升,let和const不存在变量提升
  2. let和const有块级作用域
  3. 同一作用域下let和const不能声明同名变量,而var可以

浅拷贝和深拷贝

  • 浅拷贝

    1. Object.assign()
    2. Array.prototype.concat() //修改新对象会改到原对象
    3. Array.prototype.slice() //修改新对象会改到原对象
    • 【Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组】
  • 深拷贝

    1. 函数库lodash中的_.cloneDeep
    2. JSON.parse(JSON.stringify()) *详细地址
      • 深拷贝的方法有局限性,它只适用于一般数据的拷贝(对象、数组)
      • 如果json里面有时间对象,则序列化结果:时间对象=>字符串的形式
      • 如果json里有RegExp、Error对象,则序列化的结果将只得到空对象 RegExp、Error => {}
      • 如果json里有 function,undefined,则序列化的结果会把 function,undefined 丢失
      • 如果json里有NaN、Infinity和-Infinity,则序列化的结果会变成null;
      • 如果json里有对象是由构造函数生成的,则序列化的结果会丢弃对象的 constructor;

map,forEach, for…in, for…of

  1. map:返回一个新数组,它不会检测一个空数组,也不会改变原始数组
  2. forEach:不会返回结果,必须要通过外部数组push,对数组进行值操作,会改变原来数组的值
  3. for…in:循环返回的值都是数据结构的 键值名。
  4. for…of:循环用来获取一对键值对中的值,这个是ES6新增的一个方法,不支持数组,可以中断循环

typeof instanceof

1.typeof:判断基本类型类型(number, string, undefined,boolean),array,object,正则,日期等类型返回’object’
2.instanceof:用于判断一个变量是否某个对象的实例

js中递归,闭包

  • 递归:一个函数自己调用自己,递归应用场景(累加和,阶乘)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     //1.求1-n之间的累加和
    function getSum(n){
    //递归 : 自己调用自己
    return n == 1? 1 : getSum(n-1) + n;
    // if(n == 1){
    // return 1;
    // }else{
    // return getSum(n-1) + n;
    // };
    };
    var num1 = getSum(100);
    console.log(num1);

    //2.求阶乘
    var res = (function(n){return n==1?1:n*arguments.callee(n-1)})(6);
    console.log(res);

    function getJieChen(n){
    //递归实现
    return n == 1?1:n*getJieChen(n-1);
    };
    var n1 = getJieChen(5);
    console.log(n1);
  • 闭包:在函数外部访问函数内部变量

    reduce与递归将多维数组转换为一维数组

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
//将二维数组转化为一维
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = arr.reduce((pre,cur)=>{
return pre.concat(cur)
},[])
console.log(newArr); // [0, 1, 2, 3, 4, 5]

//将多维数组转化为一维
let arr = [[0, 1], [2, 3], [4,[5,6,7]]]
const newArr = function(arr){
return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[])
}
console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]

//递归
let arr = [1, 2, 3, 4, 5, [6, 7, 8, [9, 10, 11, 12, [13, 14, 15, 16]]]]
let newArr = [] // 存放转化后的一维数组
function arrConversion (arr) {
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
arrConversion(arr[i])
} else {
newArr.push(arr[i])
}
}
}
arrConversion(arr)
console.log(newArr) // 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

Html5新增

  1. 语义化标签:header,footer,nav,aside,aritcle等
  2. 新增视频video和音频audio标签
  3. 存储:sessionStorage将数据保存在session中,浏览器关闭后删除,大小5M,无数量限制,页面刷新不会消除数据;而localStorage则一直将数据保存在客户端本地,大小5M,无数量限制;补充cookie,存储在本地的数据,存储大小4K,可设定时效,且有数量限制;IE专属userData,大小1M,可设定时效,使用时需判断是否是IE浏览器

CSS权重

从0开始,一个行内样式+1000,一个id+100,一个属性选择器/class或者伪类+10,一个元素名,或者伪元素+1,!important是无穷。

CSS3新特性

  1. animation配合keyframes使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
div{
width:100px;
height:100px;
background:red;
position:relative;
animation:myfirst 5s;
-moz-animation:myfirst 5s; /* Firefox */
-webkit-animation:myfirst 5s; /* Safari and Chrome */
-o-animation:myfirst 5s; /* Opera */
}

@keyframes myfirst{
0% {background:red; left:0px; top:0px;}
25% {background:yellow; left:200px; top:0px;}
50% {background:blue; left:200px; top:200px;}
75% {background:green; left:0px; top:200px;}
100% {background:red; left:0px; top:0px;}
}
  1. transform 字面上就是变形,属性向元素应用 2D 或 3D 转换。该属性允许我们对元素进行translate平移、rotate旋转、scale缩放、skew斜切。
1
2
3
4
1.translate有2个参数,代表x轴和y轴, 只有1个参数时,只在x轴移动,y轴默认是0;transform: translate(10px,10px)
2.rotate(1800deg)参数值为正数顺时针旋转,值为负数逆时针旋转; transform:rotate(90deg)
3.scale(x,y) x轴和y轴缩放,第二个参数没有默认取第一个参数的值,scale(0.5)参数值小于1缩小,scale(1.5)参数值大于1放大; transform:scale(1.2)
4.skew(x,y) 斜切 用法和rotate类似,在x轴和y轴同时进行角度扭曲,第二个参数没有时默认为0,不进行斜切; transform: skew(90deg,10deg)
  1. transition有4个值(默认是前2个值):property(指定css属性的name)、duration(动画持续时间)、timing-function(切换动画的速度)、delay(动画执行前的延迟时间)

flex布局
媒体查询

less和sass

  1. Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量、Mixin、函数等特性,使 CSS 更易维护和扩展,它可以运行在 Node 或浏览器端。
  2. Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 、嵌套 、混合 、导入 等高级功能,这些拓展令 CSS 更加强大与优雅。使用 Sass 以及 Sass 的样式库(如Compass)有助于更好地组织管理样式文件,以及更高效地开发项目。
  3. 相同之处

    1、混入(Mixins)——class中的class;

    2、参数混入——可以传递参数的class,就像函数一样;

    3、嵌套规则——Class中嵌套class,从而减少重复的代码;

    4、运算——CSS中用上数学;

    5、颜色功能——可以编辑颜色;

    6、名字空间(namespace)——分组样式,从而可以被调用;

    7、作用域——局部修改样式;

    8、JavaScript 赋值——在CSS中使用JavaScript表达式赋值。

  4. 区别

    Less是基于JavaScript,是在客户端处理的。

    Sass是基于Ruby的,是在服务器端处理的。

    关于变量在Less和Sass中的唯一区别就是Less用@,Sass用$。

    输出设置,Less没有输出设置,Sass提供4中输出选项:nested, compact, compressed 和 expanded。

    Sass支持条件语句,可以使用if{}else{},for{}循环等等,而Less不支持。

输入url到页面加载发生了什么

  1. 用户输入”吴彦祖”
  2. 浏览器通过DNS把url解析为IP
  3. 和IP地址建立TCP链接,发送Http请求
  4. 服务器接收请求,查库读取文件等,拼接好返回Http响应
  5. 浏览器收到首屏html,开始渲染
  6. 解析html为dom,dom-tree
  7. 解析css为css-tree
  8. dom+css生成render-tree绘图
  9. 加载script文件
  10. 执行js

从“在浏览器输入域名”到“页面静态资源完全加载”的整个流程

  1. 用户输入
    当用户输入关键字并键入回车之后,这意味着当前页面即将要被替换成新的页面,不过在这个流程继续之前,浏览器还给了当前页面一次执行 beforeunload 事件的机会,beforeunload 事件允许页面在退出之前执行一些数据清理操作,还可以询问用户是否要离开当前页面。
  2. URL 请求过程

    首先,网络进程会查找本地缓存是否缓存了该资源。

    如果有缓存资源,那么直接返回资源给浏览器进程;如果在缓存中没有查找到资源,那么直接进入网络请求流程。这请求前的第一步是要进行 DNS 解析,以获取请求域名的服务器 IP 地址。如果请求协议是 HTTPS,那么还需要建立 TLS 连接。

    接下来就是利用 IP 地址和服务器建立 TCP 连接。连接建立之后,浏览器端会构建请求行、请求头等信息,并把和该域名相关的 Cookie 等数据附加到请求头中,然后向服务器发送构建的请求信息。

    数据在进入服务端之前,可能还会先经过负责负载均衡的服务器,它的作用就是将请求合理的分发到多台服务器上,这时假设服务端会响应一个 HTML 文件。

    首先浏览器会判断状态码是什么,如果是 200 那就继续解析,如果 400 或 500 的话就会报错,如果 300 的话会进行重定向,这里会有个重定向计数器,避免过多次的重定向,超过次数也会报错。

    浏览器开始解析文件,如果是 gzip 格式的话会先解压一下,然后通过文件的编码格式知道该如何去解码文件。

    其中,DNS也有几步缓存:浏览器缓存,hosts文件,
    如果本地域名解析服务器也没有该域名的记录,则开始递归+迭代解析
    TCP三次握手,HTTP。TLS握手,HTTPS。

  3. 准备渲染进程

    默认情况下,Chrome 会为每个页面分配一个渲染进程,也就是说,每打开一个新页面就会配套创建一个新的渲染进程。

  4. 渲染阶段

    文件解码成功后会正式开始渲染流程,先会根据 HTML 构建 DOM 树,有CSS的话会去构建 CSSOM 树。如果遇到 script 标签的话,会判断是否存在 async 或者 defer ,前者会并行进行下载并执行 JS,后者会先下载文件,然后等待 HTML 解析完成后顺序执行。

    如果以上都没有,就会阻塞住渲染流程直到 JS 执行完毕。

    CSSOM 树和 DOM 树构建完成后会开始生成 Render 树,这一步就是确定页面元素的布局、样式等等诸多方面的东西

    在生成 Render 树的过程中,浏览器就开始调用GPU 绘制,合成图层,将内容显示在屏幕上了。

eventloop机制,promise的实现和静态方法、async实现

  1. Event Loop 是什么?
    js的任务队列分为同步任务和异步任务,所有的同步任务都是在主线程里执行的,异步任务可能会在宏任务或者微任务里面。
  2. JavaScript的事件分两种,宏任务(macro-task)和微任务(micro-task)
    • 宏任务:包括整体代码script,setTimeout,setInterval
    • 微任务:Promise.then(非new Promise),process.nextTick(node中)
    • 事件的执行顺序,是先执行宏任务,然后执行微任务,这个是基础,任务可以有同步任务和异步任务,同步的进入主线程,异步的进入Event Table并注册函数,异步事件完成后,会将回调函数放入Event Queue中(宏任务和微任务是不同的Event Queue),同步任务执行完成后,会从Event Queue中读取事件放入主线程执行,回调函数中可能还会包含不同的任务,因此会循环执行上述操作。

浏览器页签间通信

  1. localStorage —— 使用addeventlistene舰艇storage事件
  2. cookie+setInterval —— cookie存储数据,定时器在一定间隔获取cookie数据
  3. websocket通讯 —— html5中的协议,基于http协议,完成部分握手动作,完成双向通信功能,支持持久连接。
  4. sharedWorker —— 必须运行在服务器上

ES6中的map和set

https://es6.ruanyifeng.com/#docs/set-map

  1. Map对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
  2. Maps 和 Objects 的区别
    一个 Object 的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值。Map 中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
    Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
  3. Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。

Promise 和 async/await

对于单一的 Promise 链其实并不能发现 async/await 的优势,当需要处理由多个 Promise 组成的 then 链的时候,优势就能体现出来了

  1. promise是ES6,async/await是ES7
  2. async/await相对于promise来讲,写法更加优雅
  3. reject状态:
    1)promise错误可以通过catch来捕捉,建议尾部捕获错误,
    2)async/await既可以用.then又可以用try-catch捕捉

react知识点

发表于 2020-05-25 | 更新于 2021-06-23 | 分类于 前端笔记

15.x生命周期

avatar

  1. 挂载卸载过程
    1.1 constructor()
    1.2 componentWillMount()
    1.3 componentDidMount()
    1.4 componentWillUnmount ()
  2. 更新过程
    2.1 componentWillReceiveProps (nextProps)
    2.2 shouldComponentUpdate(nextProps,nextState)
    2.3 componentWillUpdate (nextProps,nextState)
    2.4 componentDidUpdate(prevProps,prevState)
    2.5 render()

16.x生命周期

avatar
React新增的生命周期(个人补充)

  1. getDerivedStateFromProps(nextProps, prevState)
  2. getSnapshotBeforeUpdate(prevProps, prevState)

super(props)

super(props)的作用就是在父类的构造函数中给props赋值一个对象this.props=props这样就能在它的下面定义你要用到的属性了,然而其他的由于没有传参就直接赋值为undefind

setState

  1. setstate在原生事件,setTimeout,setInterval,promise等异步操作中,state会同步更新,在React内部机制能检测到的地方, setState就是异步的。
  2. 在异步的函数里可以准确拿到更新后的 state,通过第二个参数 setState(partialState, callback) 中的 callback 拿到更新后的结果。

key为index的问题

注意:如果不存在添加/删除/排序操作, 用index没有问题

  1. 添加/删除/排序 => 产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低
  2. 如果item界面还有输入框 => 产生错误的真实DOM更新 ==> 界面有问题

解决:使用item数据的标识数据作为key, 比如id属性值

数据传递详情

  1. 父传子:props
  2. 子传父:子组件中通过this.props.事件名(参数)的方式向父组件传递参数,父组件中,事件名={this.事件名.bind(this)}
  3. 兄弟(组件A – 传值 –> 父组件 – 传值 –> 组件B)
    avatar

虚拟DOM

为了减少消耗性能的DOM操作,React 把真实 DOM 树转换成js对象树,也就是 Virtual DOM。每次数据更新后,重新计算 Virtual DOM,并和上一次生成的 Virtual DOM 做Diff计算对比,对发生 变化的部分做批量更新。

  • 当首次挂载组件时,按顺序执行 getDefaultProps、getInitialState、componentWillMount、 render 和 componentDidMount。
  • 当卸载组件时,执行 componentWillUnmount。
  • 当重新挂载组件时,此时按顺序执行 getInitialState、componentWillMount、render 和componentDidMount,但并不执行 getDefaultProps。
  • 当再次渲染组件时,组件接受到更新状态,此时按顺序执行 componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render 和 componentDidUpdate。

同一层级的子节点,可以通过唯一的 id 来进行区分,通过shouldComponentUpdate()来判断该组件是否需要进行diff算法分析。

super(props)

super(props)的作用就是在父类的构造函数中给props赋值一个对象this.props=props这样就能在它的下面定义你要用到的属性了,然而其他的由于没有传参就直接赋值为undefind,如果不写,某个构造函数中调用了某个访问props的方法,bug就很难定位了,强烈建议使用。

PureComponent

默认情况下,会对props和state进行浅比较,如果组件渲染过程中,新旧props和state是相等的,将不会执行render,不能使用shouldComponentUpdate方法

immutable

https://mp.weixin.qq.com/s/06GDG6mdaElTfzb5McMxFQ
https://blog.csdn.net/qq_42941302/article/details/111834035

在Rudux中因为深拷贝对性能的消耗太大了(用到了递归,逐层拷贝每个节点)。
但当你使用immutable数据的时候:只会拷贝你改变的节点,从而达到了节省性能。

React函数组件和类组件的区别

  1. 函数组件是一个纯函数,不能在组件中使用setState(),不能在函数组件中使用生命周期钩子,原因和不能使用state一样,所有的生命周期钩子都来自于继承的React.Component中。但是在react16.8版本中添加了hooks,使得我们可以在函数组件中使用useState钩子去管理state,使用useEffect钩子去使用生命周期函数。
  2. 类组件存在this指向的问题(使用bind(this)提前规避)
  3. 函数组件不会被实例化,整体渲染性能得到提升

setState是同步还是异步

setState 只在合成事件和钩子函数中是“异步”的(在组件中的onClick,生命周期函数或等都是属于它自定义的合成事件);在原生事件和 setTimeout 中都是同步的(addeventListener添加的,dom中的原生事件)。

Hook

  1. useState
    const [state, setState] = useState(initialState);
  2. useEffect
    2.1 当useEffect没有第二个参数时,相当于componentDidMount以及componentDidUpdate
    2.2 空数组,初始化调用一次之后不再执行,相当于componentDidMount
    2.3 一个或者多个值的数组,值其中任意一个值变化了都会触发该函数,相当于componentDidUpdate
    2.4 返回一个函数,相当于componentWillUnmout(return中)

    高阶组件

    用函数包裹,函数参数接受一个普通组件,并最终返回一个新组件,这个返回的新组件就叫做高阶组件

    react vue 区别

  3. 监听数据变化的实现原理不同
    Vue通过 getter/setter以及一些函数的劫持,能精确知道数据变化。

React默认是通过比较引用的方式(diff)进行的,如果不优化可能导致大量不必要的VDOM的重新渲染。为什么React不精确监听数据变化呢?这是因为Vue和React设计理念上的区别,Vue使用的是可变数据,而React更强调数据的不可变,两者没有好坏之分,Vue更加简单,而React构建大型应用的时候更加鲁棒。

  1. 数据流的不同
    Vue1.0中可以实现两种双向绑定:父子组件之间,props可以双向绑定;组件与DOM之间可以通过v-model双向绑定。Vue2.x中去掉了第一种,也就是父子组件之间不能双向绑定了(但是提供了一个语法糖自动帮你通过事件的方式修改),并且Vue2.x已经不鼓励组件对自己的 props进行任何修改了。

React一直不支持双向绑定,提倡的是单向数据流,称之为onChange/setState()模式。不过由于我们一般都会用Vuex以及Redux等单向数据流的状态管理框架,因此很多时候我们感受不到这一点的区别了。

相同点:

  1. 使用 虚拟DOM (Virtual DOM)

    为什么Virtual DOM的能提高页面渲染性能?
    Virtual DOM是一个映射真实DOM的JavaScript对象
    如果需要改变任何元素的状态,那么首先在Virtual DOM上进行改变(而不是直接改变真实的DOM)
    然后,计算新旧Virtual DOM之间的差别(算法)
    最后,根据这些差别对真实的DOM增加、删除、修改、移动。

  2. 提供了响应式 (Reactive) 和组件化 (Composable) 的视图组件。

  3. 中心思想相同:一切都是组件,组件实例之间可以嵌套。

  4. 每个组件都提供合理的钩子函数,可以让开发者定制化地去处理需求。

  5. 专注于核心库,而将其他功能如路由和全局状态管理交给相关的库。
    不同点

  6. 数据绑定: 单向、双向
    React: 基于JSX编码, 单向数据绑定, 不能直接更新状态数据,必须通过setState()更新指定数据
    Vue: 基于模板语法, 双向数据绑定, 直接更新data数据11.35. Vue中mixin与extend区别

  7. 模板管理:JSX、template模版
    Vue所有的模板使用的是近似常规HTML,只不过是新添加了一些属性

123
Alina

Alina

开始,我们以为自己什么都知道。后来发现,其实我们什么都不知道。
21 日志
2 分类
16 标签
RSS
GitHub E-Mail
© 2021 Alina