React脚手架+组件化开发+组件生命周期+组件通信

news/2024/10/30 15:22:45/

react脚手架(create-react-app)

1.作用: 帮助我们生成一个通用的目录结构,并且已经将我们所需的工程环境配置好
2.依赖环境
脚手架都是使用node编写的,并且都是基于webpack的;
3.安装node
4.安装脚手架

npm install -g create-react-app

5.检查脚手架版本

create-react-app --version

创建项目

create-react-app 项目名称

跑项目

yarn start

目录
在这里插入图片描述

React组件化开发

类组件
定义:

  • 组件的名称是大写字符开头的(无论类组件还是函数组件)
  • 类组件需要继承自React.Component
  • 类组件必须实现render函数

使用class定义一个组件:
constructor是可选的,我们通常在constructor中初始化一些数据
this.state中维护的就是我们组件内部的数据
render()方法是class组件中

函数式组件

/*** * 函数式组件的特点:* 1.没有this对象* 2.没有内部的状态* 3.没有生命周期* */
export default function App(){return (<div>我是function组件</div>)
}

类组件

import React, { Component } from "react";export default class App extends Component {constructor() {super();this.state = {message: 'hello'}}render () {return (<div><div>app组件</div>{/* alt+shift+f  代码格式化*/}<h2>{this.state.message}</h2></div>)}
}

render函数的返回值

  • React元素:通常通过JSX创建
  • 数组或fragments
  • portals:可以渲染子节点到不同的DOM子树中
  • 字符串或数值类型
  • 布尔类型或null:什么都不渲染

生命周期

很多事物从创建到销毁的整个过程,这个过程称之为生命周期。

constructor
如果不初始化state或不进行方法绑定,则不需要为React组件实现构造函数。
constructor中通常只做两件事情:

  • 通过给this.state赋值对象来初始化内部的state
  • 为事件绑定实例(this)

componentDidMount
componentDidMount()会在组件挂在后(插入DOM树中)立即调用
操作:

  • 依赖于DOM的操作可以在这里进行
  • 在此处发送网络请求就最好的地方(官方建议)
  • 可以在此处添加一些订阅(会在componentWillUnmount取消订阅)

componentDidUpdate
componentDidUpdate()会在更新后会被立即调用,首次渲染不会执行此方法。
当组件更新后,可以在此处对DOM进行操作。
如果你对更新前后的props进行了比较,也可以选择在此处进行网络请求;(例如,当props未发生变化时,则不会执行网络请求)

componentWillUnmount
componentWillUnmount() 会在组件卸载及销毁之前直接调用。
在此方法中执行必要的清理操作;
例如:清除timer,取消网络请求或清楚
在componentDidMount()中创建的订阅等;

import React, { Component } from 'react'class Cpn extends Component {render () {return <h2>我是cpn组件</h2>}componentWillUnmount () {console.log('我调用了componentWillUnmount')}
}export default class App extends Component {constructor() {super();this.state = {count: 1,isShow: true}console.log('执行了组件的constructor')}render () {console.log('执行了组件的render函数')return (<div>我是App组件<h2>当前计数:{this.state.count}</h2><button onClick={e => { this.increment() }}>+1</button><hr /><button onClick={e => { this.changeShow() }}>切换</button>{this.state.isShow && <Cpn />}</div>)}increment () {this.setState({counter: this.state.counter + 1})}changeShow () {this.setState({isShow: !this.state.isShow})}componentDidMount () {console.log('执行了componentDidMount方法')}componentDidUpdate (previProps,preState,snapshot) {console.log('执行了componentDidUpdate方法')}
}

组件通信

父->子 props
子->父 itemOnclock

1.父传子-类组件

import React, { Component } from 'react'class ChilCpn extends Component{// constructor(props){//   super(props);// }render(){const {name,age,height} = this.propsreturn(<h2>子组件展示数据:{name+' '+age+' '+height}</h2>)}
}export default class App extends Component {render() {return (<div><ChilCpn name='guo' age='18' height='1.55'/></div>)}
}

2.父传子-函数组件-- 参数验证
效果:
在这里插入图片描述

import React, { Component } from 'react'import PropTypes from 'prop-types'function ChildCpn(props){const {name,age,height} = propsconst {names} = propsreturn (<div><h2>{name+' '+ age+' '+height}</h2>{/*参数验证 */}<ul>{names.map((item,index)=>{return <li>{item}</li>})}</ul></div>)
}
ChildCpn.propTypes = {name:PropTypes.string.isRequired, // 必传age:PropTypes.number,height:PropTypes.number,names:PropTypes.array
}// 默认值
ChildCpn.defaultProps = {name:'wen',age:20,height:1.75,names:['111']
}export default class App extends Component {render() {return (<div><ChildCpn name='guo' age={18} height={1.55} names={['abc','mab']}/><ChildCpn/></div>)}
}

