1. 确定设计稿和数据

设计稿:

数据:

[
{category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
{category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
{category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
{category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
{category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
{category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];

2. 将设计稿UI分组件层级

组件单一功能原则:

即一个组件实现一个功能。

图中,一个颜色是一种组件,按照嵌套关系,可以分为:

FilterableProductTable:

SearchBar:

ProductTable:

ProductCategoryRow

ProductRow

3. 确定需要的state值的个数

原则:

1. 值不是来自与props
2. 值不是一成不变
3. 值不能由其他state和props求得

该示例中,需要数据源的地方有:

1. 查询框的文本 // 会变化;state.filterText
2. 复选框的状态 // 会变化;state.isStock
3. 所有的产品列表数据 // 通过props传入; 无state
4. 过滤后的产品列表数据 //通过1,2,3获得; 无state

4. 确定state的位置-状态提升

通过分析state对应的值作用的范围,state应该位于所有作用区域的父组件;

才能共享state。

从功能分析,1,2的状态会影响列表展示;则其应该位于查询框和列表的父组件;

即组件FilterableProductTable中。

3的状态会影响列表分类ProductCategoryRow和列表项ProductRow,则应该放在他们的父组件;

即组件ProductTable中。

5. 添加反向数据流

即通过触发子组件的事件监听,调用父组件传递过去的函数,从而改变父组件的state的值。

因为state的状态提升,而state又是私有状态,只能通过state所处的组件的函数进行修改。

6. 从下向上编写代码

/*
* @Author: LyraLee
* @Date: 2019-11-08 09:01:58
* @LastEditTime: 2019-11-20 17:32:14
* @Description: 分类数据处理
*/
'use strict'
const products = [
{category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
{category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
{category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
{category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
{category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
{category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];
function ProductRow(props) {
const product = props.product;
const { name } = product;
const renderName = !product.stocked ? <span style={{color: 'red'}}>{name}</span> : name
return (
<tr>
<td>{renderName}</td>
<td>{product.price}</td>
</tr>
)
}
function ProductCategoryRow(props) {
const product = props.product;
return(
<tr>
<th colSpan="2">{product.category}</th>
</tr>
)
}
function ProductTable(props) {
const { filterText, isStockedOnly, products } = props;
// 处理数据的方法!!!需要分类的属性是category,
// 如果数据不是按照该属性排序,那先将其按照category的字段顺序
let lastCategory = null;
let rows = []
products.sort((a,b) => a.category.localeCompare(b.category))
.forEach(product => {
if (!product.name.includes(filterText)) {
return;
}
if (isStockedOnly && !product.stocked) {
return;
}
if (product.category !== lastCategory) {
rows.push(<ProductCategoryRow key={product.category} product={product} />)
}
rows.push(
<ProductRow key={product.name} product={product} />
)
lastCategory = product.category;
}); return (
<table>
<thead>
<tr>
<th>name</th>
<th>price</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
)
}
function SearchBar(props) {
function handleChange (e) {
const { name, type } = e.target;
const value = type === 'checkbox' ? e.target.checked : e.target.value;
props.handleChange(name, value);
}
const { filterText, isStockedOnly } = props;
return(
<div>
<input
name="filterText"
type="text"
value={filterText}
onChange={handleChange}
placeholder="search..."
/>
<p>
<input
name="isStockedOnly"
type="checkbox"
checked={isStockedOnly}
onChange={handleChange}
/>{' '}
Only show products in stock
</p>
</div>
)
}
class FileterableProductTable extends React.Component {
constructor(props) {
super(props);
this.state = {
filterText: '',
isStockedOnly: false
}
}
handleChange = (name, value) => {
this.setState({
[name]: value
})
}
render() {
const { filterText, isStockedOnly } = this.state;
const { products } = this.props;
return(
<React.Fragment>
<SearchBar
filterText={filterText}
isStockedOnly={isStockedOnly}
handleChange={this.handleChange}
/>
<ProductTable
filterText={filterText}
isStockedOnly={isStockedOnly}
products={products}
/>
</React.Fragment>
)
}
} ReactDOM.render(<FileterableProductTable products={products} />, root);

从设计稿到实现React应用(分类数据处理)的更多相关文章

  1. React Native不同设备分辨率适配和设计稿尺寸单位px的适配

    React Native中使用的尺寸单位是dp(一种基于屏幕密度的抽象单位.在每英寸160点的显示器上,1dp = 1px),而设计师使用的是px, 这两种尺寸如何换算呢? 官方提供了PixelRat ...

  2. iPhone 6/6 Plus 出现后,如何改进工作流以实现一份设计稿支持多个尺寸?

    iPhone 6/6 Plus 出现后,如何改进工作流以实现一份设计稿支持多个尺寸? 2014-12-05 09:33 编辑: suiling 分类:iOS开发 来源:知乎(pigtwo)  2 22 ...

  3. iOS设计 - 一款APP从设计稿到切图过程概述

    这篇文章站在GUI设计师的角度概述了APP从项目启动到切片输出的过程,相当于工作流程的介绍.这里写的不是一种规范,只是一种工作方法,加上技术的更新是非常快的,大家在具体工作中,一定要灵活运用. 这里我 ...

  4. 从网易与淘宝的font-size思考前端设计稿与工作流

    本文结合自己对网易与淘宝移动端首页html元素上的font-size这个属性的思考与学习,讨论html5设计稿尺寸以及前端与设计之间协作流程的问题,内容较多,但对你的技术和工作一定有价值,欢迎阅读和点 ...

  5. 从网易与淘宝的font-size思考前端设计稿与工作流 (转)

    从网易与淘宝的font-size思考前端设计稿与工作流   阅读目录 1. 问题的引出 2. 简单问题简单解决 3. 网易的做法 4. 淘宝的做法 5. 比较网易与淘宝的做法 6. 如何与设计协作 7 ...

  6. 学习笔记:只有一套app设计稿(5s尺寸)切出4和4s尺寸以及安卓系统主流尺寸的图

    如何在只有一套app设计稿(5s尺寸)切出4和4s尺寸以及安卓系统主流尺寸的图 转自:http://www.zhihu.com/question/23255417   版权归原作者所有 目前ios手机 ...

  7. 移动端H5页面的设计稿尺寸大小规范-转载自http://www.chinaz.com/design/2015/1103/465670.shtml

    机屏幕尺寸,设计稿应该按照哪一个尺寸作为标准尺寸.现在已经有2K分辨率的手机屏幕了,设计稿是不是也要把宽高跟着最大分辨率来设计.显然不是. 请注意:(以下所有讨论内容和规范均将viewport设定为c ...

  8. 一款APP从设计稿到切图过程全方位揭秘 Mark

    纯干货!一款APP从设计稿到切图过程全方位揭秘   @BAT_LCK:我本身是一名GUI设计师,所以我只站在GUI设计师的角度去把APP从项目启动到切片输出的过程写一写,相当于工作流程的介绍吧.公司不 ...

  9. iPhone 6出现后,如何将一份设计稿支持多个尺寸?

    http://mp.weixin.qq.com/s?__biz=MzA4NTQzNTMwOA==&mid=201174413&idx=3&sn=c3fe5b3459bac288 ...

随机推荐

  1. CF197A Plate Game

    题目描述 你有一个长方形的桌子,长度 a ,宽度 b ,以及无限多的半径 r的圆盘. 两位玩家玩以下游戏:他们轮流把圆盘放在桌子上,使得盘子之间不能互相重叠(但他们的边缘可以互相接触),任何盘子上的任 ...

  2. Pythn基础课程笔记day03_学习内容概要及作业讲解

    第三天_学习内容概要 今日内容概要 1.整形 2.布尔类型 3.字符串 内容回顾和补充 内容回顾 利用思维导图,罗列复习自己学习的内容,巩固知识点. xmind 软件 processon 网站 补充 ...

  3. Python进阶:并发编程之Futures

    区分并发和并行 并发(Concurrency). 由于Python 的解释器并不是线程安全的,为了解决由此带来的 race condition 等问题,Python 便引入了全局解释器锁,也就是同一时 ...

  4. 机器学习xgboost参数解释笔记

    首先xgboost有两种接口,xgboost自带API和Scikit-Learn的API,具体用法有细微的差别但不大. 在运行 XGBoost 之前, 我们必须设置三种类型的参数: (常规参数)gen ...

  5. Redis客户端、服务端的安装以及命令操作

    目的: redis简介 redis服务端安装 redis客户端安装 redis相关命令操作 redis简介 官网下载(https://redis.io/) Redis 是完全开源免费的,遵守BSD协议 ...

  6. myisam和innodb的区别,java事务不起作用原因

    myisam:只支持表级锁.不支持事务.方便移植.该类型是mysql默认表存储类型 innodb:支持表级锁和行级锁.支持事务. 如果你的事务不起作用,很可能是用了myisam存储引擎,检查数据表引擎 ...

  7. springboot笔记03——quickstart程序原理

    一.前言 一个quickstart程序仅仅让我们初步了解一个框架,我们还需要透过现象看本质才能学好一个框架.所以这篇文章分析一下我上次写的springboot的入门程序. 二.原理分析 1.依赖分析 ...

  8. 【转载】C#中PadLeft函数按特定字符补足字符串长度

    在C#开发过程中字符串String类处理过程中,有时字符串长度不够时,需要在左侧指定特定的字符来补足字符串长度,此时可以使用String类下的PadLeft方法对字符串的左边进行按特定的字符和特定的长 ...

  9. Django学习笔记 (一) 开发环境配置

    Django是一个开放源代码的Web应用框架,由Python写成. 采用了MVC的软件设计模式,即模型M,视图V和控制器C. 1. Python安装 下载地址: http://www.python.o ...

  10. 【js】字符串反转(倒序)的多种处理方式

    今天发布一篇关于字符串反转的几种方式(一种问题的解决方案不是只有一种). 方式1: 这种方式比较简单,推荐使用 字符串转数组,反转数组,数组转字符串. split(""):根据空字 ...