ed病毒是什么| 整形什么医院好| 牙痛吃什么药好| semir是什么牌子| ipv是什么疫苗| lga肾病是什么意思| 花花世界不必当真是什么歌| 人体由什么组成| 结节是什么意思| 咳出痰带血是什么原因| 黄芪配升麻有什么作用| 脑供血不足有什么症状| 娇妻是什么意思| 嗣读什么| 什么什么若狂| 煞南是什么意思| wlp是什么意思| 十二指肠霜斑样溃疡是什么意思| 99是什么意思| hennessy是什么酒价格多少| 黄酒有什么功效与作用| 示字旁与什么有关| 邓超的老婆叫什么名字| 睡衣什么面料最好| 股藓要用什么药膏效果最好| 腿肿吃什么药消肿最快最有效| 骨头咔咔响是什么原因| 业力是什么意思| 日成念什么| 麻小是什么意思| 寒咳吃什么药| 酉时五行属什么| 脾虚吃什么水果| 淋巴系统由什么组成| ia是什么意思| 白芍的功效与作用是什么| 打嗝多是什么原因| 痛经吃什么食物| 龋齿是什么原因造成的| 野兽之王是什么动物| 胃痉挛吃什么药| 女人梦见自己掉牙齿是什么征兆| 丙氨酸氨基转移酶偏高吃什么药| 白细胞30是什么意思| 羊肉汤放什么调料| 孕早期头疼是什么原因| 昔字五行属什么| bdsm什么意思| 手淫过度有什么症状| 什么情况下会缺钾| d2聚体高是什么原因| 孕妇梦见鱼是什么意思| 机位是什么意思| 降血糖的草都有什么草| 39是什么意思| 清创手术是什么意思| 低压高吃什么中成药| 甲功是什么意思| 什么是富贵包| 基因突变发生在什么时期| 济南为什么叫泉城| 下肢静脉曲张是什么原因引起的| 脂肪瘤长什么样| 钟是什么意思| 长痱子是什么原因| 鸡精和鸡粉有什么区别| 排酸肉是什么意思| 尿无力是什么原因| 做b超挂什么科| 黑蚂蚁泡酒有什么功效| 爸爸的姐姐叫什么| 猕猴桃是什么季节的水果| 全科医生是什么意思| 头晕目赤是什么意思| 乐色是什么意思| 取笑是什么意思| 慢是什么意思| 酒精过敏是什么症状| 范仲淹号什么| 鼠加句念什么| 后厨打荷是干什么的| 钙片什么时候吃最好吸收| 窥见是什么意思| 咳嗽挂什么科室| 宇宙之外是什么| 丝瓜不可以和什么一起吃| 慢性阑尾炎吃什么药好| 东方不败练的什么武功| 87岁属什么生肖| 双脚浮肿是什么原因| 猪蹄炖什么| 什么是形声字| 多米诺骨牌是什么意思| 脆皮鸭什么意思| 6.12是什么星座| hc是胎儿的什么| 属牛的五行属性是什么| 农历五月二十是什么星座| 头昏脑胀吃什么药| 二尖瓣关闭不全是什么意思| 义五行属什么| 红薯什么时候掐尖| kailas是什么牌子| 备孕叶酸什么时候吃最好| 吃什么能消除子宫肌瘤| 狗狗喝什么水| 紫玫瑰花语是什么意思| roma是什么牌子| 犯病是什么意思| 沙茶酱是什么做的| 小孩记忆力差是什么原因| 筋膜炎用什么药好| 微信上面有个耳朵是什么意思| 冬虫夏草有什么用| 芦荟有什么功效与作用| 18是什么意思| 吃什么补气血| 哈尔滨机场叫什么名字| 三高挂号挂什么科| 性瘾是什么意思| 什么是引产| 铁是补什么的| 外阴白斑是什么原因| 小孩爱吃手指头是什么原因| 藏干是什么意思| 吃什么补内膜最快| 白色舌苔厚是什么原因| 老年斑用什么药膏可以去掉| hpv弱阳性是什么意思| 沉香有什么作用与功效| 羽毛球鞋什么牌子好| 豆包是什么| 菽是什么意思| 今年66岁属什么生肖的| 胎心不稳定是什么原因| 糖尿病人吃什么水果最好| 鱼扣是鱼的什么部位| 喷字去掉口念什么| 阳虚是什么症状| 经验是什么意思| 老年痴呆吃什么药| 沉香有什么作用| 中位数是什么意思| 感冒能吃什么水果| 小孩脚抽筋是什么原因引起的| 肚脐周围痛是什么原因| 瘫痪是什么意思| 青瓜和黄瓜有什么区别| 牙齿发黄是什么原因导致的| 有所作为的意思是什么| 吃苹果有什么好处和功效| 什么时候可以考研| 脸上掉皮是什么原因| 为什么刚吃完饭不能洗澡| agc什么意思| 迷瞪是什么意思| 上窄下宽的脸型适合什么发型| 脂肪肝吃什么食物| 耳朵痒用什么药最有效| 什么的跳| 奶茶和奶绿有什么区别| 蛇和什么属相最配| 什么话是世界通用的| 一视同仁什么意思| 12五行属什么| 减肥吃什么| 尿多吃什么药| 鼻炎用什么药效果好| 农历今天什么日子| 扁桃体发炎吃什么食物好| 69年属鸡是什么命| 血小板过低有什么危害| 胃寒能吃什么水果| 小暑是什么意思啊| 独角戏什么意思| 梦见自己骑马是什么意思| 天上的彩虹像什么| 胃泌素释放肽前体高是什么原因| 吃什么升血压最快| 头疼挂什么科室| 明心见性什么意思| 丹凤朝阳什么意思| 吃优甲乐不能吃什么| 车厘子与樱桃有什么区别| 眼睛痒用什么滴眼液| 什么值得买官网| reed是什么意思| 子不孝父之过下一句是什么| 什么时候抓知了猴| 清道夫吃什么| 615是什么星座| 清远车牌是粤什么| 掉发挂什么科| 睾丸疼痛什么原因| 不昧因果是什么意思| 吃维生素e有什么好处| 的字五行属什么| 耸是什么意思| 什么肉不含嘌呤| 吃什么补气血最快最好| 没有美瞳护理液用什么代替| 什么是管制| 做梦梦到鬼是什么意思| 上面一个日下面一个立是什么字| 株连九族是什么意思| 五谷有什么| 凹儿念什么| 早泄是什么症状| 什么的窟窿| 乙肝小二阳是什么意思| 胃酸过多是什么原因造成的| 属马的跟什么属相最配| 十一月二十九是什么星座| 汉坦病毒是什么病| 空调买什么牌子好| 氢氧化钙是什么东西| 什么油适合油炸| 两面性是什么意思| nasa是什么意思| 619是什么意思| 什么样的乌云| 头发粗硬是什么原因| 什么吹风机好用| 白醋和小苏打一起用起什么效果| 一个三点水一个及念什么| 豆芽不能和什么一起吃| 12.18是什么星座| 协调什么意思| 什么炖鸡汤好喝又营养| 什么样的人不能吃海参| 睡眠不好用什么泡脚| 霉菌阴道炎用什么药| 转氨酶偏低是什么原因| 怀孕的最佳时间是什么时候| 什么鞋油好用| 69什么意思| 318什么意思| 为什么会静脉曲张| 无创低风险是什么意思| 三七甘一是什么意思| 吃什么提高免疫力最好最快| 尿少是什么原因| 两胸之间是什么部位| 耍无赖是什么意思| 水洗棉是什么面料| 有何贵干是什么意思| 惠五行属什么| 口若悬河是指什么生肖| 有没有什么| 梦见自己离婚是什么预兆| 气管痉挛是什么症状| 银黑了用什么可以洗白| 打喷嚏是什么原因引起的| 梦见吃酒席是什么意思| 奎宁现在叫什么药| 吴亦凡什么学历| 肺寒吃什么药| 电解质什么意思| 女性什么时候最容易怀孕| 同房是什么| 什么牌子的蛋白质粉比较好| 范仲淹世称什么| 虎皮鹦鹉吃什么| 海胆是什么东西| 百度
Skip to content

聊城:全市社科优秀奖申报工作启动

百度 老人唠叨有原因多穿点,外边冷,多吃点,别饿着,怎么我说什么你都不听,我之前在单位的时候……这些千篇一律的话,任你耳朵听出了茧子,老人却每天雷打不动地唠叨,有用的没用的从早说到晚。

这里需要再强调一下:Redux 和 React 之间没有关系。Redux 支持 React、Angular、Ember、jQuery 甚至纯 JavaScript。

尽管如此,Redux 还是和 ReactDeku 这类库搭配起来用最好,因为这类库允许你以 state 函数的形式来描述界面,Redux 通过 action 的形式来发起 state 变化。

下面使用 React 来开发一个 todo 任务管理应用。

安装 React Redux ?

Redux 默认并不包含 React 绑定库,需要单独安装。

npm install --save react-redux

如果你不使用 npm,你也可以从 unpkg 获取最新的 UMD 包(包括开发环境包生产环境包)。如果你用 <script> 标签的方式引入 UMD 包,那么它会在全局抛出window.ReactRedux对象。

容器组件(Smart/Container Components)和展示组件(Dumb/Presentational Components) ?

Redux 的 React 绑定库是基于 容器组件和展示组件相分离 的开发思想。所以建议先读完这篇文章再回来继续学习。这个思想非常重要。

已经读完了?那让我们再总结一下不同点:

展示组件容器组件
作用描述如何展现(骨架、样式)描述如何运行(数据获取、状态更新)
直接使用 Redux
数据来源props监听 Redux state
数据修改从 props 调用回调函数向 Redux 派发 actions
调用方式手动通常由 React Redux 生成

大部分的组件都应该是展示型的,但一般需要少数的几个容器组件把它们和 Redux store 连接起来。这和下面的设计简介并不意味着容器组件必须位于组件树的最顶层。如果一个容器组件变得太复杂(例如,它有大量的嵌套组件以及传递数不尽的回调函数),那么在组件树中引入另一个容器,就像FAQ中提到的那样

技术上讲你可以直接使用 store.subscribe() 来编写容器组件。但不建议这么做的原因是无法使用 React Redux 带来的性能优化。也因此,不要手写容器组件,而使用 React Redux 的 connect() 方法来生成,后面会详细介绍。

设计组件层次结构 ?

还记得当初如何 设计 state 根对象的结构 吗?现在就要定义与它匹配的界面的层次结构。其实这不是 Redux 相关的工作,React 开发思想在这方面解释的非常棒。

我们的概要设计很简单。我们想要显示一个 todo 项的列表。一个 todo 项被点击后,会增加一条删除线并标记 completed。我们会显示用户新增一个 todo 字段。在 footer 里显示一个可切换的显示全部/只显示 completed 的/只显示 incompleted 的 todos。

展示组件 ?

以下的这些组件(和它们的 props )就是从这个设计里来的:

  • TodoList 用于显示 todos 列表。
    • todos: Array{ text, completed } 形式显示的 todo 项数组。
    • onTodoClick(index: number) 当 todo 项被点击时调用的回调函数。
  • Todo 一个 todo 项。
    • text: string 显示的文本内容。
    • completed: boolean todo 项是否显示删除线。
    • onClick() 当 todo 项被点击时调用的回调函数。
  • Link 带有 callback 回调功能的链接
    • onClick() 当点击链接时会触发
  • Footer 一个允许用户改变可见 todo 过滤器的组件。
  • App 根组件,渲染余下的所有内容。

这些组件只定义外观并不关心数据来源和如何改变。传入什么就渲染什么。如果你把代码从 Redux 迁移到别的架构,这些组件可以不做任何改动直接使用。它们并不依赖于 Redux。

容器组件 ?

还需要一些容器组件来把展示组件连接到 Redux。例如,展示型的 TodoList 组件需要一个类似 VisibleTodoList 的容器来监听 Redux store 变化并处理如何过滤出要显示的数据。为了实现状态过滤,需要实现 FilterLink 的容器组件来渲染 Link 并在点击时触发对应的 action:

  • VisibleTodoList 根据当前显示的状态来对 todo 列表进行过滤,并渲染 TodoList
  • FilterLink 得到当前过滤器并渲染 Link
    • filter: string 就是当前过滤的状态

其它组件 ?

有时很难分清到底该使用容器组件还是展示组件。例如,有时表单和函数严重耦合在一起,如这个小的组件:

  • AddTodo 含有“Add”按钮的输入框

技术上讲可以把它分成两个组件,但一开始就这么做有点早。在一些非常小的组件里混用容器和展示是可以的。当业务变复杂后,如何拆分就很明显了。所以现在就使用混合型的吧。

组件编码 ?

终于开始开发组件了!先做展示组件,这样可以先不考虑 Redux。

实现展示组件 ?

它们只是普通的 React 组件,所以不会详细解释。我们会使用函数式无状态组件除非需要本地 state 或生命周期函数的场景。这并不是说展示组件必须是函数 -- 只是因为这样做容易些。如果你需要使用本地 state,生命周期方法,或者性能优化,可以将它们转成 class。

