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 onPasteDOMDataTransfer clipboardData
compositionEvent 复合事件onCompositionEnd onCompositionStart onCompositionUpdatestring data
Keyboard Events 键盘事件onKeyDown onKeyPress onKeyUpnumber keyCode
Focus Events 焦点事件onFocus onBlurDOMEventTarget 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 滚轮事件onWheelnumber 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.修改 state2.更新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路由

1.使用步骤

安装

npm install --save react-router-dom

导入路由的三个核心组件: Router / Route / Link

  • Router组件:包裹整个应用,一个React应用只需要使用一次
    – 两种常用的RouterHashRouterBrowserRouter
    HashRouter: 使用URL的哈希值实现 (localhost:3000/#/first)
    – 推荐 BrowserRouter:使用H5的history API实现(localhost3000/first)
  • Link组件:用于指定导航链接(a标签)
    – 最终Link会编译成a标签,而to属性会被编译成 a标签的href属性
  • Route组件:指定路由展示组件相关信息
    path属性:路由规则,这里需要跟Link组件里面to属性的值一致
    component属性:展示的组件
    Route写在哪,渲染出来的组件就在哪
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'

使用Router 组件包裹整个应用
在这里插入图片描述
使用Link组件作为导航菜单(路由入口)

<Link to="/home">首页</Link>

使用Route组件配置路由规则和要展示的组件(路由出口)

<Route path="/home" component={Home}></Route>

2.编程式导航

  • 场景:点击登陆按钮,登陆成功后,通过代码跳转到后台首页,如何实现?
  • 编程式导航:通过JS代码来实现页面跳转
  • history是React路由提供的,用于获取浏览器历史记录的相关信息
  • push(path):跳转到某个页面,参数path表示要跳转的路径
  • go(n):前进或后退功能,参数n表示前进或后退页面数量
this.props.history.push('/first')

注意:只有使用 Route 组件的导航,才拥有 history 属性。

  • 否则报错:TypeError: Cannot read property ‘push’ of undefined
  • 解决方法:高阶组件中的withRouter, 作用是将一个组件包裹进Route里面, 然后react-router的三个对象history, location, match就会被放进这个组件的props属性中。所以withRouter的作用就是, 如果我们某个东西不是一个Router, 但是我们要依靠它去跳转一个页面, 就可以使用withRouter来做.
import { withRouter } from 'react-router-dom'
.....
export default withRouter(fn)
  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初辰ge

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值