React介绍
这篇笔记是我在哔哩哔哩[https://www.bilibili.com/video/av98533577?p=15](url)看的视频课程,
有点可惜的是这门课程没有提供课件和源代码,索性我就自己整理以下咯。
当然,如果时间充足建议观看原视频,因为我觉得讲得确实不错,很细致。
而我这篇笔记经过了一定的整理筛选,会更适合像我一样刚刚练习完vue项目,
还没接触比较大型的vue项目但是想先学学react体会一下差异的同学。
另:本文会有hooks入门的介绍,但是之后hooks会另载一篇,redux会另载一篇。
小白第一篇,希望各位大佬多多鼓励,拜托啦!
我们前端的几个框架无非就包括以下三种,分别是vue,react,angular其中呢,应该说受欢迎程度最高的前面两种框架。angular由于它的革命性的太高,那么在每一个版本发布之后都会颠覆了前一个版本,就导致了angular的维护成本非常高。
react特性
声明式
React 使创建交互式 UI 变得轻而易举。为你应用的每一个状态设计简洁的视图,当数据改变时 React 能有效地更新并正确地渲染组件。
组件化
创建拥有各自状态的组件,再由这些组件构成更加复杂的 UI。
灵活
React 还可以使用 Node 进行服务器渲染,或使用 React Native 开发原生移动应用。
编写Hello world!
CDN引入
//引入react核心框架底层的库:
https://unpkg.com/react-dom@16/umd/react-dom.development.js
//引入react操作DOM相关的库:
https://unpkg.com/react@16/umd/react.development.js
//引入解析js语法的Babel:
https://unpkg.com/babel-standalone@6/babel.min.js
基本语法
·ReactDOM.render
·React.createElement()
·React.Component
同理:
本质上而言,js当中的h1标签是react的语法糖。所以是我们需要用Babel来解析。
JSX介绍
概念:JS中编写HTML代码,同时HTML中嵌套JS代码。
如这里的
<h1></h1>标签。
上文我们提到了属性,那么继续:
效果:
当然这是最最最原始的方法,随着ES6的普及,我们可以使用语法糖来写。
注意,上图代码中的className是标准写法,不能用class,和ES6中的class关键字区别开来!
(以下也是)
如果我们想要更加动态的效果,不只是一直对world说hello,那么可以:
元素渲染
每次把同一个标签上去,实际上它没有任何的差异。但是当我们这个模型标签的内容发生变化了以后呢,react会来进行对比,把差异部分渲染上去,而不会重复的多次的进行插入和渲染,这就是为什么这类框架会比我们过去之前的一个框架效率要高的原因,那我们这同样给大家写个例子。官方文档中也是这个例子。 考虑一个计时器的例子:
HTML根节点
<div id="root"></div>
定义一个函数tick
function tick() {
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(element, document.getElementById('root'));
}
setInterval(tick, 1000);
这里每隔一秒循环一次
下图与上代码的tick函数同理
效果:每隔一秒更新一次有变化数据的位置
他只会更新我们这个对应的节点,前面这个节点它就不会发生变化,这个效率实际上是非常高的。让我们用过去的jQuery的话,会把整个html标签重新给他赋值渲染一遍。
组件和Props
基本语法
·函数式组件(无状态组件)
·React.Component
学过的vue同学应该都了解组件化思想。在react中有两种组件,一种是无状态的函数式组件,还有一种是基于react.Component继承的class类组件。当然随着版本的更新,新版本所推出来的hooks赋予了函数式组件状态。因此,在未来,函数式组件将是官方推荐的主力,当然class组件目前也用的比较广泛,所以我们都需要掌握。总而言之,只要有相同的UI模块需要复用那么就避免不了组件的使用。
函数式组件
这是一个简单的函数式组件:
注意: 组件名称必须以大写字母开头。
React 会将以小写字母开头的组件视为原生 DOM 标签。例如,
接下来让我们看看传参的写法:
效果:
当然,如果组件比较小,甚至只有一行代码,那么就没有必要封装了。
React.Component
下面是class类组件的写法:
效果:
这里的HelloJack从React.Component中继承了许多特性,包括生命周期、构造函数等。
关于class组件的传参,我们可以使用this,因为它是有状态的。而这里的this指向的是React.Component的实例HelloJack。
传参如下:
React生命周期
学习过vue生命周期的同学应该不会再有第一次对生命周期这个概念非常陌生的感觉了。那么react的生命周期也就是整个框架的执行过程。它的顺序是什么样子的,同时在不同的生命周期阶段会暴露出不同的构造函数,我们在构造函数里面就可以做很多不同的功能。我们分为四个阶段:
- 组件初始化阶段(属性和状态初始化)
- 组件加载阶段
- 数据更新阶段
- 组件销毁阶段
这个是关于整个生命周期的流程。
初始化阶段:
组件加载阶段:
其中render方法是非常基础的阶段,不像其他函数没有需求就不需要写,render是必须写的。
接下来,我们进行数据更新的演示:
更改state的时候不要用以下的错误语法:
判断数据是否要更新:
那么这里的unmounting和props的过程就不演示了,主要在于理解react生明周期的含义。
事件处理
上文提到了,我们绑定了一个onClick事件:
首先,如果我们这样定义函数,该函数将不会绑定class的this:
这里的this打印出来是undefined。
那么我们来看看正确写法打印出来的this是什么样子:this指向我们的实例。
当然,我们如果不用上面的正确方法,也有其他方法,不过更麻烦。
这里的this打印出来是undefined,那么我们就在组件初始化的阶段为该函数绑定当前的this。
bind关键字用于作用域,我们用它来绑定当前的实例。那么还有第三种方法可以让该函数有this,在绑定事件时这样写:
总之,我们不能就只这样定义:
推荐这样更加合理:
条件处理
下面演示三个组件:App组件、登录组件和登出组件。通过演示,写明白if,else以及三元表达式等的逻辑判断。
在定义App组件时,我们先改改初始化状态的方法:
接下来,我们先定义两个组件:登录、登出,由于我们暂时不需要太复杂的生命周期函数,所以我们使用函数组件:
App组件如下:
以上这个例子当中,我们可以通过点击更新数据的按钮触发updateUser事件。那么该事件会将state中的数据变为true。那么此时根据if else的控制语句,我们将显示login组件。
我们还可以再优化一下写法:
当然,我们也可以在子组件中做控制。我们接下来的例子是通过点击子组件的按钮来加载不同的状态。
props是一个属性,我们通过props把父组件的方法传给了子组件。
同时我们也改一下updateUser这个方法:
这样下来,整个例子就结束了。
列表渲染
这部分的内容实际上就类似于vue当中的for循环渲染了。但在react我们并没有指令这么一说,我们只能通过原生数组的方法把数据渲染出来。
上例子:
然后我们在return中写:
欧克,让我们看看效果:
当然,我们也可以用for循环写:
只要可以到达往listItem中push的目的就行。
接下来,我们把这个循环的数据变得更复杂一些:
那我们可以这样写:
效果:
表单应用
表单应用是非常常见的一个工作方式,vue和angular我们都知道是双向绑定的。只需要我们通过一个指令添加上去。我们就可以直接去获取这个值,而不需要再用其他的方法,但是呢,react项目的本身相对来说会稍微麻烦一点,我们需要去绑定事件去获取他的值。因为reactd这个框架是单向的,从组件到表单都是单向的。因此呢,我们包括后期的redux等等,我们都需要通过数据流量一层一层往下传递。我最终的能够拿到这个最外层的这个富集对象这个值。
接下来演示一个demo:
这里是类似原生JS的event传参,相信大家应该都明白。
效果:
脚手架使用
npm install -g create-react-app
yarn add -g create-react-app
create-react-app react-demo
以上三种均可以安装react脚手架,我们的Babel解析、ESlint等全处理好了,我们只需要关注业务逻辑。
我这里用的是
cnpm i -g create-react-app,全局安装。
创建项目:npx create-react-app 项目名称
打开项目:cd 项目名称
启动项目:npm start
暴露配置项:npm run eject
创建项目:创建时间有点长,完成后就是这样了。
打开项目:
index.js:
我们先把项目跑起来:
效果:默认监听3000端口
同时,这里解释一下scripts中的命令:
注意这里的
npm run eject暴露webpack配置项是不可逆的,我们这里暴露演示一下:
直接y:
来看看列表:
同时,package.json中也暴露出了许多插件:
当然,以上我们并不需要怎么关心。正真当我们无法被满足需求的时候,我们就要修改webpack.config.js中的配置了。
Ant Design上手
antd是基于 Ant Design 设计体系的 React UI 组件库,主要用于研发企业级中后台产品。
我们使用
npm install antd --save命令安装。
或者在浏览器中使用 script 和 link 标签直接引入文件,并使用全局变量 antd。
路由基本配置
我们先安装路由:
yarn add react-router-dom --save
创建router.js文件:
创建需要引入的组件并引入:
我们看一下效果:
但是这样的代码还有问题:
默认的情况下,这个路由组件都会进行匹配,从上到下挨个匹配,发现‘/login’包括‘/’,就会第一个路由给匹配出来。因此会加载App组件,再去加载Login组件。当我们一旦加了switch之后,就只会匹配第一个,当第一个匹配到就会自动终止。我们再来看一下:
但是现在还会有问题:
匹配的应该是Home组件而不是App组件,那么这时候我们还需要添加一个关键字:exact。
以下就达到我们要的效果了:
那么我们再把路由换一下:
改为:
BrowserRouter/HashRouter是路由地址的两种不同的呈现方式。效果分别是:
地址上有无#
接下来,我们看看如何做一些跳转:
这里的Link和我们的a标签没有多大差异,都只是链接而已。以上是我们通过路由的方法进行跳转,如下我们创建class类组件演示JS跳转:
效果:
路由动态配置
做过vue项目的同学应该也都见过动态路由:id表示对值得动态匹配,商品详情页就是这样一个例子。
重定向:
404:
*表示匹配所有,当匹配不到的时候就会跳到404页面。
Hooks
在16.8新版的react中引入了hooks的相关概念,那么他赋予了函数组件状态以及生命周期。上文我们对于有状态的组件都是采用calss类组件,并没有用到函数组件,因为他满足不了我们的需求。但是有了hooks,函数组件将成为未来。首先,我们试想class组件有生命周期可以操作,有状态可以存值。那么这些存在的意义就是为了满足我们的业务需求,如果说函数组件有一些东西可以到达这样的效果,那么我们的需求同样是可以被满足的。 那就是接下来要介绍的一系列hooks钩子:
useState
useEffect
也有基于路由的hooks钩子:
useParams
useHistory
React Hooks
接下来演示钩子的使用:useState
上图的class应该改为className
我们在组件加载之前会有使用axios拉取数据的需求,那么我们可以使用useEffect,他是在组件
didMount和didUpdate里面执行,在组件加载和数据更新时会执行:
更新一次数据又执行了一次:
但实际开发中,数据发生变化就加载一次,这样时不合理的,所以我们可以这样:
当我们传入第二个参数——一个空数组的时候,他就只会执行一次了,因为这个是订阅型的,我们传入的参数有变化时useEffect才会执行,传入空数组就不会影响。
Router Hooks
useParams的使用:
useHistory的使用: