React基础

目录

TODO1

React概述

React的使用

React脚手架的使用

全局安装

npx安装

在脚手架中使用React

JSX

[1. JSX的基本使用](#1. JSX的基本使用)

[1.1 为什么用JSX](#1.1 为什么用JSX)

[1.2 JSX简介](#1.2 JSX简介)

[1.3 使用步骤](#1.3 使用步骤)

[1.4 脚手架中能用JSX](#1.4 脚手架中能用JSX)

[1.5 注意点](#1.5 注意点)

[2. 在JSX中使用JavaScript表达式](#2. 在JSX中使用JavaScript表达式)

[2.1 嵌入js表达式](#2.1 嵌入js表达式)

[2.2 注意点](#2.2 注意点)

3.JSX的条件渲染

4.JSX的列表渲染

5.JSX的样式处理

[5.1 行内样式 style](#5.1 行内样式 style)

[5.2 类名 className](#5.2 类名 className)

TODO2

组件

1.组件介绍

2.组件的两种创建方式

[2.1 使用函数创建组件](#2.1 使用函数创建组件)

[2.2 使用类创建组件](#2.2 使用类创建组件)

[2.3 将组件抽离为单独的js文件](#2.3 将组件抽离为单独的js文件)

事件处理

1.事件绑定

2.事件对象

3.有状态组件和无状态组件

4.state和setState()

[4.1 state的基本使用](#4.1 state的基本使用)

[4.2 setState修改状态](#4.2 setState修改状态)

[4.3 从JSX中抽离事件处理程序](#4.3 从JSX中抽离事件处理程序)

this指向

1.箭头函数

2.Function.prototype.bind()

3.class的实例方法

4.总结

表单处理

1.受控组件

2.非受控组件

TODO3

组件通讯

1.组件通讯的定义

2.组件通讯的三种方式

props

props深入

Context


TODO1

React概述

1.是用于构建用户界面的JavaScript库

2.特点: 声明式 基于组件 学习一次随处使用

①声明式 只需要描述UI看起来是什么样 react负责渲染并在数据变化时更新

②组件 表示页面中的部门内容 组合复用多个组件可以实现完整的页面功能 (最重要)

③学习一次,随处使用 web应用 移动端原生应用 虚拟现实应用均可使用

3.推荐使用脚手架使用react

React的使用

//引入react和react-dom两个js文件
<script src="./node_modules/react/umd/react.development.js"></script>
<script src="./node_modules/react-dom/umd/react-dom.development.js"></script> 

//创建react元素
        //参数一 元素名称 参数二 元素属性 参数三 元素的子节点
         const title = React.createElement('h1',null,'hello react')
          
        //  const title = React.createElement(
        //     'p',
        //     { title: '我是标题',id:'p1'},
        //      'hello react'
        //      React.createElement('span',null,'我是span节点')
        //      )

//渲染react元素  (仅针对web开发)
         //参数一 要渲染的react元素 参数二 挂载点-》页面中指定的位置
         ReactDOM.render(title,document.getElementById('root'))

React脚手架的使用

全局安装脚手架和npx安装脚手架的区别

全局安装

React脚手架的使用

npm start:执行开发模式,运行该项目

npm run build:执行生产模式,打包该项目

npm test:执行测试模式,测试该项目

npm run eject:将webpack相关文件暴露出来(React设置webpack文件隐藏

npx安装

npx create-react-app 是固定命令,create-react-app是React脚手架的名称

npx 命令会帮助我们临时安装create-react-app包,然后初始化项目完成之后会自自动删掉

不需要进行全局安装(但是我已经安装完了··

初始化项目

npx create-react-app my-app

启动项目

在项目的根目录下执行** 先cd项目

npm start

在脚手架中使用React

脚手架能够帮助我们自动刷新页面

//1.导入react和react-dom两个包(非script标签导入)使用es6中的模块化语法
import React from 'react'
import ReactDOM from 'react-dom'

//2. 调用React.createElement()方法创建react元素
const title = React.createElement('p',null,'hello react')

//3. 调用ReactDOM.render()方法渲染react元素到页面中
ReactDOM.render(title,document.getElementById('')  //挂载点 

脚手架文件介绍

脚手架文件介绍

JSX

  1. JSX的基本使用

1.1 为什么用JSX

React.createElement()过于繁琐不简洁 -》和用模板字符串一样

1.2 JSX简介

1.JavaScript XML 表示在JavaScript中写HTML格式的代码

2.声明式语法更加直观 开发效率高 学习成本低

3.是React的核心内容 完全利用js语言自身的能力来编写UI

1.3 使用步骤

//1.使用JSX语法创建 React元素
const title =<h1> hello jsx</h1>

//2.使用ReactDOM.render()方法渲染react元素到页面中
ReactDOM.render(title,root)

1.4 脚手架中能用JSX

1.JSX是ECMAScript的扩展

2.需要使用babel编译处理才能在浏览器环境中使用 (脚手架中已有相关配置)

3.编译JSX语法的包为:@babel/preset-react

1.5 注意点

1.元素的属性名用驼峰命名法

2.特殊属性名 class->className for->htmlFor tabindex->tabIndex

3.没有子节点的React元素可以用/>结束

<span>hello react</span>

hello react</span>

4.使用()包裹JSX (结构清晰 避免JS自动插入分号陷阱)

const div=(
<div>hello jsx</div>
)
  1. 在JSX中使用JavaScript表达式

2.1 嵌入js表达式

1.数据存储在js中

2.语法:{JavaScript}表达式

const name ='cc'
const div ={
    <div>
        hello {name}
    </div>
}

2.2 注意点

1.单大括号中可以使用任意的JavaScript表达式

2.JSX自身也是JavaScript表达式

const sayHi=() => 'Hi'

const title =(
    <h1>可以使用任意的函数表达式</h1>
    <span>{1}</span>
    <span>{'a'}</span>
    <span>{1+2}</span>
    <span>{3>5?1:0}</span>
    <span>{sayHi()}</span>
)

const h1=<h1>cc</h1>
const div=(
    <div> JSX自身也是js表达式 {h1} </div>
)

3.js中的对象一般只会出现在style属性

4.{}中不能出现语句

3.JSX的条件渲染

1.场景:loading效果

2.条件渲染 根据条件渲染特定的jsx结构

3.可以使用if/else或三元运算符或逻辑与运算符实现

//if else
         const loadData=() =>{
            if(isLoading){
                return <div>数据加载中 请稍后 </div>
            }
            return (
                <div>数据加载完成,这里显示的是数据</div>
            )
         }

         const div=(
            <div>
                {loadData()}
            </div>
         )


//三元表达式
const loadData =() =>{
return isLoading ?(<div>数据加载中</div>) :(<div>数据加载完成,这里显示的是数据</div>)
}


//逻辑与运算符 --适合要么展示 要么隐藏
const loadData=() =>{
    return isLoading &&( <div> loading</div>)
}
const div=(
            <div>
                {loadData()}
            </div>
         )

4.JSX的列表渲染

1.要渲染一组数据 应该使用map()方法

2.渲染列表时要加key属性 key属性的值要保证唯一-id

3.map()遍历谁 就给谁加key属性

4.避免使用索引号(索引号会发生改变)

const targets =[
    {id:1,name:'react基础'},
    {id:2,name:'react进阶'},
    {id:3,name:'git+移动端开发+模块化'},
]

const list =(
    <ul>
    {targets.map(item=> <li key={item.id>{item.name}</div>)}
    </ul>
)

5.JSX的样式处理

5.1 行内样式 style

//看起来像双括号 但实际上不是 外侧的表示嵌入对象 
<h1 style={{color:'red',backgroundColor: 'skyblue'}}>
    jsx样式处理
</h1> 

5.2 类名 className

<h1 className="title">
    jsx样式处理
</h1>

//要注意引入css文件
import 'index.css'

TODO2

组件

1.组件介绍

  1. 使用react就是在使用组件
  2. 组件表示页面中的部分功能
  3. 组合多个租金按能实现完整的页面
  4. 特点:可复用、独立、可组合

2.组件的两种创建方式

2.1 使用函数创建组件

函数组件:使用js的函数(或箭头函数)创建的组件

//函数名称必须以大写字母开头
function Hello() {
    return (
    <div>函数组件是必须有返回值的,表示该组件的结构,返回值为null表示不渲染任何结构</div>
)
}

//渲染函数组件 -》用函数名作为组件标签名 
//组件名要大写的原因是 react据此区分普通组件和 react元素
//组件标签名 可以是单标签 也可以是双标签 

//箭头函数创建组件 
const Hello =() => (<div>函数组件</div>)

ReactDOM.render(<Hello />,root)

2.2 使用类创建组件

类组件:使用ES6的class创建的组件

  • 类名称也必须以大写字母开头
  • 类组件应该继承 React.Component父类,从而可以使用父类提供的方法或属性
  • 类组件必须提供render()方法
  • render()方法必须有返回值 表示该组件的结构

    //类名必须用大写字母开头
    //继承React.Component父类
    class Hello extends React.Component{
    //必须提供render()方法
    render() {
    //必须有返回值 表示该组件的结构
    return (

    类组件

    )
    }
    }
    ReactDOM.render(</Hello>,root)

2.3 将组件抽离为单独的js文件

每个组件放到单独的js文件中

  • 创建Cc.js(组件的js文件)
  • 在Cc.js中导入React
  • 创建组件(函数或类)
  • 在Cc.js中导出该组件
  • 在index.js(要使用这个组件的文件)中导入组件
  • 渲染组件

    //Cc.js
    import React from 'react'
    class Cc extends React.Component{
    render() {
    return (

    啊啊啊啊
    )
    }
    }
    //导出组件
    export default Cc

    //index.js
    //导入组件
    import Cc from '路径'
    //渲染导入的组件
    ReactDOM.render(<Cc />, document.getElementById('root'))

事件处理

1.事件绑定

  • 与DOM事件绑定语法类似
  • on+事件名称={事件处理程序} //驼峰命名法
  • 如果是类组件绑定 用this. 如果是函数组件绑定 直接写函数名字即可

    //类创建
    class App extends React.Component{
    handleClick(){
    console.log('类组件中的事件绑定')
    }
    render(){
    return(
    <button onClick={this.handleClick}> 点了会发生啥?</button>
    )
    }
    }

    //函数
    function App() {
    function handleClick(){
    console.log('函数组件中的事件绑定')
    }
    return(
    <button onClick={handleClick}>点</button>
    )
    }

    //渲染组件
    ReactDOM.render(<App />,document.getElementById('root'))

2.事件对象

通过事件处理程序的参数获取到事件对象

React中的事件对象叫合成事件(对象)

合成事件:兼容所有浏览器,无需担心跨浏览器兼容性问题(了解即可)

class App extends React.Component{
handleClick(e){
e.preventDefault()
}
render(){
    return(
    <a href="" onClick={this.handleClick}>我没加链接</a>
    )
}
}
//渲染组件
ReactDOM.render(<App/>,document.getElementById('root'))

3.有状态组件和无状态组件

状态 state即数据

  • 函数组件叫做无状态组件 只负责数据展示(静态)
  • 类组件叫做有状态组件 负责更新UI (动态)

4.state和setState()

4.1 state的基本使用

  • state是组件内部的私有数据,只能在组件内部使用
  • state的值是对象 表示一个组件中可以有多个数据

如何使用state

class Cc extends React.Component {
 //es6 class语法
    constructor(){
    super() //必须有 是es6的要求
    //初始化state
    this.state ={
        count :0
    }
}

//简洁版 实验性的public class fields语法
state = {
        count :0
    }

render(){
 return (
    <div>
        有组件状态
    </div>
)
}
}

①super()函数用于访问和调用一个对象上的父对象上的函数

②在构造函数中使用时,super关键字将单独出现,并且必须在使用this关键字之前 使用。

super关键字也可以调用父对象上的函数。

ES6 class语法拯救世界了吗 为什么要用它(?

4.2 setState修改状态

  • 状态可以改变
  • this.setState({要修改的数据})
  • 不要直接修改state中的值
  • setState() 作用 1.修改state 2.更新UI -》数据驱动视图

    this.setState({
    count:this.state.count + 1
    })

    //错误的
    this.state.count += 1

4.3 从JSX中抽离事件处理程序

如果JSX中有过多的js逻辑代码 会显得很混乱

将逻辑抽离到单独的方法中,保证结构的清晰

但是会出现事件处理程序中的this的值为undefined的情况

希望this指向组件实例(render方法中的this即为组件实例)

组件实例本质上就是一个状态集合(或一个对象)

this指向

1.箭头函数

①箭头函数自身不绑定this

②render方法中的this为组件实例,可以获取到setState()

箭头函数中的this指向

class Cc extends React.Component{
 onIncrement(){
    this.setState({ })
}
render(){
//箭头函数中的this指向外部环境,此处为:render() 方法
 return (
    <button onClick={() => this.onIncrement()}></button>
)
}
}

2.Function.prototype.bind()

class Cc extends React.Component{
    constructor() {
    super()
    this.onIncrement = this.onIncrement.bind(this)
}
//省略onIncrement
render(){
 return (
    <button onClick={this.onIncrement()}></button>
)
}
}

3.class的实例方法

①利用箭头函数形式的class实例方法

②该语法是实验性语法 但是由于babel的存在可以直接用(编译JSX的语法包)

class Cc extends React.Component{
   onIncrement =() =>{
    this.setState({...})
}
render(){
 return (
    <button onClick={this.onIncrement()}></button>
)
}
}

4.总结

推荐使用的顺序 class的实例方法>箭头函数>bind

表单处理

1.受控组件

推荐使用受控组件来处理表单

值受到React控制的表单元素

  • HTML的表单元素是可输入的 有自己的可变状态
  • React中的可变状态通常保存在State中,并且只能通过setState()方法获取

二者冲突 所以 React把state与表单元素值value绑定 由state的值来控制表单元素的值

//1.在state中添加一个状态 作为表单元素的value值(控制表单元素值的来源)
state={txt:''}
//2.给表单元素绑定change事件,将表单元素的值设置为state的值(控制表单元素值的变化)
<input type="text" value={this.state.txt}
    onChange ={e => this.setState({ txt : e.target.value })}
/>

多表单元素优化步骤

1.给表单元素加name属性,名称与state相同

2.根据表单元素类型,获取对应的值

3.在change事件处理程序中,通过[name]修改对应的state

<input
    type="text"
    name="txt"  //区分其他表单元素 名称与state相同
    value={this.state.txt}
    onChange={this.handleForm}
/>

//根据表单元素类型获取值
const value=target.type === 'checkbox'
    ?target.checked
    :target.value

//根据name设置对应的state
this.setState({
//es6的属性表达式
 [name]:value
})

2.非受控组件

1.借助ref 使用原生DONM方式来获取表单元素的值

ref的作用:获取DOM组件

2.使用步骤

①调用React.createRef()方法创建一个ref对象

②将创建好的ref对象添加到文本框中

③通过ref对象获取到文本框的值

3.大多数情况下 用受控组件

//1.调用
constructor() {
    super()
    this.txtRef = React.createRef()
}

//2.将ref添加到文本框
<input type="text" ref={this.txtRef} />

//3.通过ref对象获取到文本框的值
console.log{this.txtRef.current.value}

//实践
class App extends React.Component{
    constructor() {
    super()
    this.txtRef = React.createRef()
}
//获取文本框的值
getTxt =() =>{
    console.log('文本框的值为:', this.txtRef.current)
}
render(){
    return(
    <div>
        <input type="text" ref={this.txtRef} />
        <button onClick={this.getTxt}获取文本框的值</button>
    </div>
)
}
}

完全利用js语言的能力创建组件,这是React的思想

TODO3

组件通讯

1.组件通讯的定义

因为组件时独立且封闭的单元,默认情况下,只能使用组件自己的数据,在组件化的过程中,我们要将完整的功能拆分为多个组件,这里需要共享一些数据,所以应该让组件与外界进行"通讯"

2.组件通讯的三种方式

2.1 父组件 ->子组件

①父组件提供要传递的state数据

②给子组件标签添加属性,值为state中的数据

③子组件通过props接收父组件传递的数据

2.2 子组件 ->父组件

思路:利用回调函数,父组件提供回调,子组件调用。将要传递的数据作为回调函数的参数。

①父组件提供一个回调函数(用于接收数据)

②将该函数作为属性的值,传递给子组件。

③子组件通过props调用回调函数。

④将子组件的数据作为参数传递给回调函数。

2.3兄弟组件

将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态

思想:状态提升

公共父组件职责 1.提供共享状态 2.提供操作共享状态的方法

要通讯的子组件只需要通过props接收状态或操作状态的方法

props

  • 组件要接受外部的数据应该通过props来实现
  • props的作用:接受传递给组件的数据
  • 传递数据:给组件标签添加属性
  • 接收数据:函数组件通过参数props接收数据,类组件通过this.props接收数据
  <Hello name="jack" age={19} />
  function Hello(props){
  return (
      <div> 接收到的数据:{props.name} </div>
  )
  }
  • props特点 可以给组件传递任意类型的数据

    <Hello  
        name="rose"
        age={19}
        colors={['red','green','blue']}
        fn={() => console.log('传的是函数')}
        tag={<p>这是一个p标签</p>}
    />
    

props是只读的对象 只能读取值 但是无法修改对象

使用类组件时,如果写了构造函数,应该将props传递给super() 否则无法在构造函数中获取到props

constructor(props) {
    super(props)
}

props深入

children属性

1.表示组件标签的子节点,当组件标签有子节点时,props就会有该属性、

2.children属性与普通的props一样,值可以是任意值(文本,React元素,组件,函数)

function Hello {props}{
    return {
        <div>
            组件的子节点:{props.children}
        </div>
    }
}
<Hello> 我是子节点 </Hello>

props校验

1.因为对于组件来说,props是外来的,无法保证组件使用者传入什么格式的数据

2.如果传入数据不对,会导致组件内部报错,且组件的使用者不知道明确的错误原因。

3.添加props校验,允许在创建组件的时候,就指定props的格式和类型。捕获使用组件时因为props导致的错误,增加组件的健壮性。

步骤

1.安装prop-types包

2.导入prop-type是包

3.使用组件名.propTypes={}给组件的props添加校验规则

4.校验规则通过PropTypes对象来指定

约束规则

1.常见类型:array bool func number object string

2.React元素类型 :element

3.必填项:isRequired

4.特定结构的对象: shape({})

//添加props校验
App.propTypes={
 a:propTypes.number,
fn:propTypes.func.isRequired,
tag:PropTypes.element,
filter:PropTypes.shape({
area:PropTypes.string,
price:PropTypes,number
})
}

props默认值

场景:分页组件-》每页显示条数

作用:给props设置默认值,在未传入props时生效

App.defaultProps ={
 pageSize:10
}

Context

跨多个组件传递数据 (eg 主题 语言)

Context提供了两个组件 Provider -》用来提供数据和Consumer-》用来消费数据

//1.调用React.creatContext() 创建Provider 和Consumer 两个组件
const { Provider,Consumer} = React.createContext()
//2.使用Provider组件作为父节点
<Provider>
    <div className="App">
        <Child1 />
    </div>
</Provider>
//3.设置value属性,表示要传递的数据
<Provider value="pink">
//4.调用Consumer 组件接收数据
<Consumer>
    {data => <span>data 参数表示接收到的数据 --{data}</span>
</Consumer>

React 官方中文文档

相关推荐
齐 飞5 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
神仙别闹22 分钟前
基于tensorflow和flask的本地图片库web图片搜索引擎
前端·flask·tensorflow
aPurpleBerry1 小时前
JS常用数组方法 reduce filter find forEach
javascript
GIS程序媛—椰子1 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_0011 小时前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端1 小时前
Content Security Policy (CSP)
前端·javascript·面试
乐闻x1 小时前
ESLint 使用教程(一):从零配置 ESLint
javascript·eslint
木舟10091 小时前
ffmpeg重复回听音频流,时长叠加问题
前端
王大锤43912 小时前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
我血条子呢2 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js