props
正向传值
props能修改吗?
props是只读的 不能修改
语法:
props函数组件
语法 :
只需要在函数组件中添加一个props的形参 即可使用props
子组件接收
// 子组件需要把props当成形参传入
let Zi=(props)=>{
let {text,num}=props
return(
<div>
zizizziziziziz---{text}--{num}
</div>
)
}
export default Zi
父组件传递
import Fz from "./funpropszi.jsx"
let Fu=()=>{
let obj={text:"text数据",num:"num数据"}
return(
<div>
fufufufuffufufu
{/* 传递参数可是用扩展运算符 */}
<Fz {...obj}/>
</div>
)
}
export default Fu
props类组件
this.props.xxx
1.子组件配置props
import React, { Component } from 'react'
export default class propszi extends Component {
render() {
return (
<div>
zizizzizizizizzz---{this.props.text}
<br />
{this.props.num}
</div>
)
}
}
2.父组件传值
import React, { Component } from 'react'
import Pz from "./propszi.jsx"
export default class propsfu extends Component {
render() {
return (
<div>
fuffufufufufuffu
{/* 父组件传值 */}
<Pz text="我是父组件的text" num="我是父组件的num"/>
</div>
)
}
}
上面的写法太low了 改编一下(以后就这样写)
子组件接收数据的时候 使用解构赋值的方式取出this。props的数据
import React, { Component } from 'react'
export default class propszi extends Component {
render() {
// 由于this.props是一个对象 为了让代码看起来更加简洁 所以我们
// 使用解构赋值的方式 把props中的数据快速取出来
let {text,num}=this.props
return (
<div>
zizizizizizizziiz---{text}---{num}
</div>
)
}
}
父组件传递
import React, { Component } from 'react'
import Pz from "./propszi.jsx"
export default class propsfu extends Component {
render() {
let obj={text:"我是父组件的text",num:"我是父组件的num"}
return (
<div>
fuffufufufufuffu
{/* 父组件传值 使用扩展运算符可以简化我们在父组件给
子组件传递数据时候的复杂度
*/}
<Pz {...obj} />
</div>
)
}
}
props 验证
rccp
注意:
自 React v15.5 起,React.PropTypes
已移入另一个包中。请使用 [prop-types
库](prop-types - npm) 代替。
子组件验证,错误则会提示
// import React, { Component } from 'react'
// export default class propszi extends Component {
// render() {
// // 由于this.props是一个对象 为了让代码看起来更加简洁 所以我们
// // 使用解构赋值的方式 把props中的数据快速取出来
// let {text,num}=this.props
// return (
// <div>
// zizizizizizizziiz---{text}---{num}
// </div>
// )
// }
// }
import React, { Component } from 'react'
// 包要引
import PropTypes from 'prop-types'
export default class propszi extends Component {
// 使用PropTypes来进行props的验证
static propTypes = {
text: PropTypes.string,
num:PropTypes.number
}
render() {
let {text,num}=this.props
return (
<div>
zizizizizizizziiz---{text}---{num}
</div>
)
}
}
状态机state
状态==数据
状态机===数据机制
数据等同于状态 状态改变页面也会改变
函数组件可以使用状态吗?
函数组件默认情况下不能使用状态 后面会学到高阶语法HOOK才能使用
语法
状态创建
import React, { Component } from 'react'
export default class statedemo extends Component {
// 创建状态 需要写在constructor中
// 在es6中 子类写不写constructor 在实例的过程中 都会给补上他
// 但是如果我们写了 那么必须写super()
// super就是调用父类构造方法 只有写了子类才有自己的this
// 如果只写了constructor不写super()那么以后使用this的时候指向都是错误的
constructor(){
super()
// 创建状态
this.state={
text:"字符串",
num:18,
arr:[111,2222,33333],
obj:{name:"xxixi"}
}
}
render() {
return (
<div>
<h1>状态的使用</h1>
</div>
)
}
}
读取状态
在想使用的地方使用 this.state.xxx
import React, { Component } from 'react'
export default class statedemo extends Component {
// 创建状态 需要写在constructor中
// 在es6中 子类写不写constructor 在实例的过程中 都会给补上他
// 但是如果我们写了 那么必须写super()
// super就是调用父类构造方法 只有写了子类才有自己的this
// 如果只写了constructor不写super()那么以后使用this的时候指向都是错误的
constructor(){
super()
// 创建状态
this.state={
text:"字符串",
num:18,
arr:[111,2222,33333],
obj:{name:"xxixi"}
}
}
render() {
return (
<div>
<h1>状态的使用</h1>
{/* 使用状态 */}
<em>{this.state.num}-----{this.state.text}---{this.state.arr[1]}</em>
</div>
)
}
}
修改state
修改state不能直接使用=修改 而是要调用一个叫 setState()来进行修改
import React, { Component } from 'react'
export default class statedemo extends Component {
// 创建状态 需要写在constructor中
// 在es6中 子类写不写constructor 在实例的过程中 都会给补上他
// 但是如果我们写了 那么必须写super()
// super就是调用父类构造方法 只有写了子类才有自己的this
// 如果只写了constructor不写super()那么以后使用this的时候指向都是错误的
constructor(){
super()
// 创建状态
this.state={
text:"字符串",
num:18,
arr:[111,2222,33333],
obj:{name:"xxixi"}
}
}
// 创建函数
fun=()=>{
// 修改state数据必须使用setState()
this.setState({
num:888,
text:"我变了"
})
}
render() {
return (
<div>
<h1>状态的使用</h1>
{/* 使用状态 */}
<em>{this.state.num}-----{this.state.text}---{this.state.arr[1]}</em>
<button onClick={this.fun}>点我修改</button>
</div>
)
}
}
为什么要使用setState()来修改state
因为调用了setState之后 他会自动触发render方法重新渲染页面 从而让数据改变之后 页面也会发生改变
setState 在修改数据的时候是异步的
由于setState是一个异步的 所以他第一个参数是一个对象 用来修改数据 第二个参数是一个回调函数 是当修改完数据之后自动触发回调函数
this.setState({
num:888,
text:"我变了"
},()=>{
// 我就是想等数据修改之后在console中打印出来
console.log(this.state.num);
})
ref
用来标识组件内部的元素 但是注意 函数组件由于没有实例所以不能使用ref
使用
1.字符串方式(已经淘汰了)
2.回调函数方式
import React, { Component } from 'react'
export default class refdemo extends Component {
fun=()=>{
console.log(this.refinput.value);
}
render() {
return (
<div>
<h1>ref回调函数的方式</h1>
{/* 回调函数方式绑定ref 需要在dom节点上挂载一个函数
函数的形参是当前dom节点 (形参)=>{随便创建一个变量=形参}*/}
<input type="text" ref={(demoinput)=>{this.refinput=demoinput}}/>
<button onClick={this.fun}>点我得到值</button>
</div>
)
}
}
3.React.createRef() react16.3新增
import React, { Component } from 'react'
export default class refdemob extends Component {
constructor(){
super()
// 1.创建createRef
this.refdemo=React.createRef()
}
fun=()=>{
// 3.使用
console.log(this.refdemo.current.value);
}
render() {
return (
<div>
<h1>createRef()</h1>
{/* 2.绑定 */}
<input type="text" ref={this.refdemo}/>
<button onClick={this.fun}>点我得到值</button>
</div>
)
}
}
事件处理机制
事件的绑定
使用小驼峰命名法来进行事件的绑定 onclick----->onClick
如果事件要调用 那么函数是不加()
函数实参传递
由于react中函数是没有()的,所以传统的实参传参方式是没有办法进行的
.bind方式进行实参的传递
onClick={this.fun.bind(this,你要传递的数据)}
使用箭头函数调用函数传参
{/* 通过箭头函数调用函数传参 */}
<button onClick={()=>{this.funb("参数")}}>点我传参2</button>
事件的修饰
react中如果想阻止事件传播或者默认行为的话 使用同原生一样的方式
this指向修改的方法:
1.就是创建函数的时候使用箭头函数创建
2.通过.bind方式解决this
<button onClick={this.funb.bind(this)}>bind修改this</button>
3.把函数的调用变成使用箭头函数调用
<button onClick={()=>{this.funb()}}>箭头函数调用函数</button>
4.在constructor中提前绑定
constructor(){
super()
this.state={
text:"你好"
}
// 提前给函数绑定this
this.funb=this.funb.bind(this)
}
条件渲染
根据我们的需要 显示或者隐藏某些内容
1.三元运算符
import React, { Component } from 'react'
export default class democ extends Component {
constructor(){
super()
this.state={
bool:true
}
}
render() {
return (
<div>
<h1>条件渲染</h1>
{this.state.bool?<h1>吃了</h1>:<h1>没有吃</h1>}
</div>
)
}
}
2.if全家桶
注意注意注意:在jsx不能写if
import React, { Component } from 'react'
export default class demod extends Component {
constructor(){
super()
this.state={
num:5
}
}
render() {
let com=""
if(this.state.num==1){
com= <h1>第1</h1>
}else if(this.state.num==2){
com= <h1>第2</h1>
}else if(this.state.num==3){
com= <h1>第3</h1>
}else if(this.state.num==4){
com= <h1>第4</h1>
}else if(this.state.num==5){
com= <h1>第5</h1>
}
return (
<div>
<h1>条件渲染</h1>
{com}
</div>
)
}
}
状态提升
react中状态提升就是多个组件需要反映相同的数据变化 我们可以把这个数据提升到这几个组件的父组件之上 然后在父组件中改变数据 那么通过props分发给这几个子组件即可反映相同的数据变化
扩展----多行标签-空标签
在react中 多行标签必须有一个父容器包裹 但是往往这些包裹的容器标签是没有用 在页面渲染的时候 会造成冗余代码
1.真正的空标签
import React, { Component } from 'react'
export default class ezia extends Component {
render() {
return (
// 空标签
<>
<h1>我是h1</h1>
<h1>我是h11</h1>
</>
)
}
}
2.Fragment 空标签 今后会使用的比较多
import React, { Component,Fragment } from 'react'
export default class ezi extends Component {
render() {
return (
// Fragment空标签 别忘了引用
<Fragment>
<h2>h222222</h2>
<h2>h222222222222222</h2>
</Fragment>
)
}
}
扩展----强制刷新
react 只有使用state创建的变量 在使用setState修改之后页面才会更新。
如果我就是不想在state里面写状态 也不想使用setState修改 我怎么样创建变量修改更新呢?
import React, { Component } from 'react'
export default class demof extends Component {
constructor(){
super()
this.name="xixi"
}
fun=()=>{
this.name="haha"
console.log(this.name);
// 强制触发render()渲染
// 只要调用就会重新渲染
this.forceUpdate()
}
render() {
return (
<div>
<h1>页面强制刷新---{this.name}</h1>
<button onClick={()=>{this.fun()}}>点我修改</button>
</div>
)
}
}
组件传值
正向传值--props
详见上面内容
逆向传值
react的逆向传值 使用的也是props 只是和正向传值不同 因为正向传值传递的是数据 但是逆向传值传递的是方法
子组件
import React, { Component } from 'react'
export default class nizi extends Component {
render() {
return (
<div>
<h1>子组件</h1>
{/* 1.子组件必须通过事件来触发逆向传值 */}
{/* 2.子组件需要接收父组件传递过来的函数 并且使用bind进行函数实参传递 */}
<button onClick={this.props.fun.bind(this,"子组件的数据")}>点我逆向传值</button>
</div>
)
}
}
父组件
import React, { Component } from 'react'
import Nz from "./nizi.jsx"
export default class nifu extends Component {
// 4.创建父组件的函数
demo=(text)=>{
console.log(text);
}
render() {
return (
<div>
<h1>逆向传值</h1>
{/* 3.子组件需要一个函数 那么父组件给他传递一个函数 */}
<Nz fun={this.demo}/>
</div>
)
}
}
同胞传值---pubsub-js
1.下载pubsub-js npm install --save pubsub-js
2.在需要传递的组件中进行数据的抛出(使用自定义事件)publish("自定义事件名","传递的参数")
import React, { Component,Fragment } from 'react'
// 1.引用pubsub-js
import PubSub from "pubsub-js"
export default class pubsubzia extends Component {
fun=()=>{
// 2.抛出自定事件
PubSub.publish("pao","我是zia的数据么么哒!!!")
}
render() {
return (
<Fragment>
<h1>zia</h1>
<button onClick={this.fun}>点我同胞传值</button>
</Fragment>
)
}
}
3.在需要数据的组件内 监听自定义事件 subscribe("你要监听的事件名",(事件,数据)=>{})
import React, { Component } from 'react'
import PubSub from "pubsub-js"
export default class pubsubzib extends Component {
// 3使用生命周期自动调用subscribe()来监听自定事件
// 组件渲染之前
componentWillMount() {
PubSub.subscribe("pao",(a,b)=>{
console.log(a);//监听的事件名
console.log(b);//监听的数据
})
}
// 组件渲染之后
componentDidMount() {
}
render() {
return (
<>
<h1>zib</h1>
</>
)
}
}
跨组件传值
方式1 context上下文对象
方式2 redux