继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

react hooks

qaytix
关注TA
已关注
手记 104
粉丝 37
获赞 165

Hooks本质上就是一类特殊的函数,它们可以为你的函数型组件(function component)注入一些特殊的功能。咦?这听起来有点像被诟病的Mixins啊?难道是Mixins要在react中死灰复燃了吗?当然不会了,等会我们再来谈两者的区别。总而言之,这些hooks的目标就是让你不再写class,让function一统江湖。

React为什么要搞一个Hooks?

想要复用一个有状态的组件太麻烦了!

我们都知道react都核心思想就是,将一个页面拆成一堆独立的,可复用的组件,并且用自上而下的单向数据流的形式将这些组件串联起来。但假如你在大型的工作项目中用react,你会发现你的项目中实际上很多react组件冗长且难以复用。尤其是那些写成class的组件,它们本身包含了状态(state),所以复用这类组件就变得很麻烦。

那之前,官方推荐怎么解决这个问题呢?答案是:渲染属性(Render Props)和高阶组件(Higher-Order Components)。我们可以稍微跑下题简单看一下这两种模式。

渲染属性指的是使用一个值为函数的prop来传递需要动态渲染的nodes或组件。如下面的代码可以看到我们的 DataProvider组件包含了所有跟状态相关的代码,而 Cat组件则可以是一个单纯的展示型组件,这样一来 DataProvider就可以单独复用了。



生命周期钩子函数里的逻辑太乱了吧!

我们通常希望一个函数只做一件事情,但我们的生命周期钩子函数里通常同时做了很多事情。比如我们需要在 componentDidMount中发起ajax请求获取数据,绑定一些事件监听等等。同时,有时候我们还需要在 componentDidUpdate做一遍同样的事情。当项目变复杂后,这一块的代码也变得不那么直观。

classes真的太让人困惑了!

我们用class来创建react组件时,还有一件很麻烦的事情,就是this的指向问题。为了保证this的指向正确,我们要经常写这样的代码: this.handleClick=this.handleClick.bind(this),或者是这样的代码: <buttononClick={()=>this.handleClick(e)}>。一旦我们不小心忘了绑定this,各种bug就随之而来,很麻烦。

还有一件让我很苦恼的事情。我在之前的react系列文章当中曾经说过,尽可能把你的组件写成无状态组件的形式,因为它们更方便复用,可独立测试。然而很多时候,我们用function写了一个简洁完美的无状态组件,后来因为需求变动这个组件必须得有自己的state,我们又得很麻烦的把function改成class。

在这样的背景下,Hooks便横空出世了!

什么是State Hooks?

回到一开始我们用的例子,我们分解来看到底state hooks做了什么:



useState是react自带的一个hook函数,它的作用就是用来声明状态变量。 useState这个函数接收的参数是我们的状态初始值(initial state),它返回了一个数组,这个数组的第 [0]项是当前当前的状态值,第 [1]项是可以改变状态值的方法函数。

所以我们做的事情其实就是,声明了一个状态变量count,把它的初始值设为0,同时提供了一个可以更改count的函数setCount。

上面这种表达形式,是借用了es6的数组解构(array destructuring),它可以让我们的代码看起来更简洁。不清楚这种用法的可以先去看下我的这篇文章:30分钟掌握ES6/ES2015核心内容(上)。

如果不用数组解构的话,可以写成下面这样。实际上数组解构是一件开销很大的事情,用下面这种写法,或者改用对象解构,性能会有很大的提升。具体可以去这篇文章的分析:Array destructuring for multi-value returns (in light of React hooks),这里不详细展开,我们就按照官方推荐使用数组解构就好。



执行初始化操作的时机

当我转到React hooks的时候,首先就遇到了这个问题:

一般来说,业务组件经常会遇到要通过发起ajax请求来获取业务数据并且执行初始化操作的场景。在使用class component编程的时候,我们就可以在class component提供的生命周期钩子函数(比如componentDidMount, constructor等)执行这个操作。可是如果转到React hooks之后,function component里是没有这个生命周期钩子函数的,那这个初始化操作怎么办呢?总不能每次遇到这种场景都使用class component来做吧?