components/Todo.js ?

js
import React from "react";
import PropTypes from "prop-types";

const Todo = ({ onClick, completed, text }) => (
  <li
    onClick={onClick}
    style={{
      textDecoration: completed ? "line-through" : "none",
    }}
  >
    {text}
  </li>
);

Todo.propTypes = {
  onClick: PropTypes.func.isRequired,
  completed: PropTypes.bool.isRequired,
  text: PropTypes.string.isRequired,
};

export default Todo;

components/TodoList.js ?

js
import React from "react";
import PropTypes from "prop-types";
import Todo from "./Todo";

const TodoList = ({ todos, onTodoClick }) => (
  <ul>
    {todos.map((todo, index) => (
      <Todo key={index} {...todo} onClick={() => onTodoClick(index)} />
    ))}
  </ul>
);

TodoList.propTypes = {
  todos: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.number.isRequired,
      completed: PropTypes.bool.isRequired,
      text: PropTypes.string.isRequired,
    }).isRequired
  ).isRequired,
  onTodoClick: PropTypes.func.isRequired,
};

export default TodoList;
js
import React from "react";
import PropTypes from "prop-types";

const Link = ({ active, children, onClick }) => {
  if (active) {
    return <span>{children}</span>;
  }

  return (
    <a
      href=""
      onClick={(e) => {
        e.preventDefault();
        onClick();
      }}
    >
      {children}
    </a>
  );
};

Link.propTypes = {
  active: PropTypes.bool.isRequired,
  children: PropTypes.node.isRequired,
  onClick: PropTypes.func.isRequired,
};

export default Link;
js
import React from "react";
import FilterLink from "../containers/FilterLink";

const Footer = () => (
  <p>
    Show: <FilterLink filter="SHOW_ALL">All</FilterLink>
    {", "}
    <FilterLink filter="SHOW_ACTIVE">Active</FilterLink>
    {", "}
    <FilterLink filter="SHOW_COMPLETED">Completed</FilterLink>
  </p>
);

export default Footer;

实现容器组件 ?

现在来创建一些容器组件把这些展示组件和 Redux 关联起来。技术上讲,容器组件就是使用 store.subscribe() 从 Redux state 树中读取部分数据,并通过 props 来把这些数据提供给要渲染的组件。你可以手工来开发容器组件,但建议使用 React Redux 库的 connect() 方法来生成,这个方法做了性能优化来避免很多不必要的重复渲染。(这样你就不必为了性能而手动实现 React 性能优化建议 中的 shouldComponentUpdate 方法。)

使用 connect() 前,需要先定义 mapStateToProps 这个函数来指定如何把当前 Redux store state 映射到展示组件的 props 中。例如,VisibleTodoList 需要计算传到 TodoList 中的 todos,所以定义了根据 state.visibilityFilter 来过滤 state.todos 的方法,并在 mapStateToProps 中使用。

js
const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case "SHOW_COMPLETED":
      return todos.filter((t) => t.completed);
    case "SHOW_ACTIVE":
      return todos.filter((t) => !t.completed);
    case "SHOW_ALL":
    default:
      return todos;
  }
};

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter),
  };
};

除了读取 state,容器组件还能分发 action。类似的方式,可以定义 mapDispatchToProps() 方法接收 dispatch() 方法并返回期望注入到展示组件的 props 中的回调方法。例如,我们希望 VisibleTodoListTodoList 组件中注入一个叫 onTodoClick 的 props ,还希望 onTodoClick 能分发 TOGGLE_TODO 这个 action:

js
const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
      dispatch(toggleTodo(id));
    },
  };
};

最后,使用 connect() 创建 VisibleTodoList,并传入这两个函数。

js
import { connect } from "react-redux";

const VisibleTodoList = connect(mapStateToProps, mapDispatchToProps)(TodoList);

export default VisibleTodoList;

这就是 React Redux API 的基础,但还漏了一些快捷技巧和强大的配置。建议你仔细学习 它的文档。如果你担心 mapStateToProps 创建新对象太过频繁,可以学习如何使用 reselect计算衍生数据

其它容器组件定义如下:

js
import { connect } from "react-redux";
import { setVisibilityFilter } from "../actions";
import Link from "../components/Link";

const mapStateToProps = (state, ownProps) => {
  return {
    active: ownProps.filter === state.visibilityFilter,
  };
};

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    onClick: () => {
      dispatch(setVisibilityFilter(ownProps.filter));
    },
  };
};

