React---基础4(组件通讯)

1.父传子

通过属性props传递:组件可以接受任意的 props(属性) ,包括原始值、React 元素,或者函数

2.子传父(不共用状态,各自管理各自的状态)

2.1 react导入库

npm install pubsub-js --save

2.2 react 页面引入pubsubjs

import PubSub from 'pubsub-js'

2.3 pubsubjs使用

发送消息:PubSub.publish(名称,参数)

订阅消息:PubSub.subscrib(名称,函数)

取消订阅:PubSub.unsubscrib(名称)

PS:pubsubjs源码及使用详情https://github.com/mroderick/PubSubJS

feater.js

import React from 'react';
import PubSub from 'pubsub-js';
import Child from './child';

class Feater extends React.Component {
    constructor(props) {
        super(props);
        this.state = {name:'',age:''}
    }
    componentDidMount() {
        // 订阅消息
        this.pubsub_token = PubSub.subscribe('PubSubMsg', (topic, msg) => {
            this.setState({
                name:msg.name,
                age:msg.age,
                sex:msg.sex
            })
        })
    }
    componentWillUnmount() {
        // 取消订阅
        PubSub.unsubscribe(this.pubsub_token)
    }
    render() {
        let props = {
            name: 'muzidigbig',
            age: 22
        }
        return (
            <div>
                <hr></hr>
                <h2>使用pubsub事件订阅,组件间通信</h2>
                {/* ...属性扩展 */}
                <Child {...props}></Child>
                {this.state.name ? (<p>孩子传过来的值:{this.state.name}---{this.state.age}{this.state.sex ? <span>---{this.state.sex}</span> : ''}</p>) : ''}
            </div>
        )
    }
}
export default Feater;

child.js

import React from 'react';
import PubSub from 'pubsub-js';

class Child extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
    }
    componentDidMount() {
        this.setState({
            name: this.props.name,
            age: this.props.age
        })
    }
    changeProps() {
        this.setState({
            name: "小红",
            age: "21",
            sex: "女"
        })
    }
    sendMsg() {
        // 发送消息
        PubSub.publish('PubSubMsg', this.state);
    }
    render() {
        return (
            <div>
                <button type='button' className='my-marginR20' onClick={(e) => this.changeProps()}>更改父传来的值</button>
                <button type='button' className='my-marginR20' onClick={(e) => this.sendMsg()}>发送消息给feater</button>
                <p>得到父亲传过来的值:{this.state.name}---{this.state.age}{this.state.sex ? <span>---{this.state.sex}</span> : ''}</p>
            </div>
        )
    }
}
export default Child;

3.状态提升(子公用父的状态)

通常情况下,同一个数据的变化需要几个不同的组件来反映。我们建议提升共享的状态到它们最近的祖先组件中

feater.js

import React from 'react';
import TemperatureInput from './TemperatureInput';
import BiolingVerdict from './BoilingVerdict';

class Calculator extends React.Component {
    constructor() {
        super();
        this.state = {
            temperature: '',
            scale: 'c'
        }
    }
    /** 
     * 摄氏度和华氏度之间转换
     * temperature: input值
     * convert: 单位
    */
    tryConvert(temperature, convert) {
        const input = parseFloat(temperature);
        if (Number.isNaN(input)) {
            return '';
        }
        const output = convert(input);
        const rounded = Math.round(output * 1000) / 1000;
        return rounded.toString();
    }
    // 两个函数在摄氏度和华氏度   start
    toCelsius(fahrenheit) {
        return (fahrenheit - 32) * 5 / 9;
    }

    toFahrenheit(celsius) {
        return (celsius * 9 / 5) + 32;
    }
    // 两个函数在摄氏度和华氏度   end

    // 获取input值并改变状态   start
    handleCelsiusChange(temperature) {
        this.setState({ scale: 'c', temperature });
    }

    handleFahrenheitChange(temperature) {
        this.setState({ scale: 'f', temperature })
    }
    // 获取input值并改变状态   end

    render() {
        const scale = this.state.scale;
        const temperature = this.state.temperature;
        const celsius = scale === 'f' ? this.tryConvert(temperature, this.toCelsius) : temperature;
        const fahrenheit = scale === 'c' ? this.tryConvert(temperature, this.toFahrenheit) : temperature;

        return (
            <div>
                {/* onTemperatureChange 传给子组件 */}
                <TemperatureInput
                    scale="c"
                    temperature={celsius}
                    onTemperatureChange={this.handleCelsiusChange.bind(this)} />

                <TemperatureInput
                    scale="f"
                    temperature={fahrenheit}
                    onTemperatureChange={this.handleFahrenheitChange.bind(this)} />

                <BiolingVerdict celsius={parseFloat(celsius)} />
            </div>
        )
    }
}


export default Calculator;

child1.js

import React from 'react';

const scaleNames = {
    c: 'Celsius',
    f: 'Fahrenheit'
}
class TemperatureInput extends React.Component {
    constructor(props) {
        super(props);
        console.log(this.props); // {scale: "c", temperature: "", onTemperatureChange: ƒ}
    }

    handleChange(e) {
        // 触发父组件onTemperatureChange
        this.props.onTemperatureChange(e.target.value);
    }

    render() {
        const temperature = this.props.temperature;
        const scale = this.props.scale;
        return (
            <fieldset>
                <legend>Enter temperature in {scaleNames[scale]}</legend>
                <input value={temperature} onChange={this.handleChange.bind(this)} />
            </fieldset>
        )
    }
}

export default TemperatureInput;

child2.js

import React from 'react';
class BoilingVerdict extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        let element;
        if (this.props.celsius >= 100) {
            element = <p>The water would boil.{this.props.celsius}</p>;
        } else {
            element = <p>The water would not boil.{this.props.celsius}</p>;
        }
        return (
            <div>
                {element}
            </div>
        )
    }
}
export default BoilingVerdict;

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值