解决方案:使用useEffect(想知道useEffect是什么的话,可以点击这里

useEffect,顾名思义,就是执行有副作用的操作,你可以把它当成componentDidMount, componentDidUpdate, and componentWillUnmount 的集合。它的函数声明如下

Hooks 解决的问题

好了,知道了 Hooks 基本使用后,我们就可以来了解 Hooks 是怎么解决 react 长期存在的问题的。

如何解决 状态有关的逻辑(stateful logic) 的重用和共享问题。

过去对于类似问题的解决方案主要有两个:

https://img4.mukewang.com/5c8a94c90001c05b16000900.jpg

Hooks本质上就是一类特殊的函数,它们可以为你的函数型组件(function component)注入一些特殊的功能。咦?这听起来有点像被诟病的Mixins啊?难道是Mixins要在react中死灰复燃了吗?当然不会了,等会我们再来谈两者的区别。总而言之,这些hooks的目标就是让你不再写class,让function一统江湖。

React为什么要搞一个Hooks?

想要复用一个有状态的组件太麻烦了!

我们都知道react都核心思想就是,将一个页面拆成一堆独立的,可复用的组件,并且用自上而下的单向数据流的形式将这些组件串联起来。但假如你在大型的工作项目中用react,你会发现你的项目中实际上很多react组件冗长且难以复用。尤其是那些写成class的组件,它们本身包含了状态(state),所以复用这类组件就变得很麻烦。

那之前,官方推荐怎么解决这个问题呢?答案是:渲染属性(Render Props)和高阶组件(Higher-Order Components)。我们可以稍微跑下题简单看一下这两种模式。

渲染属性指的是使用一个值为函数的prop来传递需要动态渲染的nodes或组件。如下面的代码可以看到我们的 DataProvider组件包含了所有跟状态相关的代码,而 Cat组件则可以是一个单纯的展示型组件,这样一来 DataProvider就可以单独复用了。

https://img1.mukewang.com/5c8a94d200014ddc16000900.jpg

https://img1.mukewang.com/5c8a94d60001df0614000788.jpg

https://img.mukewang.com/5c8a94da00017c3909600620.jpg

https://img1.mukewang.com/5c8a94df0001cd3319201080.jpg

https://img2.mukewang.com/5c8a94e30001deef04800720.jpg

https://img3.mukewang.com/5c8a94ea000104d619201080.jpg

https://img2.mukewang.com/5c8a94f2000190d816000900.jpg

https://img3.mukewang.com/5c8a94f60001e4c016000900.jpg


https://img1.mukewang.com/5cc81d250001e51d06700358.jpg

https://img3.mukewang.com/5cc81d2500011eb306700358.jpg

https://img3.mukewang.com/5cc81d250001ce2806700352.jpg

https://img.mukewang.com/5cc81d250001083306700358.jpg



https://img1.mukewang.com/5cc81db10001385f04720223.jpg

https://img4.mukewang.com/5cc81db10001396f04420320.jpg

https://img4.mukewang.com/5cc81db10001e3ad04720223.jpg

https://img3.mukewang.com/5cc81db10001d33604720223.jpg

https://img2.mukewang.com/5cc81db10001079206700358.jpg

https://img4.mukewang.com/5cc81db10001d04806700358.jpg

https://img2.mukewang.com/5cc81db1000133a204720223.jpg

https://img1.mukewang.com/5cc81db200013e7606700358.jpg

https://img3.mukewang.com/5cc81db20001209f06700358.jpg

https://img.mukewang.com/5cc81db2000191bb06700358.jpg

https://img1.mukewang.com/5cc81db20001f01906700358.jpg


根据id 判断 

1.

https://img2.mukewang.com/5cc85c03000190b707500640.jpg

https://img.mukewang.com/5cc85c0300015a0a07500640.jpg

https://img4.mukewang.com/5cc85c070001f88407500640.jpg

https://img.mukewang.com/5cc85c090001f66a07500640.jpg

https://img3.mukewang.com/5cc85c0a000189d807500640.jpg

inner

https://img4.mukewang.com/5cc85c5b0001124f07500518.jpg

https://img.mukewang.com/5cc85c5c0001e5b907500555.jpg

https://img3.mukewang.com/5cc85c5c00018a2707500554.jpg

https://img.mukewang.com/5cc85c5c0001b59b07500779.jpg

https://img1.mukewang.com/5cc85c5c0001823807500762.jpg

https://img1.mukewang.com/5cc85c5e000103fa07500566.jpg

https://img3.mukewang.com/5cc85c5e0001ad4907500735.jpg

方法一:

<img src={require('../img/icon1.png')} alt="" />


方法二:

import search from '../img/search.png'
import user from '../img/user.png'
<img src={search} alt="" />
<img src={user} alt="" />

背景图片引用方法

const divStyle = {
color: 'red',
backgroundImage: 'url(' + imgUrl + ')',
// 或者 background: `url${require("1.jpg")}`
};
function HelloWorldComponent() {
return <div style={divStyle}>Hello World!</div>;
}

https://img4.mukewang.com/5ccd4d160001bf3802000200.jpg

https://img3.mukewang.com/5ccd4d160001fac002000200.jpg

https://img4.mukewang.com/5ccd4d1600018e2702000200.jpg

https://img3.mukewang.com/5ccd4d17000156e802000200.jpg

https://img1.mukewang.com/5ccd4d17000195dd02000200.jpg


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP