专栏首页小丞前端库React 入门学习(十六)-- 数据共享

React 入门学习(十六)-- 数据共享

📢 大家好,我是小丞同学,一名大二的前端爱好者 📢 这篇文章是学习 React-Redux 数据共享 的学习笔记 📢 非常感谢你的阅读,不对的地方欢迎指正 🙏 📢 愿你忠于自己,热爱生活

引言

在写完了基本的 Redux 案例之后,我们可以尝试一些更实战性的操作,比如我们可以试试多组件间的状态传递,相互之间的交互

如上动图所示,我们想要实现上面的案例,采用纯 React 来实现是比较困难的,我们需要很多层的数据交换才能实现,但是我们如果采用 Redux 来实现会变得非常简单

因为 Redux 打通了组件间的隔阂,我们可以自由的进行数据交换,所有存放在 store 中的数据都可以实现共享,那我们接下来看看如何实现的吧~

1. 编写 Person 组件

上面的 Count 组件,已经在前面几篇写过了,但是我没有记录详细的实现过程,只是做了一些小小的总结(我摸鱼了)

不管如何,我们先来实现一个 Person 组件吧

首先我们需要在 containers 文件夹下编写 Person 组件的容器组件

如何编写一个容器组件呢?(上一篇也讲过了)

首先我们需要编写 index.jsx 文件,在这个文件里面编写 Person 组件的 UI 组件,并使用 connect 函数将它包装,映射它的状态和方法

编写 UI 组件架构

<div>
    <h2>我是 Person 组件,上方组件求和为:{this.props.countAll}</h2>
    <input ref={c => this.nameNode = c} type="text" placeholder="输入名字" />
    <input ref={c => this.ageNode = c} type="text" placeholder="输入年龄" />
    <button onClick={this.addPerson}>添加</button>
    <ul>
        {
            this.props.persons.map((p) => {
                return <li key={p.id}> {p.name}--{p.age}</li>
            })
        }
    </ul>
</div>

我们可以看到这里采用了 ref 来获取到当前事件触发的节点,并通过 this.addPerson 的方式给按钮绑定了一个点击事件

编写点击事件回调

addPerson = () => {
    const name = this.nameNode.value
    const age = this.ageNode.value
    const personObj = { id: nanoid(), name, age }
    this.props.add(personObj)
    this.nameNode.value = ''
    this.ageNode.value = ''
}

在这里我们需要处理输入框中的数据,并且将这些数据用于创建一个 action 对象,传递给 store 进行状态的更新

在这里我们需要回顾的是,这里我们使用了一个 nanoid 库,这个库我们之前也有使用过

下载,引入,暴露
import { nanoid } from 'nanoid'

暴露的 nanoid 是一个函数,我们每一次调用时,都会返回一个不重复的数,用于确保 id 的唯一性,同时在后面的 map 遍历的过程中,我们将 id 作为了 key 值,这样也确保了 key 的唯一性,关于 key 的作用,可以看看 diffing 算法的文章

状态管理

在这里我们需要非常熟练的采用 this.props.add 的方式来更新状态

那么它是如何实现状态更新的呢?我们来看看

在我们调用 connect 函数时,我们第一次调用时传入的第二个参数,就是用于传递方法的,我们传递了一个 add 方法

export default connect(
    state => ({ persons: state.person, countAll: state.count }),//映射状态
    { add: createAddPersonAction }
)(Person);

它的原词是:mapDispatchToProps

我的理解是,传入的东西会被映射映射成 props 对象下的方法,这也是我们能够在 props 下访问到 add 方法的原因

对于这一块 connect ,我们必须要能够形成自己的理解,这里非常的重要,它实现了数据的交互,不至于一个组件,而是全部组件

我是如何理解的呢?

