React 组件

  • 组件是元素复用的思想,也是组件化框架的最主要的特征。我们现在要把网页的菜单栏看出一个组件,然后独立的抽象出来,这样做之后,任何需要菜单的页面只要导入该组件,就可以实现代码复用,让维护和扩展都变得简单。

组件有两个核心概念:

props

props 就是组件的属性,由外部通过 JSX 属性传入设置,一旦初始设置完成,就可以认为 this.props 是不可更改的,所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。

state

state 是组件的当前状态,可以把组件简单看成一个“状态机”,根据状态 state 呈现不同的 UI 展示。 一旦状态(数据)更改,组件就会自动调用 render 重新渲染 UI,这个更改的动作会通过 this.setState 方法来触发。setState是React事件处理函数中和请求回调函数中触发UI更新的主要方法。



复合组件

  • 创建多个组件来合成一个组件,即把组件的不同功能点进行分离
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 实例</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>

<div id="example"></div>
<script type="text/babel">
function Name(props) {
    return <h1>网站名称:{props.name}</h1>;
}
function Url(props) {
    return <h1>网站地址:{props.url}</h1>;
}
function Nickname(props) {
    return <h1>网站小名:{props.nickname}</h1>;
}
function App() {
    return (
    <div>
        <Name name="百度一下" />
        <Url url="http://www.baidu.com" />
        <Nickname nickname="百度" />
    </div>
    );
}

ReactDOM.render(
     <App />,
    document.getElementById('example')
);
</script>

</body>
</html>


React -- 组件间通信

分为三种类型的通信关系: 
1、父组件向子组件通信 
2、子组件向父组件通信 
3、没有嵌套关系的组件之间的通信

父组件向子组件通信
父组件通过子组件的props向子组件传递需要的信息。

子组件向父组件通信
两种方法: 
1、利用回调函数 
2、利用自定义事件机制


ListItem.js:


import React, { Component } from 'react';

class ListItem extends Component{
    static defaultProps = {
        text: '',
        checked: false,
    }
    render() {
        return(
            <li>
                <input type="checkbox" checked={this.props.checked} onChange={this.props.onChange}/>
                <span>{this.props.value}</span>
            </li>
        )
    }

}

export default ListItem

List.js:

import React, { Component } from 'react';
import ListItem from './ListItem';

class List extends Component {
    constructor(props) {
        super(props);
        this.state = {
            list: [
                {
                    text: '苹果',
                    checked: false
                },
                {
                    text: '草莓',
                    checked: false
                }
            ]
        }
    }

    onItemChange(val) {
        const {list} = this.state
        this.setState({
            list: list.map((item) =>({
                text: item.text,
                checked: item.text == val.text ? !item.checked: item.checked
            }))
        })

    }

    render() {
        return (
            <div>
                {
                    this.state.list.map((item, index) =>{
                        return (
                            <ListItem
                                key={index}
                                checked={item.checked}
                                value={item.text}
                                onChange={this.onItemChange.bind(this, item)}
                            />
                        )
                    })
                }
            </div>
        )
    }
}

export default List;

App.js:

import React, { Component } from 'react';
import List from './List'

class APP extends Component {

  render() {
    return (
        <List />
    )
  }
}
export default APP;

跨级组件通信 context来实现跨级通信。

Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递.

List.js:


import React from 'react';
import ListItem from './ListItem';
import MyContext from './context';

class List extends React.Component {
     constructor(props) {
        super(props)
        this.state = {
            msg: ''
        }
    }

    fromGranson(val){
        this.setState({msg: val})
    }

    // 使用一个 Provider 来将当前的 value 传递给以下的组件树。
    // 无论多深,任何组件都能读取这个值。
    render(){
        return (
            <div style={{backgroundColor:'#f7ba2a',padding:'20px',width:'500px',margin:'auto',textAlign:'center'}}>
                <p>context通信实例第一层</p>
                <span style={{color: 'red',fontSize:'30px'}}>{this.state.msg}</span>
                <MyContext.Provider value={{text: '今天星期五',toParent: this.fromGranson.bind(this)}}>
                    <Son1/>
                </MyContext.Provider>
            </div>
        )
    }
}

// 导出组件
export default List;

ListItem.js:


import React from 'react';
import Grandson from './Grandson';

class ListItem extends React.Component {
  render(){
    return (
      <div>
        <Grandson></Grandson>
      </div>
    )
  }
}
// 导出组件
export default ListItem;

Grandson.js:


import React from 'react';
import MyContext from './context';

class Grandson extends React.Component {
    // 指定 contextType 读取当前的 MyContext
    /*
        挂载在 class 上的 contextType 属性可以赋值为由 React.createContext() 创建的 Context 对象。
        此属性可以让你使用 this.context 来获取最近 Context 上的值。
        你可以在任何生命周期中访问到它,包括 render 函数中。
    */
    static contextType = MyContext
    constructor(props) {
        super(props)
    }

    toParent()
    {
        this.context.toParent('孙组件向爷爷组件传数据')
    }

    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>
                <button onClick={() => this.toParent()}>context向上</button>
            </div>

        )
    }
}

export default Grandson

context.js:


import React from "react";
const MyContext = React.createContext({text:'我是一个文本'});
export default MyContext

App.js:

import React, { Component } from 'react';
import List from './List'

class APP extends Component {
  render() {
    return (
        <List />
    )
  }
}
export default APP;

没有嵌套关系的组件通讯

events.js:


// events.js(以常用的发布/订阅模式举例,借用Node.js Events模块的浏览器版实现)
import { EventEmitter } from 'events';
export default new EventEmitter();

OneList.js:


import React, { Component } from 'react';
import emitter from './events';

class OneList extends Component {
 constructor(props) {
  super(props);
  this.state = {
   message: 'oneList',
  };
 }
 componentDidMount() {
  // 组件装载完成以后声明一个自定义事件,也就是订阅事件
  this.eventEmitter = emitter.addListener('changeMessage', (message) => {
   this.setState({
    message,
   });
  });
 }
 componentWillUnmount() {
  //  取消订阅,就是销毁事件
  emitter.removeAllListeners(this.eventEmitter);
 }
 render() {
  return (
   <div>
    {this.state.message}
   </div>
  );
 }
}
export default OneList;

TwoList.js:


import React, { Component } from 'react';
import emitter from './events';

class TwoList extends Component {
 handleClick = (message) => {
  //  发布事件,也就是触发事件
  emitter.emit('changeMessage', message);
 };
 render() {
  return (
   <div>
    <button onClick={this.handleClick.bind(this, 'TwoList')}>点击我改变OneList组件中显示信息</button>
   </div>
  );
 }
}
export default TwoList;

App.js:

import React, { Component } from 'react';
import OneList from './OneList'
import TwoList from './TwoList'

class APP extends Component {

  render() {
    return (
      <OneList/>
      <TwoList/>
    )
  }
}
export default APP;
powered by GitbookEdit Time: 2023-04-08 10:28:32