React基础知识 [ 新手上路学这一篇就够了 ]
Posted ༺初辰༻
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React基础知识 [ 新手上路学这一篇就够了 ]相关的知识,希望对你有一定的参考价值。
一、什么是React?
React是一个用于构建用户界面的javascript库,起源于facebook的内部项目,后续在13年开源了出来
1.特点
- 声明式:只需要描述UI看起来是什么样式,就跟写html一样,React负责渲染UI
- 基于组件:组件是React最重要的内容,组件表示页面中的部分内容
- 适用范围广:使用React可以开发Web应用,使用React可以开发移动端,可以开发VR应用
2.React基本使用
新建挂载点
<div id="root"></div>
React的引用
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
创建React元素并渲染到页面
<script>
// 参数一:元素名称;参数二:元素属性;参数三:元素的子节点
const title = React.createElement('h1', null, 'Hello React')
// 参数一:要渲染的react元素;参数二:挂载点
ReactDOM.render(title, document.getElementById('root'))
</script>
二、React脚手架
- 脚手架是开发现代Web应用的必备
- 充分利用 Webpack,Babel,ESLint等工具辅助项目开发
- 零配置,无需手动配置繁琐的工具即可使用
- 关注业务,而不是工具配置
1.使用React脚手架初始化项目
初始化项目
npx create-react-app myreact
- npx 目的:提升包内提供的命令行工具的使用体验
- create-react-app 这个是脚手架名称 不能随意更改
- myreact 自己定义的项目名称不能大写
启动项目
npm start
2.脚手架中使用React
删除 src 目录下的 所有文件,然后创建 index.js 文件
导入react和react-dom两个包
import React from 'react'
import ReactDOM from 'react-dom'
创建元素
let h1 = React.createElement('h1', null, 'Hello 初辰')
渲染到页面
ReactDOM.render(h1, document.getElementById('root'))
三、JSX的使用
1.概述
1.1 JSX产生的原因
使用 createElement() 方法创建复杂 dom 结构
const ul = React.createElement('ul', null,
React.createElement('li', null, 'Hello'),
React.createElement('li', null, 'React'),
React.createElement('li', null,
React.createElement('span', null, '我是'),
React.createElement('span', null, '初辰')
)
)
使用 JSX 语法创建复杂 dom 结构
const ul =
<ul>
<li>Hello</li>
<li>React</li>
<li>
<span>我是</span>
<span>初辰</span>
</li>
</ul>
由于通过 createElement() 方法创建的 React 元素有一些问题,代码比较繁琐,结构不直观,无法一眼看出描述的结构,不优雅,用户体验不爽
1.2 JSX的概述
JSX是JavaScript XML 的简写,表示在JavaScript代码中写HTML格式的代码
优势:声明式语法更加直观,与HTML结构相同,降低了学习成本,提升开发效率
2.入门
2.1 使用步骤
使用JSX语法创建react元素
let h1 = <h1>初辰通过JSX创建的元素</h1>
使用ReactDOM来渲染元素
ReactDOM.render(h1,document.getElementById('root'))
2.2 为什么在脚手架中可以使用JSX语法?
- JSX 不是标准的ECMAScript语法,它是ECMAScript的语法拓展
- 需要使用babel编译处理后,才能在浏览器环境中使用
- create-react-app脚手架中已经默认有该配置,无需手动配置
- 编译JSX语法的包: @bable/preset-react
2.3 注意点
- React元素的属性名使用驼峰命名法
- 特殊属性名:class -> className,for -> htmlFor,tabindex -> tabIndex
- 如果没有子节点的React元素可以用
/>
来结束 - 推荐:使用 小括号包裹JSX,从而避免JS中自动插入分号报错
3.JSX语法
JSX是来描述页面的结构,一般在编写业务逻辑渲染页面的时候,需要涉及到传递值,调用函数,判断条件,循环等,这一些在JSX中都能得到支持
3.1 嵌入JS表达式
语法:
{JavaScritp表达式}
例子:
let content = '插入的内容'
let h1 = <h1>初辰通过JSX创建的元素+ {content}</h1>
3.2 条件渲染
根据不同的条件来渲染不同的JSX结构
let isShow = false
let text = ''
if (isShow === true) {
text = '初辰1'
} else {
text = '初辰2'
}
写JSX的条件渲染与我们之前编写代码的逻辑是差不多的,根据不同的判断逻辑,返回不同的 JSX结构,然后渲染到页面中
3.3 列表渲染
- 如果需要渲染一组数据,我们应该使用数组的 map () 方法
- 注意:渲染列表的时候需要添加key属性,key属性的值要保证唯一
- 原则:map()遍历谁,就给谁添加key属性
- 注意:尽量避免使用索引号作为key
let arr = [
{id:1,name:'三国演义'},
{id:2,name:'水浒传'},
{id:3,name:'西游记'},
{id:4,name:'红楼梦'}
]
let ul = (<ul>
{arr.map(item => <li key={item.id}>{item.name}</li>)}
</ul>)
ReactDOM.render(ul,document.getElementById('root'))
3.4 样式处理
行内样式 -style
在style里面我们通过对象的方式传递数据
let ul = (<ul style={{ 'color': 'red', "backgroundColor": 'pink' }}>
{arr.map(item => <li key={item.id}>{item.name}</li>)}
类名 -className
创建CSS文件 index.css 编写样式代码
.container {
text-align: center;
color: rgb(124, 11, 11);
background-color: rgb(105, 105, 243);
}
在js中进行引入,然后设置类名即可
import './index.css'
let ul = (<ul className='container'>
{arr.map(item => <li key={item.id}>{item.name}</li>)}
</ul>)
四、React组件
- 组件是React的一等公民,使用React就是在用组件
- 组件表示页面中的部分功能
- 组合多个组件实现完整的页面功能
- 特点:可复用、独立、可组合
1.组件的创建方式
1.1 函数创建组件
- 函数组件:使用JS的函数创建组件
- 约定:函数名称必须以大写字母开头,函数组件必须有返回值,表示该组件的结构,如果返回值为null,表示不渲染任何内容
编写函数组件
function Hello () {
return (
<div>这是初辰的第一个函数组件</div>
)
}
利用ReactDOM.render()进行渲染
ReactDOM.render(<Hello />, document.getElementById('root'))
1.2 类组件
- 使用ES6语法的class创建的组件
- 约定1:类名称也必须要大写字母开头
- 约定2:类组件应该继承React.Component父类,从而可以使用父类中提供的方法或者属性
- 约定3:类组件必须提供 render 方法
- 约定4:render方法中必须要有return返回值
创建class类,继承React.Component,在里面提供render方法,在return里面返回内容
class Hello extends React.Component {
render () {
return (
<div>这是初辰的第一个类组件</div>
)
}
}
通过ReactDOM进行渲染
ReactDOM.render(<Hello />,document.getElementById('root'))
1.3 抽离成单独的JS文件
创建Hello.js, 在Hello.js 中导入React,创建组件,在Hello.js中导出
import React from 'react'
class fn extends React.Component {
render () {
return (
<div>单独抽离出来的 Hello</div>
)
}
}
export default fn
在index.js中导入Hello组件,渲染到页面
import ReactDOM from 'react-dom';
import Hello from './hello'
ReactDOM.render(<Hello />, document.getElementById('root'))
2.React事件处理
2.1 事件绑定
- React事件绑定语法与DOM事件语法相似
- 语法:on+事件名称=事件处理函数,比如 onClick = function(){}
- 注意:React事件采用驼峰命名法
class Hello extends React.Component {
clickHandle () {
console.log('点击了')
}
render () {
return (
<button onClick={this.clickHandle}>点我点我点我</button>
)
}
}
2.2 事件对象
- 可以通过事件处理函数的参数获取到事件对象
- React中的事件对象叫做:合成事件
- 合成事件:兼容所有浏览器,无需担心跨浏览器兼容问题
- 除兼容所有浏览器外,它还拥有和浏览器原生事件相同的接口,包括
stopPropagation()
和preventDefault()
- 如果你想获取到原生事件对象,可以通过
nativeEvent
属性来进行获取
clickHandle (e) {
console.log(e.nativeEvent)
}
2.3 支持的事件
事件 | 事件名 | 属性 |
---|---|---|
Clipboard Events 剪切板事件 | onCopy onCut onPaste | DOMDataTransfer clipboardData |
compositionEvent 复合事件 | onCompositionEnd onCompositionStart onCompositionUpdate | string data |
Keyboard Events 键盘事件 | onKeyDown onKeyPress onKeyUp | number keyCode |
Focus Events 焦点事件 | onFocus onBlur | DOMEventTarget relatedTarget |
Form Events 表单事件 | onChange onInput onInvalid onSubmit | |
Mouse Events 鼠标事件 | onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp | |
Pointer Events 指针事件 | onPointerDown onPointerMove onPointerUp onPointerCancel onGotPointerCapture onLostPointerCapture onPointerEnter onPointerLeave onPointerOver onPointerOut | |
Selection Events 选择事件 | onSelect | |
Touch Events 触摸事件 | onTouchCancel onTouchEnd onTouchMove onTouchStart | |
UI Events UI 事件 | onScroll | |
Wheel Events 滚轮事件 | onWheel | number deltaMode number deltaX number deltaY number deltaZ |
Media Events 媒体事件 | onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay | |
Image Events 图像事件 | onLoad onError | |
Animation Events 动画事件 | onAnimationStart onAnimationEnd onAnimationIteration |
3.有状态组件和无状态组件
- 函数组件又叫做 无状态组件,类组件又叫做 有状态组件
- 状态(state) 即数据
- 函数组件没有自己的状态,只负责数据展示
- 类组件有自己的状态,负责更新UI,让页面动起来
3.1 State和SetState
state基本使用
- 状态(state)即数据,是组件内部的私有数据,只能在组件内部使用
- state的值是对象,表示一个组件中可以有多个数据
- 通过this.state来获取状态
state = {
count: 0
}
render () {
return (
<div>计数器 :{this.state.count}</div>
)
}
setState() 修改状态
- 语法:this.setState({要修改的数据})
- 不要直接修改state中的值,这是错误的
- setState() 作用:1.修改 state 2.更新UI
- 思想:数据驱动视图
addCount = () => {
this.setState({
count: this.state.count + 1
})
}
render () {
return (
<div>
<div>计数器 :{this.state.count}</div>
<button onClick={this.addCount}>+1</button>
</div>
)
}
- 修改state里面的值我们需要通过 this.setState() 来进行修改
- React底层会有监听,一旦我们调用了setState导致了数据的变化,就会重新调用一次render方法,重新渲染当前组件
4.组件的props
- 组件时封闭的,要接受外部数据应该通过props来实现
- props的作用:接收传递给组件的数据
- 传递数据:给组件标签添加属性
- 接收数据:函数组件通过 参数 props接收数据,类组件通过 this.props接收数据
class App extends React.Component {
render () {
return (
<div>接收到的数据:{this.props.text}</div>
)
}
}
ReactDOM.render(<App text={'Hello Word'} />, document.getElementById('root'))
特点
- 可以给组件传递任意类型的数据
- props是只读属性,不能对值进行修改
- 注意:使用类组件时,如果写了构造函数,应该将props传递给super(),否则,无法在构造函数中获取到props,其他的地方是可以拿到的
5.组件通讯的三种方式
5.1 父组件传递数据给子组件
- 父组件提供要传递的state数据
- 给子组件标签添加属性,值为state中的数据
- 子组件中通过props接收父组件中传递的数据
class App extends React.Component {
render () {
return (
<div>接收到的数据:{this.props.text}</div>
)
}
}
ReactDOM.render(<App text={'Hello Word'} />, document.getElementById('root'))
5.2 子组件传递数据给父组件
- 利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数
- 父组件提供一个回调函数,用来接收数据
- 将该函数作为属性的值,传递给子组件
class Fat extends React.Component {
getSonMsg = (msg) => {
console.log(msg);
}
render () {
return (
<Son getMsg={this.getSonMsg} />
)
}
}
class Son extends React.Component {
handleClick = () => {
this.props.getMsg('子元素的值')
}
render () {
return (
<button onClick={this.handleClick}>点我传值</button>
)
}
}
ReactDOM.render(<Fat />, document.getElementById('root'))
5.3 Context跨组件传递数据
如果出现层级比较多的情况下(例如:爷爷传递数据给孙子),我们会使用Context来进行传递
使用步骤
调用 React.createContext() 创建 Provider(提供数据) 和 Consumer(消费数据) 两个组件
const {Provider,Consumer} = React.createContext()
使用Provider 组件作为父节点,设置value属性,表示要传递的数据
<Provider value="李白"><Node /></Provider>
哪一层想要接收数据,就用Consumer进行包裹,在里面回调函数中的参数就是传递过来的值
<Consumer>{data => <span>子节点--{data}</span>}</Consumer>
6. props进阶
6.1 children属性
- children属性: 表示组件标签的子节点,当组件标签有子节点时,props就会有该属性
- children属性与普通的props一样,值可以使任意值(文本、react元素、组件、甚至是函数)
function Fat (props) {
return (
<div>组件的子节点:{props.children}</div>
)
}
ReactDOM.render(<Fat>初辰</Fat>, document.getElementById('root'))
6.2 props校验
- 对于组件来说,props是外来的,无法保证组件使用者传入什么格式的数据
- 如果传入的数据不对,可能会导致报错
- 关键问题:组件的使用者不知道需要传递什么样的数据
- props校验:允许在创建组件的时候,指定props的类型、格式等
- 作用:捕获使用组件时因为props导致的错误,给出明确的错误提示,增加组件的健壮性
使用步骤 - 安装包 prop-types (npm add props-types)
- 导入prop-types 包
- 使用 组件名.propTypes={} 来给组件的props添加校验规则
- 校验规则通过PropTypes对象来指定
import PropTypes from 'prop-types'
Fat.propTypes = {
name: PropTypes.string
}
以上是关于React基础知识 [ 新手上路学这一篇就够了 ]的主要内容,如果未能解决你的问题,请参考以下文章