美文网首页React
【React】组件

【React】组件

作者: Qingelin | 来源:发表于2019-10-17 23:44 被阅读0次

1. class组件

复杂的组件,需要记录自己内部状态的话,使用class组件,因为function不能有局部变量和方法,而class可以有。

 //一部分页面标签放在一个函数里
function App(){
  return (
    <div>
      app
    </div>
  )
}
//必须继承组件,添加extends React.Component
class App2 extends React.Component{

  constructor(props){ //声明变量必须写在constructor里面
    super(props)//使用constructor必须写这个
    this.state= {  变量必须写在this.state里
       number:0
    }
  }
 
      
  add(){
    this.setState({
      number: this.state.number += 1
    })
  }
  render(){ //局部render
    return (
      <div>
        app 2 {this.props.name}
        <div>
          {this.state.number} 
          <button onClick={this.add.bind(this)}>+</button>
        </div>
      </div>
    )
  }
}


render()

function render(){
  
  ReactDOM.render(
      <App2 name="qinglin" age="18"/>, 
      document.querySelector('#root'))
}

2. 函数组件

把组成一部分页面的标签写在一个函数中,叫做函数组件。

  • 在上一节中说过React的作者的第一个创举,组件当中体现了第二个创举:标签的名字就是函数,标签的属性的key value 理解成一个对象,函数的参数就是这个对象。
    例如:
let number = 0

add =()=>{
  number += 1
  render()
}

minus =()=>{
  number -= 1
  render()
}
 
 //一部分页面标签放在一个函数里
function App(){
  return (
    <div>
  //这里的Box1标签就是函数,代表页面一部分的标签,标签的属性其实是对象,下面两个函数的参数obj就是这个对象
      <Box1 name="加一" />
    </div>
  )
}

function Box1(obj){
  return (
    <div class="parent">
    我的名字是{obj.name}
    <hr />
      <span>{number}</span>
      <button onClick={add}>+</button>
      <button onClick={minus}>-</button>
    </div>
  )
}


render()

function render(){
  
  ReactDOM.render(
      //虚拟DOM,本质就是对象
      
      
      <App/>, //这是XML语法
      
      
      document.querySelector('#root'))
}





【涉及到的知识点】

  • this.setState ————

    • 优点:回对更新优化,会把多次更新结果只进行一次渲染就能完成
    • 缺点:同时带来了弊端,有时候会有多个执行语句时异步更新
  • DOM diff ——— react每次修改变量都会自动智能地去局部更新页面内,更新之前都会把最新信息跟之前相比较,然后只更新有变化的部分,这种非常友好的过程叫DOM diff。


3. 组件通信

3.1 父子通信
  • 子组件向父级组件传递信息:
    原理:父级组件传一个函数,子元素在必要时(回调)调用通信函数(通信函数被调用时还可以传给它一些参数页面中可以渲染出来)。
   //代码示例
这个App是父元素
class App extends React.Component{ 
    constructor(){
       this.state={
          ...
      }
      this.setState({
        ....
      })
    }

    通信函数1(){}
    通信函数2(){}
    //App父级组件会把两个通信函数分别传给子级组件div1 和 div2
    render(){
      return (
        <div>
          <div1 f1 = {this.通信函数1.bind(this)}></div1>
          <div1 f2 = {this.通信函数2.bind(this)}></div1>
        </div>
      )
    }
}

//两个div子组件会调用通信函数

//这个div1是子元素
class div1 extends React.Component{
    ....
    this.state.通信函数1()
}
//这个div2也是子元素
class div2 extends React.Component{
   ....
  this.state.通信函数2()
}
  • 父级组件向子级组件传递信息:
    父级组件通过 props 给子组件的某个属性传一个值
      function App(){
          return (
                <div>
                     <span message="你好!"/>
                </div>
          )
      }
      
    function span(props){
        return (
          <p>子级组件得到的信息是:{props.message}</p>
        )
     }
    
    ReactDOM.renfer(
       <App />,
       document.querySelector("root")   
    )
    

3.1 爷孙通信

原理:爷爷级组件把一个或多个函数传给父级组件,父级组件再把这个函数透传给子级组件,最后自己组建调用这个函数。

代码示例,
这个App是父元素
class App extends React.Component{ 
    constructor(){
       this.state={
          ...
      }
      this.setState({
        ....
      })
    }

