React学习【05】React 消息订阅发布机制

React 消息订阅发布机制

文章目录

  • React 消息订阅发布机制
  • 1. 组件间通信
    • 1.1 方式一: 通过props传递
    • 1.2 方式二: 使用消息订阅(subscribe)-发布(publish)机制
    • 1.3 方式三: redux
  • 2. 事件监听理解
    • 2.1 原生DOM事件
    • 2.2 自定义事件(消息机制)
  • 3. ES6常用新语法

1. 组件间通信

1.1 方式一: 通过props传递

  1. 共同的数据放在父组件上, 特有的数据放在自己组件内部(state)

  2. 通过props可以传递一般数据和函数数据, 只能一层一层传递

  3. 一般数据–>父组件传递数据给子组件–>子组件读取数据

  4. 函数数据–>子组件传递数据给父组件–>子组件调用函数

1.2 方式二: 使用消息订阅(subscribe)-发布(publish)机制

  1. 工具库:PubSubJS
  2. 下载: npm install pubsub-js --save
  3. 文档: https://www.npmjs.com/package/pubsub-js
  4. 使用:
  • import PubSub from ‘pubsub-js’ //引入
  • PubSub.subscribe(‘delete’, function(data){ }); //订阅
  • PubSub.publish(‘delete’, data) //发布消息

例子1

// import PubSub from 'pubsub-js'
// or when using CommonJS
const PubSub = require('pubsub-js');

//订阅消息
var token = PubSub.subscribe('MY TOPIC', (msg, data) => {
  console.log( msg, data );
});

//发布消息
PubSub.publish('MY TOPIC', 'hello world!');

例子2

更改Ajax项目为消息订阅发布模式,具体项目地址:/react-learn-demo/class_02/class-demo-05-githubsp

React学习【05】React 消息订阅发布机制_第1张图片

app.jsx

import React, {Component} from 'react'
import Pubsub from 'pubsub-js'


import Search from './search'
import List from "./list";

export default class App extends Component {

  state = {
    searchName: ''
  }

  componentDidMount(){
    //设置订阅setSearchName
    Pubsub.subscribe("setSearchName",(msg, searchName) => {
      this.setState({searchName})
    })
  }

  //当setState改变时调用
  shouldComponentUpdate(nextProps, nextState) {
    //当searchName改变时,发布消息
    Pubsub.publish("searchName",nextState)
    return {nextProps,nextState}
  }



  render() {
    return (
      <div>
        <div id="app">
          <div className="container">
            <Search/>
            <List/>
          </div>
        </div>
      </div>
    )
  }
}

card.jsx

import React, {Component} from 'react'
import PropTypes from 'prop-types'

export default class Card extends Component {

  static propTypes = {
    user:PropTypes.object.isRequired
  }

  render() {
    const {user} = this.props
    return (
      <div className="card" key={user.html_url}>
        <a href={user.html_url} target="_blank">
          <img src={user.owner.avatar_url} style={{width: '100px'}} alt='user'/>
        </a>
        <p className="card-text">{user.name}</p>
      </div>
    )
  }
}

list.jsx

import React, {Component} from 'react'
import axios from 'axios'

import Card from './card'
import Pubsub from "pubsub-js";

export default class List extends Component {

  state = {
    firstView: true,
    loading: false,
    users: [],
    error: null
  }

  componentDidMount(){
    //订阅消息setSearchName
    Pubsub.subscribe("setSearchName",(msg, searchName) => {
      console.log("have " + searchName);
      //正在加载
      this.setState({
        firstView : false,
        loading : true
      })
      //发送请求
      axios.get("https://api.github.com/search/repositories?q=" + searchName + "&sort=stars")
        .then(response => {
          this.setState({
            loading : false,
            users : response.data.items
          })
        })
        .catch(error => {
          console.log(error.message);
          this.setState({
            loading : false,
            error : error.message
          })
        })
    })
  }

  render() {
    if (this.state.firstView) {
      return <h2>Enter name to search</h2>
    } else if (this.state.loading) {
      return <h2>Loading result...</h2>
    } else if (this.state.error) {
      return <h2>{this.state.error}</h2>
    } else {
      return (
        <div className="row">
          {
            this.state.users.map((user,index) => (
              <Card user={user} key={index}/>
            ))
          }
        </div>
      )
    }
  }
}

search.jsx

import React, {Component} from 'react'
import Pubsub from 'pubsub-js'

export default class Search extends Component {

  submitSearchName = () => {
    const inputValue = this.input.value;
    //当输入值改变时,发布消息setSearchName
    Pubsub.publish("setSearchName",inputValue)
  }

  render() {
    return (
      <section className="jumbotron">
        <h3 className="jumbotron-heading">Search Github Users</h3>
        <div>
          <input type="text" placeholder="enter the name you search" ref={input => this.input = input }/>
          <button onClick={this.submitSearchName}>Search</button>
        </div>
      </section>
    )
  }
}

1.3 方式三: redux

后面介绍

2. 事件监听理解

2.1 原生DOM事件

  1. 绑定事件监听
  • 事件名(类型): 只有有限的几个, 不能随便写
  • 回调函数
  1. 触发事件
  • 用户操作界面
  • 事件名(类型)
  • 数据()

2.2 自定义事件(消息机制)

  1. 绑定事件监听
  • 事件名(类型): 任意
  • 回调函数: 通过形参接收数据, 在函数体处理事件
  1. 触发事件(编码)
  • 事件名(类型): 与绑定的事件监听的事件名一致
  • 数据: 会自动传递给回调函数

3. ES6常用新语法

  1. 定义常量/变量: const/let

  2. 解构赋值: let {a, b} = this.props / import {aa} from 'xxx'

  3. 对象的简洁表达: {a, b}

  4. 箭头函数:

    • 常用场景

      • 组件的自定义方法: xxx = () => {}

      • 参数匿名函数

    • 优点:

      • 简洁

      • 没有自己的this,使用引用this查找的是外部this

  5. 扩展(三点)运算符: 拆解对象(const MyProps = {}, )

  6. 类: class/extends/constructor/super

  7. ES6模块化: export default | import

你可能感兴趣的:(【30】React)