Git

Git的三大区

Git三个大区:工作区(working area)、暂存区(staging area)、 版本库(repository)。

查看状态

设置Remote

拉取代码

React_JSX

JSX

JSX是JS的扩展语言,特点是既可以写JS,也可以写Html,而且不用以字符串的方式写。
例如:

1
2
3
4
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>; }
return <h1>Hello, Stranger.</h1>;}

关于JSX的三个大问题

JSX的本质是什么,它和js之间到底是什么关系?

  • 模板语法的一种
  • JSX是JS的一种语法扩展,它和模板语言很接近,但是它充分具备JS的能力。
  • JSX是如何生效的呢?
    • JSX会被编译为React.createElement(), React.createElement()将返回一个叫做“React Element”的JS对象。编译是通过Babel来完成的。
    • React.createElement(标签名, 属性, 子元素)
  • JSX使用最熟悉的类HTML标签语法来创建虚拟DOM,降低学习成本,提升研发效率与研发体验。

    React.createElement源码

    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    export function createElement(type[节点类型,div啥的], config[属性对象对象], children[子元素]) {
    // propName 变量用于储存后面需要用到的元素属性
    let propName;
    // props 变量用于储存元素属性的键值对集合
    const props = {};
    // key ref self source 均为React的属性,此处不深究
    let key = null;
    let ref = null;
    let self = null;
    let source = null;

    // config对象中存储的是元素的属性
    if (config != null) {
    // 进来之后做的第一件事,是依次对ref key self 和source属性赋值
    if (hasValidRef(config)) {
    ref = config.ref;
    }
    // 此处将key值字符串化
    // 按照Ref 以此类推
    // 接着就是要把config里面的属性都一个一个挪到props这个之前声明好多对象里面
    for (propName in config) {
    if{
    // 筛选出可以提进props对象的属性
    hasOwnProperty.call(config, propName) &&/
    !RESERVED_PROPS.hasOwnProperty(propName)
    props[propName] = config[propName];
    }
    }
    }
    // childrenLength 指的是当前元素的子元素的个数,减去的2是type和config两个参数占用的长度
    const childrenLenght = arguments.length - 2;
    // 如果抛去type和config,就只剩一个参数,一般意味着文本节点出现了
    if (childrenLength === 1){
    // 添加到props
    } else if (childrenLength > 1) {
    // 把子元素推进数组里
    // 添加到props中
    }
    // 处理defaultProps
    // defaultProps推到props
    }
    // 最后返回一个调用ReactElement执行方法,并传入刚才处理过的参数
    return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    RectCurrentOwner.current,
    props,
    )

    // 1、React.createElement
    // 2、二次处理key、ref、self、source四个属性值
    // 3、遍历config,筛出可以提进props里的属性
    // 4、提取子元素,推入childArray数组
    // 5、格式化defaultProps

开发者=》react.createElement => ReactElement =》 ReactDOM.render()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const ReactElement = function (  type,key,ref,self,source,RectCurrentOwner,current,props) {
const element = {
// REACT_ELEMENT_TYPE是一个常量,用来标识该对象是一个ReactElement
$$ typeof:REACT_ELEMENT_TYPE,
// 内置属性赋值
// 组装,然后返回给React.createElement
}
}
ReactDOM.render(
// 需要渲染的元素(ReactElement)
element,
// 元素挂载的目标容器(一个真实DOM,确实存在的)
contanier,
// 回调函数,可选参数,可以用来处理渲染的结束后的逻辑
[callback]
)

React15 React16 生命周期

虚拟DOM生命流

组件初始化 =》 render方法 =》生成虚拟DOM =》 ReactDOM.render方法 =》 真实DOM
组件更新 =》 render方法 =》 生成新的虚拟DOM =》 diff算法 =》定位出两次虚拟DOM的差异
React允许开发者基于单向数据流的原则,完成组件间的通信,而组件间的通信,又将改变通信双方某一方内部的数据,进而对渲染结果构成影响。

生命周期的本质

React组件内部的生命周期方法,LifeCircel的render,是组件的灵魂,其他方法是躯干。
渲染工作流:组件数据改变到组件实际更新的过程。
React15的生命周期流程:
挂载阶段:组件初始化渲染,只发生一次

  • constructor(),对this.state初始化
  • componentWillMount()
    在执行过程中,不会操作真实dom,只是把需要渲染的内容返回出来
  • render
    在渲染结束后被处罚,真实DOM已经挂载到页面上,可以对真实DOM操作
  • componentDidMount()
    更新阶段
  • componentWillReceiveProps(nextProps) // 父组件触发的更新
    • 不是props的变化触发的,而是父组件的变化触发的
  • shouldComponentUpdate(nextProps, nextState) // 组件自身更新
    • React组件会根据此方法的返回值,来决定是否执行该方法之后的生命周期,进而决定是否对组件进行re-render
  • componentWillUpdate()
  • componentDidUpdate()
  • render()
    组件卸载阶段
  • componentWillUnmount()

react16 生命周期

先看react16.3生命周期 react16.4后又有微调
mounting阶段:
constructor()
getDerivedStateFromProps(props[父组件的props], state[本组件的state
]) // 废弃了compoenentWillMount,是废弃不是被代替

  • 使用props来派生/更新state
  • 直接从命名层面约束了它的用途
  • 在更新和挂载两个阶段都会出现
  • 是静态方法,不依赖组件实例而存在,访问不到this
  • 得返回一个对象格式的返回值,需要用这个返回值来更新组件的state,不更新就返回null,不是覆盖式更新,而是针对某个属性的定向更新,不会替换原来的state,而是更新,也就是添加
    render() react 16之前render方法必须返回元素,现在可以返回元素数组和字符串
    componentDidMount()