    通信函数1(){}
    通信函数2(){}
    //App爷爷级组件会把两个通信函数分别传给父级组件parent
    render(){
      return (
        <div>
          <parent  
                  success1={this.success1.bind(this)}
                   success2={this.success2.bind(this)}
        />
        </div>
      )
    }
}

function parent(props){
  let 通信1 = props.通信函数1
  let 通信2 = props.通信函数2
  return (
    <div class="playground">
      //parent再把通信函数传给div孙子级组件
       <Track1 通信={通信1} />
       <Track2 通信={通信2}/>
    </div>
  )
}

div孙子级组件会调用通信函数

//这个div1是孙子组件
class div1 extends React.Component{
    ....
    this.state.通信()
}
//这个div2也是孙子元素
class div2 extends React.Component{
   ....
  this.state.通信2()
}
  • 类似父子关系组件之间的通信就是这样一次传给函数,最后子级调用这个函数的过程。

4 . 任意组件之间通信

  • 发布订阅模式(EventHub)
var eventHub = {
    //发布事件
    trigger(eventName,data){}, //参数一为事件名,参数二位要发布的数据
    //订阅事件
    on(eventName,function(){}) //参数一为事件名,参数二为调用函数
}


eventHub.on('事件名',function(){})//订阅,click是事件名称
eventHub.trigger('事件名',data)
  • 单向数据流:
    原理:一个组件向下延申拥有树形关系的子组件,那么如何在互相没有直接关系 的组件之间通信呢?对此React提供了一种发布订阅模式(eventHub)的功能,eventHub 的具体用法在上一内容中有。只要其中一个组件给页面发布修改请求,这个请求就会被最订阅机质收到,这个机质是个对象,只存在内存中,不会被渲染到页面中,订阅机制收到后给最高级的组件传递信息,然后由父向子级组件依次通过props传递调用函数最后被各个子组件调用,最后进行(DOM diff) 渲染。这样就可以在任意组件之间进行通信了。

  • Redux
    使用eventHub发布订阅模式的特点是所有的动作都是通过事件来完成,数据必须放在顶层组件。

    • 下面是一些约定名词:
      • store 所有存数据的地方
      • store 对象中的对于数据的操作叫 reducer
      • eventHub.on 订阅subscribe
      • eventHub.trigger 发布action
      • eventHub.trigger('eventName',data) eventName叫action type 、data 叫 payload
  • Redux的优点:
    1. eventHub的所有动作都是通过事件来进行的,而且事件名可以是任意的,所以可能会存在隐藏的Bug,对此Redux做出了调整:

      switch (action.type) {
          case 'event1':
            function() { }
            break;
          case 'event2':
          function() { }
            break;
            ....
        default:
          return {
        
        }
      }
    

就这样吧所有事件统一列在一个地方,防止重复使用

  1. Redux把所有数据写在顶层的组件中,并且只能只读取。
  2. 提高了前端的门槛,对于英语的要求较高。

5. Readux

  • 使用Redux的步骤:
    1. 声明一个store,专门保存数据的,
      声明时必须使用createStore,接受的参数叫counter的一个函数
        counter(state, action) {return 新的数据} //参数一为初始数据,参数二为### 1. class组件
      

复杂的组件,需要记录自己内部状态的话,使用class组件,因为function不能有局部变量和方法,而class可以有。

 //一部分页面标签放在一个函数里
function App(){
  return (
    <div>
      app
    </div>
  )
}
//必须继承组件,添加extends React.Component
class App2 extends React.Component{

  constructor(props){ //声明变量必须写在constructor里面
    super(props)//使用constructor必须写这个
    this.state= {  变量必须写在this.state里
       number:0
    }
  }
 
      
  add(){
    this.setState({
      number: this.state.number += 1
    })
  }
  render(){ //局部render
    return (
      <div>
        app 2 {this.props.name}
        <div>
          {this.state.number} 
          <button onClick={this.add.bind(this)}>+</button>
        </div>
      </div>
    )
  }
}


render()

function render(){
  
  ReactDOM.render(
      <App2 name="qinglin" age="18"/>, 
      document.querySelector('#root'))
}

2. 函数组件

把组成一部分页面的标签写在一个函数中,叫做函数组件。

  • 在上一节中说过React的作者的第一个创举,组件当中体现了第二个创举:标签的名字就是函数,标签的属性的key value 理解成一个对象,函数的参数就是这个对象。
    例如:
let number = 0

add =()=>{
  number += 1
  render()
}