类组件的参数校验

class ChildCpn extends Component{// es6中class fields写法static propTypes = {}static defaultProps = {}
}

3.子组件传递父组件

import React, { Component } from 'react'class CounterButton extends Component{render(){const {onClick} = this.props;return <button onClick= {onClick}>+1</button>}
}export default class App extends Component {constructor(props){super(props);this.state = {counter:0}}render() {return (<div><h2>当前计数{this.state.counter}</h2><button onClick= {e=>this.increment()}>+</button><CounterButton onClick={this.increment.bind(this)} /><CounterButton onClick={e=>this.increment()} /></div>)}increment(){this.setState({counter:this.state.counter + 1})}
}

4.组件通信案例-选项卡
APP.js

import React, { Component } from 'react'import TabControl from "./TabControl"export default class App extends Component {constructor(props){super(props);this.titles = ['精选','流行','新款']this.state = {currentTitle:'精选'}}render() {const {currentTitle} = this.statereturn (<div><TabControl itemClick={index=>this.itemClick(index)} titles={this.titles}/><h2>{currentTitle}</h2></div>)}itemClick(index){console.log(index)this.setState({currentTitle:this.titles[index]})}
}

tabcontrol.js

import React, { Component } from 'react'
import PropTypes from 'prop-types'export default class TabControl extends Component {constructor() {super()this.state = {currentIndex: 1}}render () {const { titles } = this.props;const { currentIndex } = this.statereturn (<div className="tab-control">{titles.map((item, index) => {return (<div key={index}className={'tab-item ' + (index === currentIndex ? 'active' : '')}onClick={e => this.itemClick(index)}><span>{item}</span></div>)})}</div>)}itemClick (index) {this.setState({currentIndex: index})const {itemClick} = this.propsitemClick(index)}
}
TabControl.propTypes = {titles: PropTypes.array.isRequired
}

5.类似插槽
效果
在这里插入图片描述
App.js

import React, { Component } from 'react'import NavBar from './NavBar'
export default class App extends Component {render() {return (<div><NavBar leftSlot={<span>aaa123</span>}centerSlot= {<strong>bbb</strong>}rightSlot= {<span>123</span>}/></div>)}
}

NavBar.js

import React, { Component } from 'react'export default class NavBar extends Component {render () {const {leftSlot,centerSlot,rightSlot} = this.props;return (<div className="nav-bar"><div className="nav-left">{leftSlot}</div><div className="nav-center">{centerSlot}</div><div className="nav-right">{rightSlot}</div></div>)}
}

6.跨组件通信-古老一层一层传递
anli.js

