第一种:属性传递方法(单向数据流的)
父亲把属性传递给儿子,或者是后代.(儿子是传不了父亲的),但是父亲组件把自身的方法通过属性传递给子组件,子组件不仅能接受这个方法,还能执行这个方法.这样就能达到子组件执行方法的时候把一些属性传递给父组件,并修改父组件中的一些信息.在react中属性传递方法类似于Jsonp,类似于hybride H5和原生App 的交互方式中的场景,能实现子改父.但是这仅仅局限于父子关系.如果是爷孙关系,还得把属性传递给儿子,再传递给孙子(如果关系层级更多,还得一层层的去传递,这样写起来比较麻烦).
第二种:发布订阅的方式
应用第三方库,或者是自己写一个发布订阅模式的代码
第三种:执行上下文
在组件元素当中,为了快速,方便的写可以用react中context这个API,在祖先元素当中,我们首先用react.Createcontext创建一个context,在他的祖先元素当中通过执行上下文中那个对象中的Provider组件,把后代元素要使用的上下文通过value的方式注册下来,那么后代可以用Consumer或contextType来进行消费.
好处:执行上下文有一个好处,只要他们有一个共同的祖先,都可以调用祖先上的信息),属性的特点:只要是父子的,哪怕是兄弟,他俩只要有一个共同的爹,都是可以用属性的方式.
缺点;执行上下文虽然解决了兄弟组件之间的传递但是他的缺点是要把所有的信息都写在祖先组件上,而且,我们想要信息改变的时候,要把祖先中某个方法放到上下文当中,由后代去执行这个方法,执行的方法还是祖先的方法,而祖先方法里边通过修改状态让祖先重新渲染,才能保证后代元素重新渲染,所以祖先的业务逻辑随着项目的不断增大会越来越多,这样也不是特别好.
import React from "react";
import PropTypes from "prop-types";
import "./Vote.css";
export default class Vote extends React.Component {
//设置属性的规则
static defaultProps = {
supNum: 0,
oppNum: 0
}
static propTypes = {
title: PropTypes.string.isRequired,
supNum: PropTypes.number,
oppNum: PropTypes.number
}
//设置初始值
constructor(props) {
super(props)
this.state = {
//把传进来的属性复制给了状态,好处是 状态可以在组件中修改,属性不能
supNum: this.props.supNum,
oppNum: this.props.oppNum
}
}
render() {
let { supNum, oppNum } = this.state;
return <div className="voteBox">
<header className="headerBox">
<h3>{this.props.title}</h3>
<span>N:{supNum + oppNum}</span>
</header>
<main>
<p>支持人数:{supNum}</p>
<p>反对人数:{oppNum}</p>
<p>支持率:{this.getRatio()}</p>
</main>
<footer className="footerBox">
<button onClick={this.handle.bind(this,"A")}>支持</button>
<button onClick={this.handle.bind(this,"B")}> 反对</button>
<button onClick={this.text}>测试ev</button>
</footer>
</div>
}
//=>定义一些需要使用的方法(vote.prototype) :vue中的写法,方法中的this都是vue的实例,不管怎么调用都是这样,但是react中不是,他就是我们原生js中的特性,this是不固定的,看你怎么调用来决定
//=>为了保证this是实例,我们写的方法一般基于箭头来构建
getRatio=()=> {
// this是实例了
let {supNum,oppNum} = this.state,
ratio=null,
total =supNum+oppNum;
ratio =total===0? 0:supNum/total*100;
return ratio.toFixed(2)+"%";
}
handle=(type,ev)=>{
console.log(ev)
console.log(type)
let {supNum,oppNum} = this.state
if(type==="A"){
this.setState({
supNum:supNum+1
})
return ;
}else if(type==="B"){
this.setState({
oppNum:oppNum+1
})
return
}else{
return
}
}
// text(){
// console.log(this) //这么写 this不是当前类的实例
// }
//一般用箭头函数让 this指向实例
text=ev=>{
//=>ev不是我们原生js的事件对象(经过react处理的,把每一个属性都getter和setter了),但是用的时候和原生用法一致即可
// console.log(ev.currentTarget)
ev.persist();
console.log(ev)
//ev.currentTarget能知道当前元素 输出 <button>测试ev</button>
console.log(ev.currentTarget)
}
}