minus =()=>{
  number -= 1
  render()
}
 
 //一部分页面标签放在一个函数里
function App(){
  return (
    <div>
  //这里的Box1标签就是函数,代表页面一部分的标签,标签的属性其实是对象,下面两个函数的参数obj就是这个对象
      <Box1 name="加一" />
    </div>
  )
}

function Box1(obj){
  return (
    <div class="parent">
    我的名字是{obj.name}
    <hr />
      <span>{number}</span>
      <button onClick={add}>+</button>
      <button onClick={minus}>-</button>
    </div>
  )
}


render()

function render(){
  
  ReactDOM.render(
      //虚拟DOM,本质就是对象
      
      
      <App/>, //这是XML语法
      
      
      document.querySelector('#root'))
}





【涉及到的知识点】

  • this.setState ————

    • 优点:回对更新优化,会把多次更新结果只进行一次渲染就能完成
    • 缺点:同时带来了弊端,有时候会有多个执行语句时异步更新
  • DOM diff ——— react每次修改变量都会自动智能地去局部更新页面内,更新之前都会把最新信息跟之前相比较,然后只更新有变化的部分,这种非常友好的过程叫DOM diff。


3. 组件通信

3.1 父子通信
  • 子组件向父级组件传递信息:
    原理:父级组件传一个函数,子元素在必要时(回调)调用通信函数(通信函数被调用时还可以传给它一些参数页面中可以渲染出来)。
   //代码示例
这个App是父元素
class App extends React.Component{ 
    constructor(){
       this.state={
          ...
      }
      this.setState({
        ....
      })
    }

    通信函数1(){}
    通信函数2(){}
    //App父级组件会把两个通信函数分别传给子级组件div1 和 div2
    render(){
      return (
        <div>
          <div1 f1 = {this.通信函数1.bind(this)}></div1>
          <div1 f2 = {this.通信函数2.bind(this)}></div1>
        </div>
      )
    }
}

//两个div子组件会调用通信函数

//这个div1是子元素
class div1 extends React.Component{
    ....
    this.state.通信函数1()
}
//这个div2也是子元素
class div2 extends React.Component{
   ....
  this.state.通信函数2()
}
  • 父级组件向子级组件传递信息:
    父级组件通过 props 给子组件的某个属性传一个值
      function App(){
          return (
                <div>
                     <span message="你好!"/>
                </div>
          )
      }
      
    function span(props){
        return (
          <p>子级组件得到的信息是:{props.message}</p>
        )
     }
    
    ReactDOM.renfer(
       <App />,
       document.querySelector("root")   
    )
    

3.1 爷孙通信

原理:爷爷级组件把一个或多个函数传给父级组件,父级组件再把这个函数透传给子级组件,最后自己组建调用这个函数。

代码示例,
这个App是父元素
class App extends React.Component{ 
    constructor(){
       this.state={
          ...
      }
      this.setState({
        ....
      })
    }

    通信函数1(){}
    通信函数2(){}
    //App爷爷级组件会把两个通信函数分别传给父级组件parent
    render(){
      return (
        <div>
          <parent  
                  success1={this.success1.bind(this)}
                   success2={this.success2.bind(this)}
        />
        </div>
      )
    }
}

function parent(props){
  let 通信1 = props.通信函数1
  let 通信2 = props.通信函数2
  return (
    <div class="playground">
      //parent再把通信函数传给div孙子级组件
       <Track1 通信={通信1} />
       <Track2 通信={通信2}/>
    </div>
  )
}

div孙子级组件会调用通信函数

//这个div1是孙子组件
class div1 extends React.Component{
    ....
    this.state.通信()
}
//这个div2也是孙子元素
class div2 extends React.Component{
   ....
  this.state.通信2()
}
  • 类似父子关系组件之间的通信就是这样一次传给函数,最后子级调用这个函数的过程。

4 . 任意组件之间通信

  • 发布订阅模式(EventHub)
var eventHub = {
    //发布事件
    trigger(eventName,data){}, //参数一为事件名,参数二位要发布的数据
    //订阅事件
    on(eventName,function(){}) //参数一为事件名,参数二为调用函数
}