const FilterLink = connect(mapStateToProps, mapDispatchToProps)(Link);

export default FilterLink;

containers/VisibleTodoList.js ?

js
import { connect } from "react-redux";
import { toggleTodo } from "../actions";
import TodoList from "../components/TodoList";

const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case "SHOW_ALL":
      return todos;
    case "SHOW_COMPLETED":
      return todos.filter((t) => t.completed);
    case "SHOW_ACTIVE":
      return todos.filter((t) => !t.completed);
  }
};

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter),
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
      dispatch(toggleTodo(id));
    },
  };
};

const VisibleTodoList = connect(mapStateToProps, mapDispatchToProps)(TodoList);

export default VisibleTodoList;

其它组件 ?

containers/AddTodo.js ?

回想一下前面提到的AddTodo 组件的视图和逻辑混合在一个单独的定义之中。

js
import React from "react";
import { connect } from "react-redux";
import { addTodo } from "../actions";

let AddTodo = ({ dispatch }) => {
  let input;

  return (
    <div>
      <form
        onSubmit={(e) => {
          e.preventDefault();
          if (!input.value.trim()) {
            return;
          }
          dispatch(addTodo(input.value));
          input.value = "";
        }}
      >
        <input
          ref={(node) => {
            input = node;
          }}
        />
        <button type="submit">Add Todo</button>
      </form>
    </div>
  );
};
AddTodo = connect()(AddTodo);

export default AddTodo;

如果你不熟悉 ref 属性, 请阅读这篇文档以熟悉这个属性的推荐用法。

将容器放到一个组件 ?

components/App.js ?

js
import React from "react";
import Footer from "./Footer";
import AddTodo from "../containers/AddTodo";
import VisibleTodoList from "../containers/VisibleTodoList";

const App = () => (
  <div>
    <AddTodo />
    <VisibleTodoList />
    <Footer />
  </div>
);

export default App;

传入 Store ?

所有容器组件都可以访问 Redux store,所以可以手动监听它。一种方式是把它以 props 的形式传入到所有容器组件中。但这太麻烦了,因为必须要用 store 把展示组件包裹一层,仅仅是因为恰好在组件树中渲染了一个容器组件。

建议的方式是使用指定的 React Redux 组件 <Provider>魔法般的 让所有容器组件都可以访问 store,而不必显示地传递它。只需要在渲染根组件时使用即可。

index.js ?

js
import React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import todoApp from "./reducers";
import App from "./components/App";

let store = createStore(todoApp);

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

下一步 ?

参照 本完整示例 来深化理解。然后就可以跳到 高级教程 学习网络请求处理和路由。

21三体高风险是什么原因造成的 图灵测试是什么 生育保险是什么意思 什么人不适合做收银员 为什么体检前不能喝水
动物园里有什么动物 cook什么意思 张学良为什么不回大陆 床榻是什么意思 子虚乌有是什么意思
大什么什么手 狗生小狗前有什么征兆 脾主四肢是什么意思 道士是干什么的 恩师是什么意思
肾结石有什么表现症状 为什么突然头晕 熬夜头疼是什么原因 维生素d3是什么 中性皮肤的特征是什么
便秘吃什么可以调理hcv7jop6ns3r.cn 古人的婚礼在什么时候举行hcv9jop5ns6r.cn 彩色多普勒超声常规检查是什么hcv8jop6ns5r.cn xn是什么意思hcv8jop9ns3r.cn 睡觉被憋醒是什么原因hcv8jop1ns6r.cn
b型血rh阳性是什么意思qingzhougame.com 术前四项检查是什么hcv8jop0ns5r.cn 什么叫囊肿hcv8jop4ns1r.cn 阿戈美拉汀片是什么药hcv8jop0ns0r.cn 17点到19点是什么时辰hcv9jop3ns5r.cn
ex是什么意思hcv8jop0ns3r.cn 气血虚吃什么补最快女人hcv8jop1ns8r.cn 6月23号是什么星座gangsutong.com 劫财是什么意思hcv9jop7ns9r.cn 79年属什么的生肖hcv8jop9ns4r.cn
梦到吃螃蟹是什么意思hcv8jop2ns3r.cn 手工diy是什么意思hcv8jop0ns6r.cn 口腔医学技术是什么aiwuzhiyu.com 喉咙痛鼻塞吃什么药hcv9jop1ns8r.cn 122是什么号码hcv7jop6ns6r.cn
百度