1. 组件通讯-概念

了解组件通讯的意义
大致步骤:

  • 知道组件的特点
  • 知道组件通讯意义

具体内容:

  1. 组件的特点
    • 组件是独立且封闭的单元,默认情况下,只能使用组件自己的数据
    • 在组件化过程中,通常会将一个完整的功能拆分成多个组件,以更好的完成整个应用的功能
  2. 知道组件通讯意义
    • 而在这个过程中,多个组件之间不可避免的要共享某些数据
    • 为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通
    • 这个过程就是组件通讯

总结:

  • 组件状态是独立的,组件化之后涉及状态同步,需要进行组件通讯

    2. 组件通讯-props 基本使用

    能够通过 props 传递数据和接收数据
    大致步骤:

  • 传递数据和接收数据的过程

  • 函数组件使用 props
  • 类组件使用 props

具体内容:

  1. 传递数据和接收数据的过程
    • 使用组件的时候通过属性绑定数据,在组件内部通过 props 获取即可。
  2. 函数组件使用 props

// 使用组件

// 定义组件 props包含{name:’jack’,age:’20’}
function Hello(props) {
return

接收到数据:{props.name}
;
}

  1. 类组件使用 props

// 使用组件

// 定义组件 props包含{name:’jack’,age:’20’}
class Hello extends Component {
render() {
return

接收到的数据:{this.props.age}
;
}
}
总结:

  • props 是实现组件通讯的关键,它通过使用组件绑定属性,组件内部使用 props 来传值。

    3. 组件通讯-props 注意事项

    知道 props 是单项数据流只读,但是可以传递任意数据。
    大致步骤:

  • 知道什么是单向数据流

  • 知道 props 可以传递什么数据

具体内容:

  1. 知道什么是单向数据流?
    • 单向数据流,是从上到下的,自顶而下的,数据流。
    • 好比:河流,瀑布,只能从上往下流动,上游污染下游受影响,但是下游不能影响上游。
    • 父组件传递数据给子组件,父组件更新数据子组件自动接收更新后数据,当是子组件是不能修改数据的。
  2. props 可以传递什么数据?任意
    • 字符串
    • 数字
    • 布尔
    • 数组
    • 对象
    • 函数
    • JSX (插槽)

总结:

  • props 传递数据是单向的,可以传递任意格式的数据。

    4. 组件通讯-父传子方式

    通过 props 将父组件的数据传递给子组件
    大致步骤:

  • 父组件提供要传递的 state 数据

  • 给子组件标签添加属性,值为 state 中的数据
  • 子组件中通过 props 接收父组件中传递的数据

具体代码:

  1. 父组件提供要传递的 state 数据

class Parent extends React.Component {
state = {
money: 10000,
};
render() {
return (


父组件:{this.state.money}



);
}
}

  1. 给子组件标签添加属性,值为 state 中的数据

class Parent extends React.Component {
state = {
money: 10000
}
render() {
return (


父组件:{this.state.money}


+

)
}
}

  1. 子组件中通过 props 接收父组件中传递的数据

function Child(props) {
return (


子组件:{props.money}



);
}
总结:

  • 父组件声明state,在子组件标签通过属性绑定,在子组件中通过props使用。

    5. 组件通讯-父传子练习

    通过提供的素材,利用父传子知识,完成以下练习
    界面参考:
    image.png
    配套素材:
  1. jsx 结构

今日要闻



坚定不移走中国特色社会主义法治道路



新华社
774点赞



2021年度法治人物——倪伯苍



央视网
774点赞



岁末年终 愿这份“温良”伴你乘风破浪



央视新闻客户端
248点赞


  1. 组件样式

.parent {
width: 500px;
margin: 0 auto;
}
.parent h1 {
font-weight: normal;
margin: 0;
padding: 20px 0;
}
.child {
width: 100%;
box-sizing: border-box;
margin-bottom: 10px;
}

.child h3 {
font-weight: normal;
color: #333;
margin: 0;
padding: 10px 0;
}
.child .detail {
font-size: 14px;
color: #999;
}
.child .detail span {
margin-right: 10px;
}

  1. 实现思路
    1. 新建样式 src/index.css 准备样式,导入到入口文件
    2. 新建 Parent 组件,渲染准备的 parent 的结构,导入到入口文件渲染该组件
    3. 新建 Child 组件,渲染准备的渲染 child 的结构,导入到 Parent 组件使用
    4. Parent 组件,参考界面定义状态,通过状态遍历 Child 组件传值,Child 组件根据 props 渲染。

      6. 组件通讯-子传父方式

      通过 props 将子组件的数据传递给父组件
      大致步骤:
  • 父组件提供回调函数,通过 props 传递给子组件
  • 子组件调用 props 中的回调函数,函数可传参
  • 父组件函数的参数就是子组件传递的数据

具体代码:

  1. 父组件

class Parent extends React.Component {
state = {
money: 10000,
};
// 回调函数
buyPhone = (price) => {
this.setState({
money: this.state.money - price,
});
};
render() {
const { money } = this.state;
return (


父组件:{money}




);
}
}

  1. 子组件

const Child = (props) => {
const handleClick = () => {
// 子组件调用父组件传递过来的回调函数
props.buyPhone(5000);
};
return (


子组件:{props.money}




);
};
总结:

  • 子组件如何传递数据给父组件?触发父组件传递的回调函数传入数据
  • 父组件如何接收子组件的数据?回调函数的参数是子组件传递的数据
  • 父组件数据更新后,传递给子组件的数据是否更新?自动更新

    7. 组件通讯-子传父练习

    通过提供的素材,利用子传父知识,完成点赞功能
    界面参考:
    image.png
    配套素材:
  1. jsx 结构

坚定不移走中国特色社会主义法治道路



新华社
774点赞
+ 点赞+1

  1. 新增样式

.child .detail span:last-child {
cursor: pointer;
color: burlywood;
user-select: none;
}

  1. 实现思路
    1. 子组件绑定点击事件指定处理函数
    2. 在处理函数中调用父组件传递的回调函数
    3. 给回调函数传入评论 ID 和点赞后的数量
    4. 父组件在回调函数中更新数据

      8. 组件通讯-兄弟组件通讯

      通过状态提升思想完成兄弟组件数据通讯
      大致步骤:
  • 状态提升思想是什么?
  • 演示通过状态提升完成兄弟组件通讯。

具体内容:

  1. 状态提升思想是什么?
    • 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态和修改状态的方法
    • 需要通讯的组件通过 props 接收状态和函数即可image.png
  2. 参考代码index.js

import React, { Component } from ‘react’;
import ReactDOM from ‘react-dom’;

// 导入两个子组件
import Jack from ‘./Jack’;
import Rose from ‘./Rose’;

// App 是父组件
class App extends Component {
// 1. 状态提升到父组件
state = {
msg: ‘’,
};

changeMsg = (msg) => {
this.setState({ msg });
};

render() {
return (


我是App组件


{/ 兄弟组件 1 /}

{/ 兄弟组件 2 /}


);
}
}

// 渲染组件
ReactDOM.render(, document.getElementById(‘root’));
Jack.js
import React, { Component } from ‘react’;

export default class Jack extends Component {
say = () => {
// 修改数据
this.props.changeMsg(‘you jump i look’);
};
render() {
return (

我是Jack组件




);
}
}
Rose.jsx
import React, { Component } from ‘react’;

export default class Rose extends Component {
render() {
return (

我是Rose组件-{this.props.msg}



);
}
}

9. 组件通讯-context 跨级组件通讯

掌握使用 context 实现跨级组件通讯
大致步骤:

  • 什么是跨级组件通讯?
  • context 怎么去理解?
  • 演示使用 context 完成跨级组件通讯。

具体内容:

  1. 什么是跨级组件通讯?
    • 组件间相隔多层,理解成叔侄,甚至更远的亲戚。
  2. context 怎么去理解
    • 术语:上下文
    • 理解:一个范围,只要在这个范围内,就可以跨级组件通讯。(不需要 props 层层传递)

image.png

  1. 演示使用 context 完成跨级组件通讯

    根组件:10000


父组件:


子组件:10000 修改money

