2022-03-16 React基础

第一个React程序

函数式组件

//引入react核心
import React from 'react'
//引入react对dom操作的核心,相对于react-native而言的
import ReactDOM from 'react-dom'
//定义一个函数式组件
const app=(props)=><h1>还原进入{props.name}的世界</h1>
//点用渲染方法
ReactDOM.render(
<App name="react" />, //第一个参数为el组件
document.getElementById('root') // 第二个参数为dom根节点
)

class组件

//引入react核心
import React from 'react'
//引入react对dom操作的核心,相对于react-native而言的
import ReactDOM from 'react-dom'
//定义一个class组件
class App extends React.Component {
render(){
return(
        <h1>还原进入{this.props.name}的世界</h1>
)
}
}
//点用渲染方法
ReactDOM.render(
<App name="react" />, //第一个参数为el组件
document.getElementById('root') // 第二个参数为dom根节点
)

组件的组合和嵌套

将一个组件渲染到另一个组件内部构成父子组件关系

注:react组件不存在vue那样的slot内容分发机制

//引入react核心
import React,{Component,Fragment } from 'react'
//引入react对dom操作的核心,相对于react-native而言的
import ReactDOM from 'react-dom'
class Title extends Component {
render(){
return(
<h1>还原进入{this.props.name}的世界</h1>
)
}
}
class Content extends Component {
render(){
return(
<p>{this.props.name}是世界上最好的框架(vue听到想打人)</p>
)
}
}
//定义一个class组件
class App extends Component {
render(){
return(
        <Fragment>  //类似vue的template节点
<Title name='react'/>
<Content name='react'/>
  </Fragment> 
)
}
}
//点用渲染方法
ReactDOM.render(
<App name="react" />, //第一个参数为el组件
document.getElementById('root') // 第二个参数为dom根节点
)

JSX原理

将js和html融合在一起的一种写法,浏览器无法直接识别,最终需要编译成js语言

**行内样式
//这里有两个大括号,第一个大括号表示需要在JSX中插入JS,第二个括号是用对象的形//式表达样式
<p style={{color:'red',fontSize:'14px'}}>Hello World</p>

**class
<p class='hello'>Hello World</p>
使用classNames包
npm install classnames

class Button extends React.Component {
  // ...
  render () {
    var btnClass = 'btn';
    if (this.state.isPressed) btnClass += ' btn-pressed';
    else if (this.state.isHovered) btnClass += ' btn-over';
    return <button className={btnClass}>{this.props.label}</button>;
  }
}

组件的数据挂载

props (属性)

props是属性的意思,用来描述当前组件的特征,一般用于外界传入,如函数式组件的参数传入,或者class组件的构造函数传入。一般不能在内部更改。

**设置组件的默认props
class组件===》在class内部使用静态属性 static defaultProps = {name:'react'}
函数式组件===》挂载在函数上的属性(非原型属性)func.defaultProps={name:'react'}

**props.children
props.children相当于一个嵌套内容的占位符,运训在组件标签之间嵌套内容

const App = (props) = >{
return(
<p>{props.children}</p>
)
}

state(状态)

状态是组件内部使用的数据,组件自己维护

class App extends Component{
constructor(){
super()
//定义state
this.state = {
name:'react',
isLink;false
}
}

handleClick=()=>{
//不能直接给state赋值,因为没有被跟踪,必须使用setState进行响应式绑定
this.setState({
isLink:!this.state.isLink
})
}

render(){
return(
<div>
<h1>hello to {this.state.name} world</h1>
<button onClick={this.handleClick}>
{this.state.isLink?'取消':'收藏'}
</<button>>
</div>
)
}
}

完整的setState方法,第一个函数的参数中可以拿到当前state和props
this.setState((prevState,props)=>{
return {
isLink:!prevState.isLink
}
},()=>{
//这个回调可以获取最新的state值
})

渲染数据

**条件渲染

{
condition?‘取消’:‘收藏’
}

**列表渲染

const people = [
{
id:1,
name:'a'},
{
id:2,
name:'b'},
{
id:3,
name:'c'},
]

people.map((item)=>{
return(
<span>id:{item.id}</span>
<div>name:{item.name}</div>
)
})

dangerrouslySetHTML(富文本)

content='<p>xxxx</p>'
render(){
    return(
<div dangerouslySetHTML={{__html:this.state.content}}></div>
)
}

事件处理

绑定事件

采用on+事件名的方式来绑定一个事件,注意,这里和原生的事件是有区别的,原生的事件全是小写onclick, React里的事件是驼峰onClick,React的事件并不是原生事件,而是合成事件。

**handler的写法:
在组件内使用箭头函数定义一个方法(推荐)

handleInputChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}

render(){
<input
type="text"
name="xing"
value={xing}
onChange={this.handleInputChange}
/>
}

组件的生命周期

初始化

1,constructor(props)