import React, { Component } from 'react'function ProfileHeader(props){return(<div><h2>用户昵称1{props.nickname}</h2><h2>粉丝等级:{props.level}</h2></div>)
}function Profile(props){return(<div>{/* <ProfileHeader nickname={props.nickname} level= {props.level}></ProfileHeader> */}{/* 属性展开 */}<ProfileHeader {...props}/><ul><li>设置1</li><li>设置2</li><li>设置3</li><li>设置4</li></ul></div>)
}export default class anli extends Component {constructor(props){super(props);this.state = {nickname:'ming',level:9}}render() {// const {nickname,level} = this.statereturn (<div>{/* <Profile nickname= {nickname} level={level}></Profile> */}<Profile {...this.state}></Profile></div>)}
}

6.跨组件通信-context
React.createContext
创建一个需要共享的Context对象:
如果一个组件订阅了Context,那么这个组件会从离自身最近的那个匹配的Provider中读取当前的context值;
defaultValue是组件在顶层查找过程中没有找到对应的Provider,那么久使用默认值

const MyContext = React.createContext(defaultValue);

Context.Provider
每个Context对象都会返回一个Provider React组件,它允许消费组件订阅Context的变化:
Provider接收一个value属性,传递给消费组件;
一个Provider可以和多个消费组件有对应关系
多个Provider也可以嵌套使用,里层的会覆盖外层的数据;
当Provider的value值发生变化时,它内部的所有消费组件都会重新渲染;

Class.contextType
挂载在class上的contextType属性会被重赋值为一个由React.createContext()创建的Context对象;
这能让你使用this.context来消费最近Context上的那个值;
你可以在任何生命周期中访问到它,包括render函数中

效果:
在这里插入图片描述
anli.js

import React, { Component } from 'react'//1.创建Context对象
const UserContext = React.createContext({nickname: 'lan',level: 3
})class ProfileHeader extends Component {render () {console.log(this.context)return (<div><h2>用户昵称:{this.context.nickname}</h2><h2>粉丝等级:{this.context.level}</h2></div>)}
}
ProfileHeader.contextType = UserContextfunction Profile (props) {return (<div><ProfileHeader></ProfileHeader><ul><li>设置1</li><li>设置2</li><li>设置3</li><li>设置4</li></ul></div>)
}export default class anli extends Component {constructor(props) {super(props);this.state = {nickname: 'ming',level: 9}}render () {return (<div>{/* 第二步 */}<UserContext.Provider value={this.state}><Profile /></UserContext.Provider></div>)}
}

函数用法-其余代码参考上面代码

function ProfileHeader () {return (<UserContext.Consumer>{value => {return (<div><h2>用户昵称:{value.nickname}</h2><h2>粉丝等级:{value.level}</h2></div>)}}</UserContext.Consumer>)
}

http://www.ppmy.cn/news/12756.html

相关文章

【web安全】——HTTP请求头注入

作者名&#xff1a;Demo不是emo主页面链接&#xff1a; 主页传送门创作初心&#xff1a; 舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座右…

【墙角数枝梅,凌寒独自开】代码改变未来

墙角数枝梅&#xff0c;凌寒独自开 “墙角数枝梅&#xff0c;凌寒独自开。” 出自王安石的《梅花》 诗句是集语言中的精华&#xff0c;浓缩为七言、五言和四言等&#xff0c;寥寥几句道尽人生酸甜苦辣&#xff0c;儿女情长。 而我更愿把现代的程序员称作诗人&#xff0c;语言是…

《Linux Shell脚本攻略》学习笔记-第十二章

12.1 简介 我们可以通过关闭无用的服务、调整内核参数或是添加新的硬件来改善系统性能。 12.2 识别服务 Linux系统可以同时运行数百个任务&#xff0c;其中可能也会有那么一两个你不需要的守护进程。 有三种可以用于启动守护进程和服务的工具&#xff0c;Linux发行版支持其中任…

亚马逊云科技 Build On - 毫厘控制传统行业快速搭建部署智能业务这件事“钱花在刀刃上”——迎云计算更高一层精专形态的下一个时代Serverless

/*本文章总计6052词&#xff0c;可能需要16分钟进行阅读&#xff0c;创作时间近1周&#xff0c;尽量将Serverless干货打包满满&#xff0c;并尝试向您解释清楚。 无论是路过还是看得乐呵的看官姥爷只求能给个&#x1f44d;点赞和⭐收藏&#xff0c;谢谢您嘞❤ P.S.CSDN侧边可以…

Rancher 2022 关键主题与新年展望

作者简介 张智博&#xff0c;SUSE Rancher 大中华区研发总监&#xff0c;一直活跃在研发一线&#xff0c;经历了 OpenStack 到 Kubernetes 的技术变革&#xff0c;在底层操作系统 Linux、虚拟化 KVM 和 Docker 容器技术领域都有丰富的研发和实践经验。 以 Rancher 为核心的 SUS…

c++11 标准模板(STL)(std::forward_list)(十)

定义于头文件 <forward_list> template< class T, class Allocator std::allocator<T> > class forward_list;(1)(C11 起)namespace pmr { template <class T> using forward_list std::forward_list<T, std::pmr::polymorphic_…

机器学习的相关概念与建模流程

文章目录一、机器学习简介1. 机器学习的相关定义2. 一次简单的机器学习任务&#xff1a;鸢尾花分类二、数据与数据集相关概念1. 数据与数据集2. 特征与标签3. 连续变量和离散变量4. 模型类型三、机器学习建模一般流程1. 提出基本模型2. 确定损失函数3. 根据损失函数性质&#x…

来看看我在CSDN上的好朋友们吧,看看有没有你

首先&#xff0c;感谢支持我的所有人&#xff0c;其次&#xff0c;感谢支持我的所有人&#xff0c;然后感谢支持我的所有人&#xff0c;最后&#xff0c;感谢支持我的所有人&#xff08;我这是废话吗&#xff1f;&#xff1f;&#xff1f;不是吧&#xff09; 今天就来看看我在…