目录
react官网
React 英文官网
一、新建react项目命令
安装脚手架
npm install -g create-react-app
创建项目
create-react-app my-react
二、初始化react项目
1.创建的时候会把依赖一块创建出来所以就可以直接运行
运行命令
npm run start
2.删除src下面的文件(注意文件夹留下不要删除),新建index.js作为入库js文件(必须叫index.js)
3.初始化index.js(组件首字母要大写)注意:组件的封装与调用不过多讲解
import React from "react";
import ReactDOM from "react-dom";
import './index.css'
import App from "./app";
import { createRoot } from 'react-dom/client';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App />);
三、事件的简单处理
1.三种事件的处理方式和this指向问题
import React, { Component } from 'react'
export default class clickEvent extends Component {
render() {
return (
<div>
<button onClick={() =>{
console.log('标签内部处理点击事件');
}}> 点击事件1</button>
<button onClick={this.handleClick2}> 点击事件2</button>
<button onClick={() =>{
this.handleClick3(2)
}}> 点击事件3</button>
</div>
)
}
handleClick2(){
console.log('外部处理一');
}
handleClick3(e){
console.log('外部处理2,接收参数',e);
}
}
四、页面数据的更新
1.状态管理(及响应式)简单的选项卡切换
SwitchTabs.css代码
.tabs{
display: flex;
margin-top: 10px;
}
.tab{
background-color: #f1f1f1;
padding: 5px 10px;
color: #000;
}
.active{
background-color: skyBlue;
color: #fff;
}
SwitchTabs代码
import React, { Component } from 'react'
import './SwitchTabs.css'
export default class SwitchTabs extends Component {
state ={
currentShow :'选项一'
}
render() {
return (
<div className='tabs'>
<div className={"tab "+(this.state.currentShow === '选项一' ?'active':'')} onClick={()=>{
this.handleTabClick('选项一')
}}>选项一</div>
<div className={"tab "+(this.state.currentShow === '选项二' ?'active':'') } onClick={()=>{
this.handleTabClick('选项二')
}} >选项二</div>
<div className={"tab "+(this.state.currentShow === '选项三' ?'active':'')} onClick={()=>{
this.handleTabClick('选项三')
}}>选项三</div>
</div>
)
}
handleTabClick(e){
this.setState({
currentShow:e
})
}
}
五、ref的使用
import React, { Component } from 'react'
export default class ref extends Component {
myInput = React.createRef()
render() {
return (
<div>
<input ref={this.myInput} />
<button onClick={() =>{
this.getDom()
}
}>获取dom</button>
</div>
)
}
getDom(){
console.log('获取到的元素',this.myInput);
}
}
六、列表的渲染、超出隐藏、添加、删除
安装better-scroll插件使用超出隐藏滚动
npm i better-scroll
import React, { Component } from 'react'
import BetterScroll from 'better-scroll'
import './index.css'
export default class index extends Component {
state = {
list:[]
}
render() {
return (
<div>
<button onClick={() =>{
this.addList()
}}>添加列表元素</button>
<div className='box'>
<ul>
{
this.state.list.map((item,index) =>
<li key={index}>{item}
<button onClick={() =>{
this.del(index)
}}>删除单个元素</button>
</li>)
}
</ul>
</div>
</div>
)
}
del(i){
var arr = this.state.list.slice()
arr.splice(i,1)
this.setState({
list:arr
})
}
addList(){
var arr = [1,2,3,4,5,6,7,8,9,0]
this.setState({
list:arr
},() =>{
new BetterScroll('.box')
})
}
}
七、组件传参
1.父传子,可以传多个,如非字符串使用{},传参限制类似使用 类名.propTypes默认值 类名.defaultProps
父组件在标签内部使用参数名加参数进行传参
<TransferData title="父传子" show={false}/>
<TransferData title="父传子" show={true}/>
子组件使用this.props进行接收
import React, { Component } from 'react'
import kerwinPropType from 'prop-types'
export default class index extends Component {
static propTypes = {
show:kerwinPropType.bool()
}
render() {
return (
<div style={{display:'flex',width:'100px',justifyContent:'flex-end',alignItems:'center'}}>
{this.props.show && <h3>显示</h3>}
<h2>{this.props.title}</h2>
</div>
)
}
}
index.defaultProps = {
show :true
}
函数组件,无法限制类性,无法添加默认值,以形参的方式进行传参
import React from 'react'
export default function fun(data) {
return (
<div>
<h1>{data.title}</h1>
</div>
)
}
八、子传父
理解:使用父传子的方案,定义一个方法吧父组件的方法传过去,子组件操作的时候,把父组件的方法执行一下
父组件代码
<Son event={() =>{
this.setState({
val:'子组件传的'
})
}}/>
子组件代码
class Son extends Component{
render(){
return (
<div>
<button onClick={()=>{
console.log(this.props);
this.props.event()
}}>这是子组件</button>
</div>
)
}
}
九、试用ref获取子组件
ref可以获取子组件整个class类属性,包括里面的方法,dom等,试用方案请看代码
父组件
<FieId ref={this.userName}></FieId>
<button onClick={() =>{
console.log(this.userName.current.state.val);
}}>获取子组件val</button>
<button style={{margin:'0 10px'}} onClick={() =>{
this.userName.current.clear()
}}>清除</button>
<button onClick={() =>{
this.userName.current.serVal()
}}>set子value</button>
子组件
class FieId extends Component{
state = {
val:''
}
clear(){
this.setState({
val:''
})
}
serVal(){
this.setState({
val:'123'
})
}
render(){
return(
<div>
<input onChange={(e)=>{
this.setState({
val:e.target.value
})
}} value={this.state.val}/>
</div>
)
}
}
十、简单介绍下兄弟传参
①.父传子 -> 子传父 ->父传第二个子
父代码
export default class index extends Component {
constructor() {
super()
this.state = {
filmsList: [],
val:'初始值'
}
axios.get('http://localhost:3000/test.json').then(res => {
this.setState({
filmsList: res.data.data.films
})
})
}
render() {
return (
<div>
<h1>组件传参</h1>
{
this.state.filmsList.map(item =>
<Son {...item} key={item.filmId} onEvent={(val) =>{
this.setState({
val:val
})
}
}/>
)
}
<div className='con'><Son1 val={this.state.val}/></div>
{/* <div className='footer'><Footer></Footer></div> */}
</div>
)
}
}
第一个子组件
class Son extends Component {
render() {
return (
<div className='son1' onClick={() =>{
this.props.onEvent(this.props.synopsis)
}}>
{/* <h1 onClick={ this.get()}>子组件1</h1> */}
<img src={this.props.poster} />
{this.props.name}
</div>
)
}
}
第二个子组件
class Son1 extends Component {
render() {
return (
<div className='son2'>
<h1>{this.props.val}</h1>
</div>
)
}
}
②.使用全局订阅、发布的方案进行传参(思路很简单,在第二个子组件定义一个回调函数,通过全局的方法可以调取到第二个组件的方法,使用一个变量,然后在第一个子组件出发的时候调用回调函数即可
全局定义对象
var bus = {
method: '11233',
// 订阅
subscribe(val) {
this.method = val
},
//发布
publish(v) {
this.val = v
this.method(v)
}
}
//父组件正常渲染数据
export default class 兄弟传参02 extends Component {
constructor() {
super()
this.state = {
filmsList: []
}
axios.get('http://localhost:3000/test.json').then(res => {
this.setState({
filmsList: res.data.data.films
})
})
}
render() {
return (
<div>
{
this.state.filmsList.map(item =>
<Son {...item} key={item.filmId} />
)
}
<div className='con'>
<Son1 val={this.state.val} />
</div>
</div>
)
}
}
第一个子组件
class Son extends Component {
render() {
return (
<div className='son1' onClick={() => {
// this.props.onEvent(this.props.synopsis)
bus.publish(this.props.synopsis)
}}>
<img src={this.props.poster} alt={this.props.name} />
{this.props.name}
</div>
)
}
}
第二个子组件
class Son1 extends Component {
state = {
val: '初始化'
}
constructor() {
super()
bus.subscribe((v) => {
this.setState({
val: v
})
})
}
render() {
return (
<div className='son2'>
<h1>{this.state.val}</h1>
</div>
)
}
}
③.context状态树传参(没有子、父组件之分,通过回调函数进行传参)
最外层使用GlobalContext.Provider
组件使用GlobalContext.Consumer
const GlobalContext = React.createContext()
//最外层代码
export default class 组件传参 extends Component {
constructor() {
super()
this.state = {
filmsList: [],
val: '初始值'
}
axios.get('http://localhost:3000/test.json').then(res => {
this.setState({
filmsList: res.data.data.films
})
})
}
render() {
return (
<GlobalContext.Provider value={{
val:this.state.val,
chanSetSynopsis:(val) =>{
this.setState({val:val})
}
}}>
<div>
<h1>组件传参</h1>
{
this.state.filmsList.map(item =>
<Son {...item} key={item.filmId} />
)
}
<div className='con'><Son1 /></div>
{/* <div className='footer'><Footer></Footer></div> */}
</div>
</GlobalContext.Provider>
)
}
}
组件1
class Son extends Component {
render() {
return (
<GlobalContext.Consumer>
{
(value) =>{
return(
<div className='son1' onClick={() => {
value.chanSetSynopsis(this.props.synopsis)
}}>
<img src={this.props.poster} alt={this.props.name} />
{this.props.name}
</div>
)
}
}
</GlobalContext.Consumer>
)
}
}
组件2
class Son1 extends Component {
render() {
return (
<GlobalContext.Consumer>
{
(value) =>{
return(
<div className='son2'>
<h1>{value.val}</h1>
</div>
)
}
}
</GlobalContext.Consumer>
)
}
}
十一、插槽的使用
export default class index extends Component {
render() {
return (
<div>
<ChildComponent>
<div>111111</div>
<div>222222</div>
<div>333333</div>
</ChildComponent>
</div>
)
}
}
const ChildComponent = (props) => {
return (
<div>
{props.children}
</div>
)
}
十二、生命周期
import React, { Component } from 'react'
export default class index extends Component {
state ={
val : '初始',
type:true
}
static getDerivedStateFromProps(e,v){
console.log(e,v);
console.log('运行render之前 修改state的值');
return {
}
}
componentDidMount(){
console.log('dom挂在后 可以拿到dom元素',document.getElementsByClassName('dom'));
}
render() {
console.log('默认执行');
return (
<div className='dom'>
<button onClick={() =>{
this.setState({
val:'123',
type:!this.state.type
})
}}>更换</button>
{this.state.val}
{this.state.type && <Son title={this.state.val} />}
</div>
)
}
getSnapshotBeforeUpdate(e,v){
console.log(e,v);
console.log('更新后生命周期');
return{type:111}
}
shouldComponentUpdate(e,v){
console.log(e,v);
console.log('返回 true 页面进行 返回 false 则不更新');
return true
}
componentDidUpdate(e,v,value){
console.log(e,v);
console.log('使用setState修改值以后触发 值是修改后的值','getSnapshotBeforeUpdate返回的数据',value);
console.log(this.state.val);
}
}
class Son extends Component{
UNSAFE_componentWillReceiveProps(e,v){
console.log(e,v);
console.log('父组件更新以后会触发子组件的生命周期');
}
render(){
return (
<div>123</div>
)
}
componentWillUnmount(){
console.log('销毁生命周期');
}
}
十二、hooks的使用
(在function组件使用)
useState定义变量,修改变量方法
useEffect初始化运行,[]为空时默认执行一次
useMemo重新渲染页面事触发,[]传入,修改的数据。如:list,val分别是列表、val值
useRef 获取dom元素
useReducer设置全局变量
import React, { useEffect, useState, useMemo, useRef, useReducer } from 'react'
import React, { useEffect, useState, useMemo, useRef, useReducer } from 'react'
import axios from 'axios'
const reducer = (e, type) => {
const types = type.type
let newCount = { ...e }
if (types == '-') {
newCount.count--
return newCount
} else {
newCount.count++
return newCount
}
}
//数据可以有多个 useReducer
const intialState = {
count: 0,
}
export default function useMemo1() {
const [val, setval] = useState('')
const [list, setlist] = useState([])
const useRefData = useRef()
const [state, setState] = useReducer(reducer, intialState)
// useEffect的使用
useEffect(() => {
axios({
url: "/test.json",
method: "get",
headers: {
'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.0.4","e":"16395416565231270166529","bc":"110100"}',
'X-Host': 'mall.film-ticket.cinema.list'
}
}).then(res => {
setlist(res.data)
})
}, [])
const getList = useMemo(() => list.filter(item => item.name.toUpperCase().includes(val.toUpperCase()) ||
item.address.toUpperCase().includes(val.toUpperCase())
), [list, val])
const getRef = () => {
console.log(useRefData.current.value);
}
return (
<div>
<p> useState, useRef,的使用</p>
<input value={val} ref={useRefData} onChange={(e) => {
setval(e.target.value)
}} /> <button onClick={() => {
getRef()
}}>获取ref数据</button>
<p>useMemo的使用</p>
{
getList.map(item =>
<li key={item.cinemaId}>{item.name}</li>)
}
<p>useReducer的使用</p>
<button onClick={() => {
setState({
type: '-'
})
}}>-</button>
{state.count}
<button onClick={() => {
setState({
type: '+'
})
}
}>+</button>
</div>
)
}