constructor(props){
//用来绑定props,后面就可以用this.props调用
super(props)
//可初始化state,构造函数中不要使用setState()更新状态
this.state={
    //可用props初始化内容
    name:props.name
}
}

2,static getDerivedStateFromProps(nextProps,prevState)
组件实例化之后,父组件传递新的props的时候会触发
3,componentWillMount()
在render前调用,不建议使用
4,render()
当render方法被调用后,其返回一个可供后续渲染成真正DOM的类型
5,componentDidMount()
当组件真正被渲染成真实DOM后触发,此处才可以进行DOM操作,如加载第三方DOM库或者手动更改DOM等

更新

1,componentWillRecevieProps()
在挂载后,如果props有改变,则会触发
官方推荐getDerivedStateFromProps
2,static getDerivedStateFromProps()
同上
3,shouldComponentUpdate(nextProps, nextState)
可以获取将变更的参数
如果返回false,则4,5,6不会被触发
4,componentWillUpdate()
render前调用,不推荐
5,render()
同上
6,getSnapshotBeforeUpdate()
在render输出但为最终渲染前调用
能够获取DOM的当前状态,如滚动条更新前的高度
这个勾子返回的任何值都将传递给componentDidUpdate()
7,compontentDidUpdate(prevProps,prevState,snapshot)

销毁

1,componentWillUnmount()
组件销毁前触发,可执行一些必要的清理工作,比如定时器,事件等

错误处理

1,compontentDidCatch(error,info)
在整个生命周期中可以捕获js错误

ref

ref属性同vue,可以直接用其引用组件的实例
ref只能通过class声明和添加,因为函数式组件没有实例

import React,{Component,createRef} from 'react'
class App extends Component{
constructor(){
super()
//创建ref标识
this.inputRef=createRef
}
componentDidMount(){
console.log(this.inputRef)
}
render(){
return(
<input type='text' ref={this.inputRef}>
)
}
}

React Hooks

hooks使得在函数式组件中,也能运用像class组件一样的state和生命周期的特性

State Hook

//useState是react包提供的一个方法
import React,{useState} from 'react'
const Counter=()=>{
   const [count,setCount] = useState(0);
   return(
    <p>点击{count}次</p>
    <button onClick={()=>setCount(count + 1)}>点击</button>
   )
}

Effect Hook

import React, { useEffect, useState } from 'react'
const Test = () => {
  let [count, setCount] = useState(0)
  useEffect(() => {
    setTimeout(() => {
      setCount(count + 1)
    }, 1000)
  })
  return (
    <p>自增{count}次</p>
  )
}

**React Hooks 的规则
1,只能在函数的顶层调用
2,不要在循环,条件,嵌套中调用

**内置hooks api
基础 Hook
//类似class的状态
useState
//类似class的didMount和didUpdate,但是不同的是,会在浏览器绘制完dom之后
useEffect
//类似vue的inject方式从祖先节点传递数据
useContext

额外的 Hook
//类似vuex的redux实现,用于状态管理
useReducer
//
useCallback
useMemo
useRef
useImperativeHandle
useLayoutEffect
useDebugValue

组件通信

1,父组件向子组件通信
父组件将自己的状态通过props传递
父组件通过ref标记拿到子组件,调用子组件相关方法变更子组件状态
2,子组件向父组件通信
父组件将整个自己通过props传递给子组件,子组件可以通过调用父组件事先写好的方法变更状态
3,隔代通信
使用context
4,全局通信
使用redux

HOC(高阶组件)

Higher-Order Components 是一个函数,可接受一个以组件形式的参数并返回一个新组件

const NewComponent = higherOrderComponent(prevComponent)

比如我们想要一个版权注入

const withCopyRight = (wrapperComponent) =>{
return class NewComponent extends Component{
render(){
<Fragment>
<wrapperComponent />
<div>copyright info xxx</div>
</Fragment>
}
}
}

使用

const copyRightApp=withCopyRight(App)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容

  • 生命周期 旧 初始化阶段 由React.render 触发 -- 初次渲染 constructor() 构造函数...
    命题_1f6e阅读 263评论 0 0
  • 本文目录: 1.React入口 2.JSX语法 3.组件 4.正确使用setState 5.生命周期 6.组件复合...
    前端辉羽阅读 1,385评论 0 20
  • 简介 设计理念单向数据流、虚拟 DOM、组件化 组件化编程的思想React 以组件的方式去重新思考用户界面的构成,...
    欢欣的膜笛阅读 1,245评论 0 2
  • 最近在学习React,并使用React做了一个cnode(欢迎大家给我star、issue,一起学习讨论进步),现...
    tiancai啊呆阅读 690评论 0 6
  • React基础 React 简介 2013年由Facebook推出且开源 函数式编程代码主要是函数构成,有利于前端...
    ChuckieWIll阅读 257评论 0 0