最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 前端学习笔记(十八)--React学习-4

    正文概述 掘金(oyishyi)   2021-01-21   525

    今天在油管看慕课网的 React 教程(出口转内销。

    1. 各种小细节

    因为看过文档,就简单过一遍。顺便也学到了很多小细节。

    1. 为什么很多时候没有看到对 React 的引用,也要导入 React

    原因其实我应该是知道的,但是一时间没有联系起来。
    因为这些文件里都有 JSX 语法,而 JSX 会被 Babel 事先转译成 React.createElement 语法,再运行。也就是说运行的时候 JS 文件是有对 React 的引用的,那自然要导入 React 了。

    2. 受控组件为什么叫受控

    之前的理解是因为被 state 控制。
    确实没错,确实是因为被 state 控制。但是可以进一步解释:

    1. 假设有一个输入框,输入框的值是被 value 控制的这个没什么问题。
    2. 如果给 value 设置了值,即使是像这样的固定值<input value="希区柯克" />,会发现此时输入框就已经变成只读了。并不是设置了和 state 相关的值才会变只读。除非干脆不写 value <input />。(在非受控组件中,如果要设置默认值,则要用 defaultValue,在设置了 value 的情况下 defaultValue 是无效的)
    3. 如果给 value 设置了和 state 相关的属性,如 <input value={this.state.artistName} />,此时 value 的值和 state 一样。
    4. 如果设置了 handleChange 方法,每次输入框变更的时候,先改变的是 state 的内容,然后 state 变更会触发重新渲染,<input> 读取 value 的值,也就是 state 的值,于是修改后的 state 的值被渲染到页面上。
    5. 因此,整个流程从:用户输入 -> value 改变
      变成了:     用户输入 -> 触发 onChange也就是(handleChange) -> state 改变 -> 重新渲染 -> value 改变。

    3. 浅拷贝 和 深拷贝

    这和 React 无关了,不过 setState 之前往往也都要进行拷贝。
    之前对这两者的理解一直出错:
    首先最重要的是,浅拷贝和深拷贝都是针对引用类型的说法,值类型赋值就可以当拷贝了。

    3.1 浅拷贝

    平常最常用的像是 concat(),slice(),[...xxx],都是浅拷贝。

    1. 浅拷贝的对象,值成员都可以拷贝,但是引用成员则会是同一个地址。
    2. 平常用的时候可能会觉得我修改了浅拷贝的对象,原对象也没有改变啊,怎么就同一个地址了呢?
    3. 这是因为,引用成员指的是对象的成员,而不是对象本身,见下面的例子:
      • [1,2,3,"sdsd",5] 这个完全可以用浅拷贝,因为成员都是 number 和 string,是值类型。
      • 但是 [1,2,3,"sdsd", {name: "alice"}] 如果用浅拷贝就会出现问题,因为其中有一个对象,如果对这个数组用浅拷贝,前面几个更改都没有问题,但是如果原数组的最后那个对象成员改变了,浅拷贝后的对象也会改变

    3.2 深拷贝

    深拷贝比较复杂,常用的方法有

    1. JSON.parse(JSON.stringfy()),此方法有缺陷,无法处理函数,正则(因为 JSON 识别不了这两个),循环引用等情况
    2. lodash 的 _.cloneDeep()

    或者也可以自己写,参考这位大佬。

    4. JSX 相关

    4.1 JSX 属性和 html 的改动

    React 坚持认为 JSX 就是 js,不是 html,要以 js 的约定规范来。

    1. 皆为 camelCase 命名方式
    2. class 改成 className
    3. <label> 标签的 for 改成 htmlFor

    4.2 JSX 可以取消转义

    JSX 默认转义所有字符,以克制 xss 攻击。不过也有方法可以取消转义。具体要用的时候再去搜。

    5. 虚拟 DOM

    React.createElement 创建的为 React 元素(是一个对象),在 React 里指的就是虚拟 DOM 元素。
    JSX --(babel转译)--> React.createElement ----> React 元素(虚拟 DOM)----> 真实 DOM 虚拟 DOM 的优点:

    1. 在更新 DOM 的时候,提高页面性能。真实 DOM 的构造是极其复杂的。而虚拟 DOM 实际只是个对象,而对象的对比和改变是比较简单的。(首次加载的性能并不会提高)
    2. 提高开发效率。由于不用手动 DOM 操作,全部被抽象成组件。而改变组件的方式也是通过修改数据。所以开发的时候

    6. diff 算法

    6.1 为什么删除类别不同的节点,还会删除所有的子节点

    diff 算法的其中一个假设,标签类别不一样的节点生成的树也不一样,因而包括子节点全部删除。这么做虽然增加了 DOM 的操作,但是实际上减少了树比对算法的复杂度。
    如果按照传统的 diff 算法,复杂度为 O(n^3)。但是通过 react 的 diff 算法,可以将复杂度减少到 O(n),这是极其庞大的性能优化,多余的 DOM 操作相比之下就显得微不足道。(当然并不是说只靠这一个假设就缩减到了 O(n),O(n) 是所有的优化策略最终的结果)

    6.2 diff 算法的三个策略

    除了两个假设的说法,diff 算法还有三个策略的说法,解释地更加详细。

    1. tree diff:diff 算法为逐层级同层比较,不会比较不同层级的节点。
    2. component diff: 相同类型的组件生成的树类似,不同类型的组件生成的树不同。(这个和第一个假设是一样的意思。)
    3. element diff:同一层级的节点,使用唯一 key 来区分。(即第二个假设)

    这三个策略指的是树的不同粒度:

    1. 在 tree diff 中,逐层遍历比较,如果发现组件不存在了,就直接销毁。如果存在,进到下一个策略。
    2. 在 component diff 中,如果前后组件都存在,则使用 component diff,比较节点的类型,如果不一样则删除整个组件来替换,如果一样则只更新属性(当然是否更新还得看 shouldComponentUpdate 的设置)。
    3. element diff,同一层级的所有节点前后的变化通过设置唯一 key 值,以此快速找到前后哪些元素是对应的。

    7. setState 的异步性(或者说 ref 的坑)

    这是很多时候在 React 里操作 DOM 的风险来源,比如说使用 ref。
    由于 setState 是异步的,操作 DOM 往往会在 setState 之前执行,那么如果这个 DOM 依赖更新之后的 state,就会出 bug。解决这个问题有两种方式:

    1. setState 可以接两个参数,平时我们只传入一个参数,但是其实可以传入第二个参数,这是一个回调函数,保证会在 setState 执行后执行。
    2. 或者使用 componentDidMount。

    2. fiddler 的坑

    1. 使用 fiddler 来 MOCK,要关掉浏览器代理,比如说 unblockYouku,否则大部分包都无法抓取,进入网页会发现 fiddler 没动静。
    2. 使用 autoresponser 后,会发现有 websocket 连接错误,wds 退出。不过替换的文件依然能够返回,浏览器能够接收到数据并处理。就是报错实在不知道是什么原因。

    3. CSSTransition

    使用 react-transition-group 这个库的 CSSTransition 组件,可以更加灵活地设置 CSS 动画。

    <CSSTransition
    	classNames="light" // 初始 className
    	in={this.state.isLightShown} // 检测哪个值的变化 ,只能为 true 或者 false
    	timeout={1000} // 动画持续时间
    	unmountOnExit // exit 动画结束后卸载该组件(这里指的是 h1)
    	appear={true} // 当第一次加载页面的时候,附加的 className
    >
    	<h1>
    		Hello, light
    	</h1>
    </CSSTransition>
    

    该组件会自动给被包裹的标签挂上特殊命名的 class,详细见文档。

    // enter 动画,在 in 的值从 false 变成 true 时候发生
    <className>-enter // 动画刚开始的瞬间
    <className>-enter-active // 动画进行中
    <className>-enter-done // 动画结束后保留的状态
    
    exit 动画,在 in 的值从 true 变成 false 的时候发生。命名就是把上面的 enter 改成 exit。
    
    appear 动画,第一次加载页面的时候发生。命名为把上面的 enter 改成 appear。
    

    以及提供了一些诸如 onEnter, onEntering, onEntered 等的监听函数,顾名思义在不同阶段执行。也就是说除了 CSS,还可以用 JS 来辅助动画,因而使得这个库比原生 CSS 动画更强大。

    4. TransitionGroup 的坑

    1. 只能用于列表,用于每个元素出现和消失的动画。
    2. TransitionGroup 中的 CSSTransition 不需要加 in 属性,因为如 1 所说,TransitionGroup 能做的事就只有列表中每个元素出现和消失时的动画(className 命名方式和 CSSTransition 一样,分别为 enter 和 exit,没有 appear,或者说 enter 就是 appear)。
    3. <TransitionGroup> 并不是占位符,而是创建一个 <div> 标签,可以更改该行为。

    起源地下载网 » 前端学习笔记(十八)--React学习-4

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元