目录
3.1 函数组件使用钩子 useState() 来创建state
3.2 类组件中state统一存储到了实例对象的state属性中
4.1 函数组件 从React处获取DOM对象 useRef()
4.2 类组件使用 React.createRef() 获取DOM
项目结构
1. React 组件创建方式
1.1 函数组件
- 函数组件就是一个返回JSX的普通
- 组件的首字母必须是大写
1.1.1 在App.js中用函数创建App组件
const App = () => {
return <div>我是App组件!</div>
};
// 导出App
export default App;
1.1.2 在index.js 引入 App组件
import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById('root'));
// React组件可以直接通过JSX渲染
root.render(<App/>);
1.2 类组件
- 类组件必须要继承React.Component
- 用啥变量都要用 this.xxx
1.2.1 在App.js中用类的方式创建App组件
import React from "react";
// import React,{Component} from "react";
class App extends React.Component {
// 类组件中,必须添加一个render()方法,且方法的返回值要是一个jsx
render() {
return <div>我是一个类组件</div>;
}
}
// 导出App
export default App;
1.2.2 在index.js 引入 App组件
- 跟 1.1.2 一模一样
1.3 区别
- 相较于函数组件,类组件的编写要麻烦一下,但是实现的功能是一样的
2. props 父传子
2.1 函数组件使用props
- 在函数组件中,属性就相当于是函数的参数,可以通过参数来访问
- 可以在函数组件的形参中定义一个props,props指向的是一个对象,包含了父组件中传递的所有参数
2.1.1 入口文件 index.js
// 引入ReactDOM
import ReactDOM from "react-dom/client"
import "./index.css"
import ListItems from './Components/ListItems'
// 创建一个JSX
const App = <div className="logo">
<ListItems />
</div>
// 获取根容器
const root = ReactDOM.createRoot(document.getElementById('root'))
// 将App渲染进根容器
root.render(App)
2.1.2 父组件 ListItems.js
import Item from "./Item/Item"
const Items = () => {
const list = [
{ id: 1, des: "打王者荣耀", time: 60, date: new Date(), },
{ id: 2, des: "学习Vue", time: 120, date: new Date(), },
{ id: 3, des: "学习React", time: 20, date: new Date() },
]
return <div className="items">
{
list.map(item => <Item key={item.id} des={item.des} time={item.time} date={item.date}></Item>)
}
</div>
}
export default Items
2.1.3 子组件 Item.js
const Item = (props) => {
console.log(props, 'props');
return <div className="content">
<h2 className="des">{props.des}</h2>
<div className="time">{props.time}分钟</div>
{/* 显示的是 中文的 五月 */}
<div style={{ background: '#f00' }}>{props.date.toLocaleString('zh-CN', { month: 'long' })}</div>
</div>
}
export default Item
2.2 类组件使用props
- 类组件的props是存储到类的实例对象中,可以直接通过实例对象访问,this.props
2.2.1 入口文件 index.js
// 引入ReactDOM
import ReactDOM from "react-dom/client"
import "./index.css"
import App from './App'
// 获取根容器
const root = ReactDOM.createRoot(document.getElementById('root'))
// 将App渲染进根容器
root.render(<App />)
2.2.2 App.js
import React from "react";
import ListItems from "./Components/ListItems"
class App extends React.Component {
render() {
return <ListItems></ListItems>
}
}
export default App
2.2.3 父组件 ListItems.js
import React from "react";
import Item from "./Item/Item"
class ListItems extends React.Component {
list = [
{ id: 1, des: "打王者荣耀", time: 60, date: new Date(), },
{ id: 2, des: "学习Vue", time: 120, date: new Date(), },
{ id: 3, des: "学习React", time: 20, date: new Date() },
]
render() {
return <div className="items">
{
this.list.map(item => <Item key={item.id} des={item.des} time={item.time} date={item.date}></Item>)
}
</div>
}
}
export default ListItems
2.2.4 子组件 Item.js
import React from "react";
class Item extends React.Component {
render() {
return <div className="content">
<h2 className="des">{this.props.des}</h2>
<div className="time">{this.props.time}分钟</div>
{/* 显示的是 中文的 五月 */}
<div style={{ background: '#f00' }}>{this.props.date.toLocaleString('zh-CN', { month: 'long' })}</div>
</div>
}
}
export default Item
3. state 在React中注册变量
* state相当于一个变量,
* 只是这个变量在React中进行了注册,
* React会监控这个变量的变化,当state发生变化时,会自动触发组件的重新渲染
* 使得我们的修改可以在页面中呈现出来
3.1 函数组件使用钩子 useState() 来创建state
- 钩子需导入后使用:
import {useState} from "react";
- useState() 需要一个值作为参数,这个值就是state的初始值,返回一个数组
- 数组中第一个元素,是初始值,初始值只用来显示数据,直接修改不会触发组件的重新渲染
- 数组中的第二个元素,是一个函数,通常会命名为setXxx,此函数用来修改state,调用其修改state后会触发组件的重新渲染,并且使用函数中的值作为新的state值
App.js
import { useState } from "react";
const App = () => {
const [count, setCounter] = useState(0)
const [other, setOther] = useState({
age: 18,
gender: 'w'
})
const handleCilck = () => {
// setCounter(count + 1)
// 会有异步的问题
// setCounter(count + 1)
/*
* setState()中回调函数的返回值将会成为新的state值
* 回调函数执行时,React会将最新的state值作为参数传递
* */
setCounter(prevCount => {
return prevCount + 1
});
}
const handleCilckOther = () => {
// other会从两个属性变成一个属性
// setOther({ gender: 'm' })
setOther({
...other, gender: 'm'
});
}
return <div className="items">
<div>{count}</div>
<div>{other.age}</div>
<div>{other.gender}</div>
<button onClick={handleCilck}>点击</button>
<button onClick={handleCilckOther}>改变other</button>
</div>
}
export default App
注: state实际就是一个被React管理的变量
- 当我们通过setState()修改变量的值时,会触发组件的自动重新渲染
- 只有state值发生变化时,组件才会重新渲染
- 当state的值是一个对象时,修改时是使用新的对象去替换已有对象
- 当通过setState去修改一个state时,并不表示修改当前的state,修改的是组件下一次渲染时state值
- setState()会触发组件的重新渲染,它是异步的
- 所以当调用setState()需要用旧state的值时,一定要注意
- 有可能出现计算错误的情况
- 为了避免这种情况,可以通过为setState()传递回调函数的形式来修改state值
3.2 类组件中state统一存储到了实例对象的state属性中
- 可以通过 this.state 来访问
- 通过 this.setState() 对其进行修改
- 当我们通过 this.setState() 修改state时,React只会修改设置了的属性
App.js
import React from "react";
class App extends React.Component {
state = {
count: 0,
name: 'hahh',
other: {
age: 18,
gender: 'w'
}
}
// 必须用箭头函数,保证this指向
handleCilck = () => {
// this.setState({ count: 2 })
// 会有异步的问题
// this.setState({ count: this.state.count + 1 })
// prevState 是一个对象
this.setState(prevState => {
return {
count: prevState.count + 1
}
});
}
handleCilckOther = () => {
// other会从两个属性变成一个属性,因为other没有直接存储到state中
// this.setState({ other: { gender: 'm' } })
this.setState({
other: { ...this.state.other, gender: 'm' }
});
}
render() {
return <div className="items">
<div>{this.state.count}</div>
<div>{this.state.name}</div>
<div>{this.state.other.age}</div>
<div>{this.state.other.gender}</div>
<button onClick={this.handleCilck}>点击</button>
<button onClick={this.handleCilckOther}>改变other</button>
</div>
}
}
export default App
3.3 区别:
- 函数组件中,响应函数直接以函数的形式定义在组件中
- 在类组件中,响应函数是以类的方法来定义,之前的属性都会保留,但是这你仅限于直接存储于state中的属性
4. React 获取DOM对象
4.1 函数组件 从React处获取DOM对象 useRef()
1. 创建一个存储DOM对象的容器
- 使用 useRef() 钩子函数
钩子函数的注意事项:
① React中的钩子函数只能用于函数组件或自定义钩子
② 钩子函数只能直接在函数组件中调用
2. 将容器设置为想要获取DOM对象元素的ref属性
<div ref={divRef}>....</div>
const divRef= useRef()
- React会自动将当前元素的DOM对象,设置为容器current属性
返回的就是一个普通的JS对象 {current:undefined}
* - 所以我们直接创建一个js对象,也可以代替useRef()
* - 区别:
* 我们创建的对象,组件每次重新渲染都会创建一个新对象
* useRef()创建的对象,可以确保每次渲染获取到的都是同一个对象
* - 当你需要一个对象不会因为组件的重新渲染而改变时,就可以使用useRef()
import React, { useRef } from "react";
const App = () => {
const divRef = useRef() // 创建一个容器
const handleChange = () => {
// 原生的DOM对象
// document.getElementById('haha').innerText = "哈哈哈哈"
// react中的DOM对象
console.log(divRef.current)
divRef.current.innerText = "哈哈哈哈"
}
return <div className="items">
<div id="haha" ref={divRef}>hhhhh</div>
<button onClick={handleChange}>改变div里面的内容</button>
</div>
}
export default App
4.2 类组件使用 React.createRef() 获取DOM
1.创建一个属性,用来存储DOM对象
divRef = React.createRef();
2.将这个属性设置为指定元素的ref值
<div ref={divRef}>....</div>
import React, { Component } from 'react'
class App extends Component {
divRef = React.createRef()
handleChange = () => {
// 原生的DOM对象
// document.getElementById('haha').innerText = "哈哈哈哈"
// react中的DOM对象
console.log(this.divRef.current, 'lei')
this.divRef.current.innerText = "哈哈哈哈"
}
render() {
return <div className="items">
<div id="haha" ref={this.divRef}>hhhhh</div>
<button onClick={this.handleChange}>改变div里面的内容</button>
</div>
}
}
export default App
学习笔记,只为了记录!!!