eventHub.on('事件名',function(){})//订阅,click是事件名称
eventHub.trigger('事件名',data)
  • 单向数据流:
    原理:一个组件向下延申拥有树形关系的子组件,那么如何在互相没有直接关系 的组件之间通信呢?对此React提供了一种发布订阅模式(eventHub)的功能,eventHub 的具体用法在上一内容中有。只要其中一个组件给页面发布修改请求,这个请求就会被最订阅机质收到,这个机质是个对象,只存在内存中,不会被渲染到页面中,订阅机制收到后给最高级的组件传递信息,然后由父向子级组件依次通过props传递调用函数最后被各个子组件调用,最后进行(DOM diff) 渲染。这样就可以在任意组件之间进行通信了。

  • Redux
    使用eventHub发布订阅模式的特点是所有的动作都是通过事件来完成,数据必须放在顶层组件。

    • 下面是一些约定名词:
      • store 所有存数据的地方
      • store 对象中的对于数据的操作叫 reducer
      • eventHub.on 订阅subscribe
      • eventHub.trigger 发布action
      • eventHub.trigger('eventName',data) eventName叫action type 、data 叫 payload
  • Redux的优点:
    1. eventHub的所有动作都是通过事件来进行的,而且事件名可以是任意的,所以可能会存在隐藏的Bug,对此Redux做出了调整:

      switch (action.type) {
          case 'event1':
            function() { }
            break;
          case 'event2':
          function() { }
            break;
            ....
        default:
          return {
        
        }
      }
    

就这样吧所有事件统一列在一个地方,防止重复使用

  1. Redux把所有数据写在顶层的组件中,并且只能只读取。
  2. 提高了前端的门槛,对于英语的要求较高。

5. VanillaJs

  • 使用Redux之关键函数:
    声明一个store,专门保存数据的,
    声明时必须使用createStore,接受的参数叫counter的一个函数

        ```
         counter(state, action) {return 新的数据} //这个函数提前声明,函数的参数一为初始数据,      
        参数二为操作数据的函数
         var store = Redux.createStore(counter)   //接受一个函数为参数
       ```
    
  • 使用redux的思路:

    1. dispatch一个action
    2. counter函数生成一个新的state,然后触发一个事件
    3. 上一步出触发的事件被subscribe函数接受,
    4. subscribe函数会调用render函数,然后重新render
    5. 第二次render之后在得到新的store,浏览器DOM diff 之后渲染页面

6. Redux

  • react比vanilla好的地方是会DOM diff,局部更新。

7. React-Redux

7.1 API
  • connect(mapStateToProps,mapDispatchToProps)(App)
    一个括号为一个参数,第一个括号里可有多个参数,第二个括号为第二个参数 ;功能是把数据、数据变更动作、组件组合起来。
  • Provider() 从React-Redux引入之后以标签的形式写成包围组件,功能是获取state,然后通知到里面的每一个组件

  • 写这一节博客,做了简单的项目[https://github.com/cnqinglin/react-redux-v1]之后的最大的感觉就是React社区的东西其实不难,但为什么总感觉很难是因为它给就概念都给了一个新的名字。

相关文章

  • React基础

    React包含react元素和react组件 react元素 react组件 react组件分为函数组件和类组件 ...

  • 组件

    组件是React的基石,所有的React应用程序都是基于组件的。React组件,可以通过React.createC...

  • ReactNative学习笔记(三)Hello World!

    React Native 看起来很像 React,但React Native的基础组件是原生组件 不是web组件。...

  • react子组件向父组件传值

    相关资料:react 父组件怎么获取子组件的这个值React组件间信息传递方式react同级组件之间传值 • 父...

  • React 进阶二 组件详解

    React组件 React的组件大概分为俩部分,无状态组件和有状态组件 无状态组件。下面React官网中定义的一个...

  • 2、react基础介绍

    React理念 划分组件边界的原则 React组件的数据种类 React组件的声明周期 组件的划分 高内聚 低耦合...

  • React概念图

    React概念图 React组件生命周期概念图 参考文档:React入门教程 组件生命周期React:组件生命周期...

  • react16.3-jest

    功能组件和UI组件 react-antd 命名 react 规定组件开头都为大写,所以如果react项目如果用an...

  • 如何创建React组件并发布到npm?

    实现步骤: 创建React组件项目; 创建测试项目并引用组件; 发布React组件到npm上; 一、创建React...

  • RN原始项目-HelloWorld

    React Native看起来很像React,只不过其基础组件是原生组件而非web组件,。要理解React Nat...

网友评论

    本文标题:【React】组件

    本文链接:https://www.haomeiwen.com/subject/jpmrmctx.html