React 学习项目1
React 学习
最近想学习一下react, 看到有一个比较有趣的网站, 本文记录用react简单实现它的过程
整体结构可以看两张截图
整体可分
- Header
- Body
- Footer
效果如截图, 有一个商品的长列表, 假设比尔盖茨有1000亿美元, 看能够买什么东西.
下面根据部分拆解实现
Header
左边是原站连接, 右边是语言切换按钮. 可以使用css的grid来横向展示多个div
function Header() {
const onChangeLang = (isCn) => {
i18n.changeLanguage(isCn ? "zh_CN" : "en");
};
return (
<div className="Header">
<div className="SourceSiteLike">...</div>
<div className="LanguageSwitcher"><Switch onChange={changeLang}/></div>
</div>
);
}
// Header.css
.Header {
...
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
}
采用i18next
和react-i18next
实现国际化多语言切换
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import zh_CN from "./zh_CH"; // json 文件存放的中文翻译键值对
import en from "./en"; // json 文件存放的英文翻译键值对
const resources = {
zh_CN: {
translation: zh_CN,
},
en: {
translation: en,
},
};
i18n.use(initReactI18next).init({
resources,
lng: "zh_CN",
keySeparator: false,
interpolation: { escapeValue: false },
});
export default i18n;
在index.js
引用i18n
, 即可使用withTranslation
和useTranslation
, 来对关键词做语言切换
Body
首先为了和Header
和Footer
产生视觉差距, Body
采用固定比例宽度, 并且margin-left{right}: auto;
- Title
头像和游戏名字, 可以使用border-radius : 50%
获得一个圆形头像.
接下来的MoneyBor
,ProductList
和Receipt
之间联系紧密, 采用Component
组件Shop
管理它们的共同状态
class Shop extends React.PureComponent {
constructor(props) {
super(props);
// product_data = [ ['product name', product cost, {product inventory}] ]
let data_list = ProductList.product_data.map((value, index) => {
// 生成每个item的属性
return {
// 静态属性
image_src: this._getImageUrl(String(value[0])), // 图片地址
product_cost: value[1], // 花费
product_name: value[0], // 商品名字
inventory: value[2] ? value[2] : Number.MAX_SAFE_INTEGER, // 商品库存
index: index, // 商品在Shop列表的下标
// 动态属性
enable_buy: true, // 是否可以买
enable_sell: false, // 是否可以卖
buy_count: 0, // 买了几个
};
});
this.state = {
column_count: 3,
data_list: data_list,
current_money: 100000000000,
};
}
}
- MoneyBar
- 使用
position: sticky; z-index: 9999;
来实现附着效果. Shop.current_money
绑定到react-animated-number
来展示动态变化的剩余金钱formatMoney
工具函数将数字转化为英文表示法
- ProductList
- 继续使用
Grid
布局, 通过Shop.data_list
生成每个ProductCell
- 由于商品是固定且有限的,将
ProductCell
定义为stateless的组件, 购买和出售绑定到Shop处理, 并动态计算是否可以继续出售和购买(出售可能导致其他商品可以购买,购买可能导致购买其他商品的金额不足).
- Receipt
遍历Shop.data_list[i].buy_count
, 生产购买单项和总价即可.
Summary
- React分函数组件和类组件, 函数组件返回值就是渲染的html元素, 类组件使用render函数表达需要渲染的html函数, 它们都接受
props
参数, 是由父节点在html上绑定传递过来的. - html元素中使用
{}
执行js逻辑 - 函数组件可使用hooks,
useState(val)
:产生/设置内部参数. 自定义hook可以方便添加公有属性, hook也可为函数组件添加生命周期逻辑 - 类组件要使用类似自定义hook的效果要利用HOC(高阶组件,以参数为组件,返回值为新组件的函数).
- 类组件在构造函数声明
state
,使用setState
更新状态, 是否要更新html元素及更新的时机由react决定. - 组件之间的数据流动, 简单办法可以使用传回调函数做参数.
- 条件渲染: if表达式或
flag && element
- 列表渲染: 对数组应用map函数, 每个生成的组件都应该有在列表内唯一的key, 且不能为数组下标, react通过key来决定列表元素是否发生了变化.(这个列表是只对ul/li生效还是所有元素组成的列表都生效存疑)