React-配置代理-pubsubjs发布订阅

React中配置代理解决跨域问题

解决跨域问题,在React开启中间代理
在项目中的package.json中,最后加上一行"proxy": "http://loaclhost:5000" 写到端口号
然后重启脚手架
再次发送请求的时候就直接写自己的3000端口
3000端口有的资源直接请求3000端口的,3000端口没有的资源就请求代理设置的5000端口

在package.json中追加如下配置

"proxy":"http://localhost:5000"

配置多个代理方法

在src下创建配置文件:src/setupProxy.js

编写setupProxy.js配置具体代理规则:

const proxy = require('http-proxy-middleware')

module.exports = function(app) {
  app.use(
    proxy('/api1', {  //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
      target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
      changeOrigin: true, //控制服务器接收到的请求头中host字段的值
      /*
      	changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
      	changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
      	changeOrigin默认值为false,但我们一般将changeOrigin值设为true
      */
      pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
    }),
    proxy('/api2', { 
      target: 'http://localhost:5001',
      changeOrigin: true,
      pathRewrite: {'^/api2': ''}
    })
  )
}

  • 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
  • 缺点:配置繁琐,前端请求资源时必须加前缀。

【补充】连续解构赋值

let obj = {a:{b:{c:1}}}
console.log(a.b.c) // 1
const {a:{b:{c}}} = obj
console.log(c) // 1

let obj2 = {a:{b:1}}
const {a:{b:data}} = obj2 // 重命名
console.log(data) // 1

PubSubJS库

前面案例中,兄弟组件之间的通信总是要借助父组件才行
现在介绍消息订阅-发布机制来进行兄弟组件之间通信

下载: npm install pubsub-js

使用:
在【接收】数据的组件中【订阅】消息

import PubSub from 'pubsub-js' //引入
PubSub.subscribe('delete', function(data){ }); // 订阅
PubSub.publish('delete', data) // 发布消息 携带数据

在案例中使用:

Users/index.jsx
export default class Users extends Component {
  // 初始化状态
  state = { 
    users: [], // users初始值
    isFirst: true, // 是否第一次打开页面
    isLoading: false, // 标识是否处于加载中
    err:'' // 请求失败的消息
  }
  componentDidMount() {
    // 订阅消息
    PubSub.subscribe('ykyk', (_, data) => {
      this.setState(data)
    })
  }
  render() {
    const {users, isFirst, isLoading, err} = this.state
    return (
      <div className="row">
        {
          isFirst ? <h2>欢迎使用,请输入关键字,随后点击搜索</h2> :
          isLoading ? <h2>Loading...</h2> :
          err ? <h2 style={{color: 'red'}}>{err}</h2> :
          users.map((userObj) => {
            return (
              <div key={userObj.id} className="card">
                <a rel="noreferrer" href={userObj.html_url} target="_blank">
                    <img alt="avatar" src={userObj.avatar_url} style={{ 'width': '100px' }}/>
                </a>
                <p className="card-text">{userObj.login}</p>
              </div>
            )
          })
        }
      </div>
    )
  }
}


Search/index.jsx

export default class Search extends Component {
  search = () => {
    const {keyWordElement: {value: keyWord}} = this
    // 发送请求前通知Users更新状态
    // this.props.updateAppState({isFirst: false,isLoading: true})
    PubSub.publish('ykyk', {isFirst: false,isLoading: true})
    // 发送网络请求
    axios.get(`/api1/search/users?q=${keyWord}`).then(
      response => {
        // 请求成功,通知Users更新状态
        PubSub.publish('ykyk', {isLoading: false, users: response.data.items})
        // this.props.updateAppState({isLoading: false, users: response.data.items})
      },
      error => {
        // 请求失败,通知Users更新状态
        PubSub.publish('ykyk', {isLoading: false, err: error.message})
        // this.props.updateAppState({isLoading: false, err: error.message})
      }
    )
  }
  render() {
    return (
      <section className="jumbotron">
      <h3 className="jumbotron-heading">搜索Github用户</h3>
      <div>
          <input ref={c => this.keyWordElement = c} type="text" placeholder="请输入你要搜索的用户名" />&nbsp;
          <button onClick={this.search}>搜索</button>
      </div>
      </section>
    )
  }
}




阅读剩余
THE END