子传父——函数传递

  • 在 vue 中是通过自定义事件来完成的
  • 在 react 中同样是通过 props 来传递信息,只不过这个 props 是一个回调函数。父组件在引入的子组件中传递一个函数,并传参,子组件去触发这个函数更改参数完成数据更新
  • 注意,父组件向子组件传值时,要用increment = {e => this.increment()}的方式传递一个箭头函数过去,这样就没有 this 绑定的问题了。

案例:tabControl组件的实现

  • 要实现的功能如下,点击后进行切换:

2021-07-13_150053.jpg

  • 首先我们写一个最外层组件

    1. class App extends React.Component {
    2. constructor(props) {
    3. super(props);
    4. this.titles = ['路飞','索隆','艾斯'];
    5. this.state = {
    6. currentTitle: '路飞',
    7. titles: ['路飞','索隆','艾斯']
    8. }
    9. }
    10. render() {
    11. return (
    12. <div>
    13. <TabControl itemClick={index => this.itemClick(index)} titles={this.titles} />
    14. <h2>{ currentTitle }</h2>
    15. </div>
    16. )
    17. }
    18. itemClick(index) {
    19. this.setState({
    20. currentTitle: this.titles[index]
    21. })
    22. }
    23. }
  • 再写一个子组件

    1. class TabControl extends React.Component {
    2. constructor(props) {
    3. super(props);
    4. this.state = {
    5. currentIndex = 0
    6. }
    7. }
    8. render() {
    9. const { titles } = this.props;
    10. const { currentIndex } = this.state;
    11. return (
    12. <div className="tab-control">
    13. {
    14. titles.map((item, index) => {
    15. return (
    16. <div
    17. key={index}
    18. className={"tab-item" + (index === currentIndex ? "active" : "")}
    19. onClick={e => this.itemClick(index)}
    20. >
    21. <span>{item}</span>
    22. </div>
    23. )
    24. })
    25. }
    26. </div>
    27. )
    28. itemClick(index) {
    29. this.setState({
    30. currentIndex: index
    31. })
    32. const {itemClick} = this.props
    33. itemClick(index)
    34. }
    35. }
    36. }

React中实现类似vue的slot(插槽)功能

  • ….

跨组件通信——props

  1. // 头部组件
  2. function ProfileHeader(props) {
  3. return (
  4. <div>
  5. <h2>用户昵称:{props.nickName}</h2>
  6. <h2>用户等级:{props.level}</h2>
  7. </div>
  8. )
  9. }
  10. // 列表组件
  11. function Profile(props) {
  12. return (
  13. <div>
  14. <ProfileHeader nickName={props.nickName} level={props.level}/>
  15. <ul>
  16. <li>list1</li>
  17. <li>list2</li>
  18. <li>list3</li>
  19. <li>list4</li>
  20. </ul>
  21. </div>
  22. )
  23. }
  24. // 最外层组件
  25. class App extends React.Component {
  26. constructor(props) {
  27. super(props);
  28. this.state = {
  29. nickName: "ryan",
  30. level: "99"
  31. }
  32. }
  33. render() {
  34. const {nickName, level} = this.state;
  35. return (
  36. <div>
  37. <Profile nickName={nickName} level={level} />
  38. </div>
  39. )
  40. }
  41. }
  42. ReactDOM.render(<App/>, document.getElementById("App"));
  • 展示如下:

2021-07-13_160427.jpg

如上这种写法是很麻烦的,而且中间层 Profile 都没有用到那两个参数,但是为了传给子组件,必须接受下,所以这种跨组件的通信我们是不用的。有一种语法 ,效果和如上一样

跨组件通信——context

  • 非父子组件间数据的共享:
    • 开发中,比较常见的数据传递方式是通过 props 属性自上而下(父到子)进行传递
    • 但是对于一些场景:一个数据要在多个组件中进行共享(地区偏好、UI主题、用户登录状态,用户信息等)
    • 如果我们再顶层的 App 中定义了这些信息,之后一层层传递下去,那么对于一些不需要这些数据的中间层来说,是一种冗余的操作
    • 而且,如果层级更多,一层层传递非常麻烦,所以我们使用一种别的办法来实现
  • React 提供了一个API context
    • context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递props
    • context 设计的目的是为了共享那些对于一个组件树而言是“全局”的数据,如当前认证的用户,主题,或者首选语言
  • context 相关API
    • React.createContext
      • 创建一个需要共享的 Context 对象
      • 如果一个组件订阅了 Context ,那么这个组件会从离自身最近的那个匹配的 Provider 中读取到当前的 Context
      • defaultValue 是组件在顶层查找过程中没有找到对应的 Provider,那么就是用的默认值
      • const MyContext = React.createContext(defaultValue);
    • Context.Provider
      • 每个 Context 对象都返回一个 Provider React 组件,它允许消费组件订阅 Context 的变化
      • Provider 接收一个 value 属性,传递给消费组件
      • 一个 Provider 可以和多个消费组件有对应关系
      • 多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据
      • Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染
    • Class.contextType
      • 挂载在 class 上的 contextType 属性会被重新赋值未一个由 React.createContext() 创建的 Context 对象
      • 这能让你使用 this.context 来消费最近 Context 上的那个值
      • 你可以在任何生命周期中访问到它,包括 render 函数中
      • Myclass.contextType = MyContext;
    • Context.Consumer
      • 这里,React 组件也可以订阅到 Context 变化,这能让你在函数式组件中完成订阅 Context
      • 这里需要函数作为子元素(function as child)这种做法
      • 这个函数接收当前的 Context 值,返回一个 React 节点
  • 基本使用 ```javascript

// 1. 创建一个context对象 const UserContext = React.createContext({ nickName: ‘ryan’, level: 100 });

// 头部组件 function ProfileHeader(props) { return (

用户昵称:{props.nickName}


用户等级:{props.level}

) }

// 列表组件 function Profile(props) { return (

  • list1
  • list2
  • list3
  • list4

) }

// 最外层组件 class App extends React.Component { constructor(props) { super(props);

  1. this.state = {
  2. nickName: "ryan",
  3. level: "99"
  4. }

}

render() { return (

// 2. 因为ProfileHeader要共享数据,在App组件中使用.provider内置组建,必须要共享数据的组建 // 是被共享组件的子孙组件
) } }

ReactDOM.render(, document.getElementById(“App”)); ```