更新阶段
getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate(prevProps, prevState) // 代替了compoenentWillUpdate

  • 会作为第三个参数给到componenetDidUpdate()
  • 在真实DOM更新之前,在render之后执行
  • 同时获得更新前真实DOM和更新前后的state&props信息

compoenentDidUpdate()
react16.4和react16.3更新流程不一致,getDerivedStateFromProps 任何更新流程都会触发,而3只有父组件的触发才会走该生命周期。
为啥要用getDerivedStateFromProps?

  • getDerivedStateFromProps是作为试图代替compoenentWillReceiveProps的APT而出现的
  • getDerivedStateFromProps 不能喝compoenentWillReceiveProps划等号
  • getDerivedStateFromProps 现在只能做基础props更新state

卸载阶段
没变

Fiber架构

是对React16对React核心算法的一次重写
Fiber会使原本同步的渲染过程变成异步的

  • 将大的更新任务拆分成许多个小任务
  • 可以被打断的异步渲染模式
  • 但这个“打断”是有原则的,根据“能否被打断”这一标准,React 16 的生命周期被划分为了 render 和 commit 两个阶段,而 commit 阶段又被细分为了 pre-commit 和 commit。每个阶段所涵盖的生命周期如下图所示:
  • render 阶段在执行过程中允许被打断,而 commit 阶段则总是同步执行的。
  • render 阶段是允许暂停、终止和重启的。当一个任务执行到一半被打断后,下一次渲染线程抢回主动权时,这个任务被重启的形式是“重复执行一遍整个任务”而非“接着上次执行到的那行代码往下走”。这就导致 render 阶段的生命周期都是有可能被重复执行的。
  • React 16 改造生命周期的主要动机是为了配合 Fiber 架构带来的异步渲染机制
  • React 团队精益求精,针对生命周期中长期被滥用的部分推行了具有强制性的最佳实践。这一系列的工作做下来,首先是确保了 Fiber 机制下数据和视图的安全性,同时也确保了生命周期方法的行为更加纯粹、可控、可预测。

Selection

通过做文本的复制粘贴了解到这个属性,通过该机制操作选中的文本。
参考MDN:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/getSelection
描述比较简单。

获取选中的文本

selection 对象

const selection = window.getSelection();或者document.getSelection();

文本

  • MDN上写的是selection.toString()即可。这样拿的话,可以保留换行等一些符号,因为在某些网站中,会把换行处理成<br>,这样就拿可以保留来。
  • 如果通过下面这种方式拿,换行符会消失。
    1
    window.getSelection().getRangeAt(0).cloneContents().textContent

删除选中的文本

  • 1
    window.getSelection().getRangeAt(0).deleteContents()

npx

安装

  • 如果npm版本(v5.2.0)足够,会自带npx,如果没有,则执行该命令即可:npm install -g npx

用处

  • 主要是为了解决npm的一些问题。比如说,如果npm在全局安装了某个工具的某个版本,但是在项目中安装了该工具另一版本。如果用npx + 该工具命令,则可以方便使用该项目下的版本工具,不用像以前一样,要访问node_modules中的安装包
  • 而且如果使用npx来安装某些工具的话,可以避免全局安装,因为它会自动下载临时包,然后执行,执行完后再删除。

puppeteer

简介

这是一款前端自动化测试工具,是黑盒测试,可以模仿用户操作。

下载以及安装

先摆上各种链接:

看官方介绍知道如果使用puppeteer可以有两种东西需要下载,一种是puppeteer-core,一个是puppeteer,具体介绍可以看上述中文api网站,不过大体可以看出来puppeteer-core是精简版的puppeteer。鉴于本人没用过puppeteer-core,本文只讲puppeteer。

  • 首先可以直接用npm或者cnpm下载:cnpm i puppeteer@版本号 -g,这里给的例子为什么是cnpm而不是npm,当然是npm不好使,详情如下:
    • 首先npm比较慢,咱都懂,而且puppeteer能用,除了下载本身以外,还会下载chromium,因为puppeteer会单独启动一个浏览器,默认会启动下载的这个。
    • 本人采用npm没下载成功过chromium,cnpm虽然也有点慢,但能下载成功。
    • 当然也可以配置其他浏览器,但是chromium最好用。
    • 当然也可以通过单独下载chromium,但是本人没试过,通过cnpm在下载puppeteer的时候下载chromium是最简单的了。
  • 首次下载安装后,可能会报错,详细报错信息为缺少共享库,不要慌张,也不要去网上乱搜,直接去上述网站上找,需要下载非常多。

语法

语法非常简单,调用各种api即可。不过学习这个需要有js同步异步事件执行机制和es6的基础,尤其是promise await/async 还要对dom操作比较熟悉。

运行环境

本人亲测,在win10 虚拟机上运行比较ok,不过在虚拟机上会出现一些问题,渲染元素慢,导致找不到元素等等,后续会讲。但是在windows的虚拟子系统中运行会出现各种问题,100%运行失败。需要再寻找解决方案,但是本人没有解决此问题。

多看一下相关知识会发现,puppeteer是需要运行在async/await下的,因为很多api的返回值是promise函数。