总结:

  • 使用creatContext()创建一个上下文对象,包含:Provider Consumer 组件。
  • 使用 Provider 包裹组件,value 属性注入状态,函数,被包裹组件下的任何组件可以使用。
  • 使用 Consumer 消费 Provider 提供的数据和函数,语法{value=>使用数据和函数}

    10. 评论案例-组件拆分

    能够按照功能结构拆分组件组件
    大致步骤:

  • 在 components 下分别创建 CommentInput CommentHead CommentList 三个组件

  • 在 index.js 创建 App 组件,组织上面三个组件
  • 准备 index.css 支持样式,导入到 index.js 即可

具体代码:

评论

0/100
发表评论

热门评论(5)默认时间

  • 清风徐来image.png2012-12-12删除这里是评论的内容!!!这里是评论的内容!!!这里是评论的内容!!!
  • 清风徐来2012-12-12这里是评论的内容!!!这里是评论的内容!!!这里是评论的内容!!!

字体图标:在 index.html 头部引入 https://at.alicdn.com/t/font_2998849_vtlo0vj7ryi.css
总结:

  • 按照 UI 结构进行组件拆分

    11. 评论案例-基础渲染

    根据默认状态数据渲染列表
    大致步骤:

  • 在 App 组件准备状态数据,传递给 CommentList 组件

  • 进行渲染,需要区分会员,控制删除按钮,展示收藏状态,格式化时间

具体代码:

  1. 在 App 组件准备状态数据,传递给 CommentList 组件

state = {
// 用户信息
user: {
name: ‘清风徐来’,
avatar: ‘https://static.youku.com/lvip/img/avatar/310/6.png‘,
vip: true,
},
// 评论列表
comments: [
{
id: 100,
name: ‘__RichMan’,
avatar: ‘https://r1.ykimg.com/051000005BB36AF28B6EE4050F0E3BA6‘,
content:
‘这阵容我喜欢😍靳东&闫妮,就这俩名字,我就知道是良心剧集…锁了🔒’,
time: new Date(‘2021/10/12 10:10:23’),
vip: true,
collect: false,
},
{
id: 101,
name: ‘糖蜜甜筒颖’,
avatar:
https://image.9xsecndns.cn/image/uicon/712b2bbec5b58d6066aff202c9402abc3370674052733b.jpg‘,
content:
‘突围神仙阵容 人民的名义第三部来了 靳东陈晓闫妮秦岚等众多优秀演员实力派 守护人民的财产 再现国家企业发展历程’,
time: new Date(‘2021/09/23 15:12:44’),
vip: false,
collect: true,
},
{
id: 102,
name: ‘清风徐来’,
avatar: ‘https://static.youku.com/lvip/img/avatar/310/6.png‘,
content:
‘第一集看的有点费力,投入不了,闫妮不太适合啊,职场的人哪有那么多表情,一点职场的感觉都没有’,
time: new Date(‘2021/07/01 00:30:51’),
vip: true,
collect: false,
},
],
};
render() {
+ const {user, comments} = this.state
return (


{/ 输入框组件 /}

{/ 标题排序组件 /}

{/ 列表组件 /}
+

)
}

  1. 进行渲染,需要区分会员,控制删除按钮,展示收藏状态,格式化时间
    • 格式化时间需要安装 dayjs

import dayjs from ‘dayjs’;
const CommentList = (props) => {
// 格式时间
const formatTime = (time) => dayjs(time).format(‘YYYY/MM/DD HH:mm:ss’);
return (


    {props.comments.map((item) => (

  • className=”avatar”
    style={{ backgroundImage: url(${item.avatar}) }}
    >


    {item.name}
    {item.vip && (
    alt=””
    src={
    https://gw.alicdn.com/tfs/TB1c5JFbGSs3KVjSZPiXXcsiVXa-48-48.png
    }
    />
    )}



    {formatTime(item.time)}
    className={iconfont icon-collect${item.collect ? '-sel' : ''}}
    >
    {item.name === props.user.name && (
    删除
    )}


    {item.content}




  • ))}

);
};

export default CommentList;
总结:

  • 状态数据都在 App 组件,其他组件都有共享的
  • 格式化时间使用 dayjs 定义一个函数转换,复杂类名的控制大家可以尝试 classnames。

    12. 评论案例-排序功能

    根据选择的排序方式更新列表
    大致步骤:

  • 在App组件定义当前排序方式数据,和修改数据的函数

  • 传入 CommentHead 组件,点击排序的时候修改排序方式数据
  • 在 CommentList 组件,根据列表数据和排序方式得到新的列表数据,渲染即可

