react组件和组件通信

组件

函数式组件(推荐)

//1.创建函数式组件
function re(){
  console.log(this); //此处的this是undefined,因为babel编译后开启了严格模式
  return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
}

//2.渲染组件到页面
ReactDOM.render(<MyComponent/>,document.getElementById('test'))

执行了ReactDOM.render(…之后,发生了什么?

  1. React解析组件标签,找到了MyComponent组件。
  2. 发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中。

类式组件

//1.创建类式组件
class MyComponent extends React.Component {
  render(){
    //render是放在哪里的?—— MyComponent的原型对象上,供实例使用。
    //render中的this是谁?—— MyComponent的实例对象 <=> MyComponent组件实例对象。
    console.log('render中的this:',this);
    return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
  }
}
//2.渲染组件到页面
ReactDOM.render(<MyComponent/>,document.getElementById('test'))

执行了ReactDOM.render(…之后,发生了什么?

  1. React解析组件标签,找到了MyComponent组件。
  2. 发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。
  3. 将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。

弊端

  • 大型组件很难拆分和重构,也很难测试。
  • 业务逻辑分散在组件的各个方法之中,导致重复逻辑或关联逻辑。
  • 组件类引入了复杂的编程模式,比如 render props 和高阶组件。

注意

  1. 组件名必须首字母大写
  2. 虚拟DOM元素只能有一个根元素
  3. 虚拟DOM元素必须有结束标签

组件通信

父传子

父组件通过向子组件传递 props,子组件得到 props 后进行相应的处理

// 父组件
render(){
  return(
    <div>
      <Sub title = "今年过节不收礼" />
    </div>
  )
}

// 子组件 Sub
render(){
  return(
    <h1>
      { this.props.title }
    </h1>
  )
}

// 函数组件使用
function Sub(props){
  const { title } = props;
}

子传父

父组件将一个函数作为 props 传递给子组件,子组件调用该回调函数,便可以向父组件通信

// 父组件
callback = msg =>{console.log(msg);}
render(){
  return(
    <div>
      <Sub callback = { this.callback } />
    </div>
  )
}

// 子组件 Sub
cb = (msg) => {
  return () => {
    this.props.callback(msg)
  }
}
render(){
  return(
    <div>
      <button onClick = { this.cb("子数据") }>点击我</button>
    </div>
  )
}

跨级传值

// 先创建一个context.js文件(与父子孙同个目录),默认值为一个对象
import React from ``"react"``;
const MyContext = React.createContext({text:``'luck'``});
export ``default` `MyContext

// 父组件
import MyContext from './context';
class Parent extends React.Component {
  constructor(props) {
    super(props);
  }
  // 使用一个 Provider 来将当前的 value 传递给以下的组件树。
  // 无论多深,任何组件都能读取这个值。
  render(){
    return (
      <div style={{backgroundColor:'#f7ba2a',padding:'20px',width:'500px',margin:'auto',textAlign:'center'}}>
        <p>context通信实例</p>
        <MyContext.Provider value={{text:'good luck'}}>
          <Children></Children>
        </MyContext.Provider>
      </div>
    )
  }
}

// 孙组件
// 新增一个“孙”组件,同样需引入context,在组件内部添加static contextType = MyContext,此时将能通过this.context直接获取到上层距离最近的Provider传递的值,此时this.context = {text:good luck},即父组件传递value。
import MyContext from './context';
class Grandson extends React.Component {
  static contextType = MyContext
  render(){
    return (
      <div style={{backgroundColor:'#13ce66',padding:'10px',width:'200px',margin:'auto',marginTop:'20px'}}>
        <p>通过context传过来:</p>
        <span style={{color:'blue'}}>{this.context.text}</span>
      </div>
    )
  }
}

// 如果想孙-->父向上传值,可以通过回调的方式
// 注意:在下层组件中取的context中的字段需与value中传递字段保持一致

兄弟(无嵌套)组件通信

当两个组件互不嵌套,处在同个层级或者不同层级上,他们之间要进行通信,有以下几种常用方法

  • 某个组件先将值传到同一个父组件,然后在通过父组件传给另外一个组件,用到父子组件传值
  • 使用缓存sessionStorage、localStorage等
  • 如果两个组件之间存在跳转,可以使用路由跳转传值
  • event(发布–订阅)

使用event方法的基本流程

// 1. 安装event
npm install event -save

// 2. 新建一个events.js
import { EventEmitter } from 'events';
export default new EventEmitter();

// 3. 发数据
import EventBus from './events'
EventBus.emit('login',values.userName)

// 4. 收数据
const a = EventBus.addListener('login',(name)=>{
  this.setState({user:name})
})
const a = EventBus.on('login',(name)=>{
  this.setState({user:name})
})
// 6. 卸载绑定事件
EventBus.removeListener(a)
  • on(): 负责注册事件的监听(订阅),指定事件触发(发布)时的回调函数;
  • emit(): 负责触发事件,可以通过传参使其在触发的时候携带数据
  • off():负责监听器的删除(解除事件)

消息订阅-发布机制

工具库: PubSubJS

下载: npm install pubsub-js --save

使用:

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

你可能感兴趣的:(#,React,react.js,javascript,前端,组件,组件通信)