想象一个 store 仓库,在我们这个案例当中,Count 组件需要存放 count 值在 store 中,Person 组件需要存放新增用户对象在 store 中,我们要把这两个数据存放在一个对象当中。当某个组件需要使用 store 中的值时,可以通过 connect 中的两个参数来获取,例如这里我们需要使用到 Count 组件的值,可以通过 .count 来从 store 中取值。

也就是说,所有的值都存放在 store 当中,通过点运算符来获取,所有的操作 store 的方法都需要通过 action 来实现。当前组件需要使用的数据都需要在 connect 中暴露

2. 编写 reducer

首先,我们需要明确 reducer 的作用,它是用来干什么的?

根据操作类型来指定状态的更新

也就是说当我们点击了添加按钮后,会将输入框中的数据整合成一个对象,作为当前 action 对象的 data 传递给 reducer

我们可以看看我们编写的 action 文件,和我们想的一样

import { ADD_PERSON } from "../constant";
// 创建一个人的action 对象
export const createAddPersonAction = (personObj) => ({
  type: ADD_PERSON,
  data: personObj,
});

当 reducer 接收到 action 对象时,会对 type 进行判断

export default function personReducer(preState = initState, action) {
  const { type, data } = action;
  switch (type) {
    case ADD_PERSON:
      return [data,...preState]
    default:
      return preState
  }
}

一般都采用 switch 来编写

这里有个值得注意的地方是,这个 personReducer 函数是一个纯函数,什么是纯函数呢?这个是高阶函数部分的知识了,纯函数是一个不改变参数的函数,也就是说,传入的参数是不能被改变的。

为什么要提这个呢?在我们 return 时,有时候会想通过数组的 API 来在数组前面塞一个值,不也可以吗?

但是我们要采用 unshirt 方法,这个方法是会改变原数组的,也就是我们传入的参数会被改变,因此这样的方法是不可行的!

3. 打通数据共享

写到这里,或许已经写完了,但是有些细节还是需要注意一下

采用 Redux 来进行组件的数据交互真的挺方便。

我们可以在 Count 组件中引入 Person 组件存在 store 中的状态。

export default connect(state => ({ count: state.count, personNum: state.person.length }),
    {
       ...
    }
)(Count)

在这里我们将 store 中的 person 数组的长度暴露出来这样 Count 组件就可以直接通过 props 来使用了

同样的我们也可以在 Person 组件中使用 Count 组件的值

从而实现了我们的这个 Demo

4. 最终优化

  1. 利用对象的简写方法,将键名和键值同名,从而只写一个名即可
  2. 合并 reducer ,我们可以将多个 reducer文件 写在一个 index 文件当中,需要采用 combineReducers 来合并

5. 项目打包

执行 npm run build 命令,即可打包项目,打包完成后,会生成一个 build 文件,这个文件我们需要部署到服务器上才能运行

我们可以放在自己的服务器上即可

但是我遇到了一个问题

打包后的文件路径少了一个 . 导致文件无法找到,报错无法执行,我通过手动添加的方式解决了,不知道还有没有什么其他方法解决

也可以采用 npm i serve -g 安装,如何通过 serve ‘指定文件夹’ 来执行