具体代码:

  1. 在App组件定义当前排序方式数据,和修改数据的函数

state = {
// …省略
+ active: ‘default’
}
+ setActive = value => {
+ // 改变过排序修改状态
+ if (value !== this.state.active) {
+ this.setState({active:value})
+ }
+ }

  1. 传入 CommentHead 组件,点击排序的时候修改排序方式数据App组件

render() {
+ const {user, comments, active} = this.state
return (


{/ 输入框组件 /}

{/ 标题排序组件 /}
+
CommentHead组件
const CommentHead = (props) => {
return (


热门评论({props.comments.length})
onClick={() => props.setActive(‘default’)}
className={props.active === ‘default’ ? ‘active’ : ‘’}
>
默认

onClick={() => props.setActive(‘time’)}
className={props.active === ‘time’ ? ‘active’ : ‘’}
>
时间


);
};

export default CommentHead;

  1. 在 CommentList 组件,根据列表数据和排序方式得到新的列表数据,渲染即可App组件

{/ 列表组件 /}
+
CommentList组件
import dayjs from ‘dayjs’;
const CommentList = (props) => {
// 格式时间
const formatTime = (time) => dayjs(time).format(‘YYYY/MM/DD HH:mm:ss’);
+ // 得到排序后的数组
+ const newList = […props.comments];
+ if (props.active === ‘default’) {
+ newList.sort((p, c) => c.id - p.id);
+ }
+ if (props.active === ‘time’) {
+ newList.sort((p, c) => c.time - p.time);
+ }
return (


    + {newList.map((item) => (

  • 总结:

    • 先定义 active 数据 setActive 函数
    • 点击排序修改 active
    • 根据 active 和 列表数据 进行排序

      13. 评论案例-发表评论

      通过子传父完成发表评论功能
      大致步骤:

    • 输入框变为受控组件,现在输入字数 100

    • 点击发表评论,将内容传递给 App 组件,在 App 自己完成追加评论

    具体代码:

    1. 输入框变为受控组件,现在输入字数 100

    CommentInput组件
    import React, { Component } from ‘react’;

    export default class CommentInput extends Component {
    state = {
    content: ‘’,
    };
    setContent = (e) => {
    const value = e.target.value.trim();
    if (value.length <= 100) {
    this.setState({ content: value });
    }
    };
    render() {
    return (
    <>

    评论



    value={this.state.content}
    onChange={this.setContent}
    placeholder=”爱发评论的人,运气都很棒”
    >

    {this.state.content.length}/100

    发表评论



    </>
    );
    }
    }

    1. 点击发表评论,将内容传递给 App 组件,在 App 自己完成追加评论CommentInput组件
    • handleClick = () => {
      + this.props.addComment(this.state.content)
      + this.setState({content: ‘’})
      + }
      render() {
      return (
      <>

      评论



      value={this.state.content}
      onChange={this.setContent}
      placeholder=”爱发评论的人,运气都很棒”
      >

      {this.state.content.length}/100

      +
      发表评论



      </>
      );
      }
      APP组件
      // 发表评论
      addComment = (content) => {
      // 递增ID
      const id = Math.max(…this.state.comments.map((item) => item.id)) + 1;
      const newComment = {
      …this.state.user,
      id,
      content,
      time: new Date(),
      collect: false,
      };
      this.setState({
      comments: […this.state.comments, newComment],
      });
      };
      {/ 输入框组件 /}
      +
      总结:
    • CommentInput 组件把评论内容传递给 App 组件,然后组织完整的评论对象添加到数组

      14. 评论案例-删除评论

      通过子传父完成删除评论功能
      大致步骤:

    • App 组件提供删除的函数,根据 ID 删除数据,并且传递给 CommentList 组件

    • CommentList 组件绑定删除按钮点击事件,调用props中的删除函数传入 ID

    具体代码:

    1. App 组件提供删除的函数,根据 ID 删除数据,并且传递给 CommentList 组件

    // 删除评论
    delComment = (id) => {
    this.setState({
    comments: this.state.comments.filter((item) => item.id !== id),
    });
    };
    {/ 列表组件 /}
    user={user}
    comments={comments}
    active={active}
    + delComment={this.delComment}
    />

    1. CommentList 组件绑定删除按钮点击事件,调用props中的删除函数传入 ID

    props.delComment(item.id)} className=”del”>
    删除

    总结:

    • 通过子传父把 id 给父组件去删除数据

      15. 评论案例-收藏评论

      通过子传父完成收藏评论功能
      大致步骤:

    • App 组件提供收藏函数,根据 ID 进行收藏&取消收藏,并且传递给 CommentList 组件

    • CommentList 组件绑定收藏按钮点击事件,调用props中的收藏函数传入 ID

    具体代码:

    1. App 组件提供收藏函数,根据 ID 进行收藏&取消收藏,并且传递给 CommentList 组件

    // 收藏评论&取消收藏
    collectComment = (id) => {
    this.setState({
    comments: this.state.comments.map((item) => {
    if (item.id === id) {
    return { …item, collect: !item.collect };
    } else {
    return item;
    }
    }),
    });
    };
    {/ 列表组件 /}
    user={user}
    comments={comments}
    active={active}
    delComment={this.delComment}
    + collectComment={this.collectComment}
    />

    1. CommentList 组件绑定收藏按钮点击事件,调用props中的收藏函数传入 ID

    onClick={() => props.collectComment(item.id)}
    className={iconfont icon-collect${item.collect ? '-sel' : ''}}
    >
    总结:

    • 通过子传父把 id 给父组件去修改数据

      16. props-children 属性

      掌握 props 中 children 属性的用法
      大致步骤:

    • props 中 children 属性代表什么?

    • props 中 children 属性的使用
    • 使用 props 中 children 属性 封装 NavBar 组件

    具体内容:

    1. props 中 children 属性代表什么?
      • 组件标签的子节点(标签之间的内容),可以是任意值(文本,React 元素,组件,函数)
    2. props 中 children 属性的使用

    // 定义组件
    const Hello = (props) => {
    return

    该组件的子节点:{props.children}
    ;
    };
    // 使用组件
    我是子节点;

    1. 使用 props 中 children 属性 封装 NavBar 组件

      < 文章详情

      < 文章列表

      < 我的点赞

    17. 今日总结

    1. 组件状态特点?
      • 相互独立的,互不影响。
    2. props 如何使用?
      • 给组件标签上绑定属性,组件中 props 去使用。
    3. props 注意些什么?
      • 传递的数据是单向的不能改,可以传递任意数据。
    4. 父传子如何实现?
      • 父组件定义数据,给子组件标签绑定,子组件通过 props 获取
    5. 子传父如何实现?
      • 父组件提供函数,给子组件标签绑定,子组件通过 props 调用且传参
    6. 兄弟组件通讯如何实现?
      • 通过状态提升思想,数据和修改数据放在最近的父组件,传给兄弟组件使用和修改数据
    7. 跨级组件通讯如何实现?
      • 通过createContext对象,提供注入数据的组件Provider,和消费数据的组件Consumer
    8. porps 的 children 作用?
      • 获取组件标签之前的节点内容,任何类型。
    • 案例-优酷评论

      评论

      0/100
      发表评论

      热门评论(3)默认时间

    • 清风徐来image.png2021/07/01 00:30:51删除第一集看的有点费力,投入不了,闫妮不太适合啊,职场的人哪有那么多表情,一点职场的感觉都没有

    • 糖蜜甜筒颖2021/09/23 15:12:44突围神仙阵容 人民的名义第三部来了 靳东陈晓闫妮秦岚等众多优秀演员实力派 守护人民的财产 再现国家企业发展历程
    • __RichManimage.png2021/10/12 10:10:23这阵容我喜欢😍靳东&闫妮,就这俩名字,我就知道是良心剧集…锁了🔒

    • 练习-新闻列表

      今日要闻

      坚定不移走中国特色社会主义法治道路

      新华社11赞点赞+1

      2021年度法治人物——倪伯苍

      央视网56赞点赞+1

      岁末年终 愿这份“温良”伴你乘风破浪

      央视新闻客户端345赞