非常感谢您的阅读,欢迎提出你的意见,有什么问题欢迎指出,谢谢!🎈

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 前端资源分享-只为更好前端

    阅读更多 本文在GitHub的地址GitHub Front-end-resources

    WEBING
  • 前端资源分享——只为更好前端

    一、团队组织 网站说明腾讯 AlloyTeam 团队腾讯Web前端团队,代表作品WebQQ,致力于前端技术的研究ISUX腾讯社交用户体验设计,简称ISUX,腾...

    wangxl
  • 前端资源、交流社区、技术博客等整理总汇

    最近看到这篇前端资源总汇的文章,整理的非常详细,于是搬过来,方便自己后期查阅,侵删。

    德顺
  • React 入门学习(十)-- React 路由

    在我们之前写的页面当中,用我们的惯用思维去思考的话,可能会需要写很多的页面,例如做一个 tab 栏,我们可能会想每个选项都要对应一个 HTML 文件,这样会很麻...

    小丞同学
  • React 入门学习(六)-- TodoList 案例

    TodoList 案例在前端学习中挺重要的,从原生 JavaScript 的增删查改,到现在 React 的组件通信,都是一个不错的案例,这篇文章主要记录,还原...

    小丞同学
  • React 入门学习(十七)-- React 扩展

    学到这里 React 已经学的差不多了,接下来就学习一些 React 扩展内容,可以帮助我们更好的开发和理解,这部分的知识还有很多的东西可以探寻,比如:网红 R...

    小丞同学
  • React 入门学习(十一)-- React 路由传参

    在上一篇中,我们学习了 React 中使用路由技术,以及如何使用 MyNavLink 去优化使用路由时的代码冗余的情况。

    小丞同学
  • React 入门学习(十二)-- React 路由跳转

    默认情况下,开启的是 push 模式,也就是说,每次点击跳转,都会向栈中压入一个新的地址,在点击返回时,可以返回到上一个打开的地址,

    小丞同学
  • React 入门学习(十五)-- React-Redux 基本使用

    在前面我们学习了 Redux ,我们在写案例的时候,也发现了它存在着一些问题,例如组件无法状态无法公用,每一个状态组件都需要通过订阅来监视,状态更新会影响到全部...

    小丞同学
  • React学习(六)-React中组件的数据-state

    一个组件最终渲染的数据结果,除了prop还有state,state代表的是当前组件的内部状态,你可以把组件看成一个'状态机",它是能够随着时间变化的数据,更多的...

    itclanCoder
  • 《HelloGitHub》第 43 期

    这是一个面向编程新手、热爱编程、对开源社区感兴趣 人群的月刊,月刊的内容包括:各种编程语言的项目、让生活变得更美好的工具、书籍、学习笔记、教程等,这些开源项目大...

    HelloGitHub
  • web前端开发如何入门提高?

    想要成为web前端工程师应该如何开始学习呢?学完HTML以及css之后应该从哪些方面学习呢?入门web前端开发之后又该如何提高自己的前端开发技术呢?如果是自学,...

    企鹅号小编
  • 业界 | GitHub 年度报告盘点:开发者增至 3100 万,开源项目达 9600 万

    AI 科技评论按:日前,GitHub 发布了一年一度的「Octoverse」报告,其中列出了一些年度(2017 年 10 月 1 日-2018 年 9 月 30...

    AI科技评论
  • 前端大牛们都学过哪些东西?

    单纯的技术层面也就是上述的那些个东西。如果某个同学都学会了上面的那些东西,是不是就能完全的胜任前端开发工作呢?

    web前端教室
  • 沙龙报名 | 无线技术工程化,4月21日上海

    携程技术
  • 前端学习路线指南

    这是你最初必须掌握的 是网站的构建元素 没得选! 随着你前端的学习进程,熟练掌握 HTML/CSS简单易学

    达达前端
  • React 入门学习(十四)-- redux 基本使用

    在了解了 Antd 组件库之后,我们现在开始学习了 Redux ,在我们之前写的案例当中,例如:todolist 案例,GitHub 搜索案例当中,我们对于状态...

    小丞同学
  • Nodejs学习笔记(十六)--- Pomelo介绍&入门

    前言&介绍 Pomelo:一个快速、可扩展、Node.js分布式游戏服务器框架 从三四年前接触Node.js开始就接触到了Pomelo,从Pomelo最...

    Porschev
  • 【实战】1096- React 中后台系统多页签实现

    本项目是我现在所在部门的项目,是一个企业级中后台管理系统,包括系统管理、角色权限体系、基于 Activiti 的工作流引擎等很多开箱即用的功能。项目包括前后端,...

    pingan8787

扫码关注云+社区

领取腾讯云代金券