1.学习社区的示例
目的是通过React社区熟悉和精通每个示例项目,记录学习笔记的目的是为自己提高做记录,同时和相关同学一起探讨技术问题;
简单的电子商务购物车应用程序
- 从浮动购物车中添加和删除产品
- 按最高到最低和最低到最高价格对产品进行分类
- 按可用尺寸过滤产品
- 页面重新加载后,产品仍保留在浮动购物车中
- 单元测试、集成测试和e2e测试
- 响应式设计
例子
Zeldog A Zelda like game with a dog fighting ducks and more to eat pizza ! game 我直接跳过
代码下载后,用npm install 或者是yarn install 安装一下
运行npm start
2.计算器的例子
import Big from "big.js";
import operate from "./operate";
import isNumber from "./isNumber";
/**
*给定一个按钮名和一个计算器数据对象,返回一个更新的
*计算器数据对象。
*计算器数据对象包含:
*total:String运行总数
*下一步:将要操作的下一个数字与总数串在一起
*操作:字符串+、-,等等。
*/
export default function calculate(obj, buttonName) {
if (buttonName === "AC") {
return {
total: null,
next: null,
operation: null,
};
}
if (isNumber(buttonName)) {
if (buttonName === "0" && obj.next === "0") {
return {};
}
// If there is an operation, update next
if (obj.operation) {
if (obj.next) {
return { next: obj.next + buttonName };
}
return { next: buttonName };
}
// If there is no operation, update next and clear the value
if (obj.next) {
const next = obj.next === "0" ? buttonName : obj.next + buttonName;
return {
next,
total: null,
};
}
return {
next: buttonName,
total: null,
};
}
//点击% 等于是除以100的值
if (buttonName === "%") {
if (obj.operation && obj.next) {
const result = operate(obj.total, obj.next, obj.operation);
return {
total: Big(result)
.div(Big("100"))
.toString(),
next: null,
operation: null,
};
}
if (obj.next) {
return {
next: Big(obj.next)
.div(Big("100"))
.toString(),
};
}
return {};
}
if (buttonName === ".") {
if (obj.next) {
// ignore a . if the next number already has one
if (obj.next.includes(".")) {
return {};
}
return { next: obj.next + "." };
}
return { next: "0." };
}
if (buttonName === "=") {
if (obj.next && obj.operation) {
return {
total: operate(obj.total, obj.next, obj.operation),
next: null,
operation: null,
};
} else {
// '=' with no operation, nothing to do
return {};
}
}
if (buttonName === "+/-") {
if (obj.next) {
return { next: (-1 * parseFloat(obj.next)).toString() };
}
if (obj.total) {
return { total: (-1 * parseFloat(obj.total)).toString() };
}
return {};
}
if (obj.operation) {
return {
total: operate(obj.total, obj.next, obj.operation),
next: null,
operation: buttonName,
};
}
//还没有操作,但用户键入了一个
//用户尚未键入数字,请保存操作
if (!obj.next) {
return { operation: buttonName };
}
// save the operation and shift 'next' into 'total'
return {
total: obj.next,
next: null,
operation: buttonName,
};
}
3.运行一个测试例子
//判断是为0-9字符
export default function isNumber(item) {
return /[0-9]+/.test(item);
}
import Big from "big.js";
import operate from "./operate";
import isNumber from "./isNumber";
/**
*给定一个按钮名和一个计算器数据对象,返回一个更新的
*计算器数据对象。
import calculate from "./calculate";
import chai from "chai";
// https://github.com/chaijs/chai/issues/469
chai.config.truncateThreshold = 0;
const expect = chai.expect;
function pressButtons(buttons) {
const value = {};
buttons.forEach(button => {
Object.assign(value, calculate(value, button));
});
// no need to distinguish between null and undefined values
Object.keys(value).forEach(key => {
if (value[key] === null) {
delete value[key];
}
});
return value;
}
function expectButtons(buttons, expectation) {
expect(pressButtons(buttons)).to.deep.equal(expectation);
}
function test(buttons, expectation, only = false) {
const func = only ? it.only : it;
func(`buttons ${buttons.join(",")} -> ${JSON.stringify(expectation)}`, () => {
expectButtons(buttons, expectation);
});
}
describe("calculate", function() {
test(["6"], { next: "6" });
test(["6", "6"], { next: "66" });
test(["6", "+", "6"], {
next: "6",
total: "6",
operation: "+",
});
test(["6", "-", "6","="], {
total: "0",
});
test(["6", "+", "6", "="], {
total: "12",
});
test(["0", "0", "+", "0", "="], {
total: "0",
});
test(["6", "+", "6", "=", "9"], {
next: "9",
});
test(["3", "+", "6", "=", "+"], {
total: "9",
operation: "+",
});
test(["3", "+", "6", "=", "+", "9"], {
total: "9",
operation: "+",
next: "9",
});
test(["3", "+", "6", "=", "+", "9", "="], {
total: "18",
});
// When '=' is pressed and there is not enough information to complete
// an operation, the '=' should be disregarded.
test(["3", "+", "=", "3", "="], {
total: "6",
});
test(["+"], {
operation: "+",
});
test(["+", "2"], {
next: "2",
operation: "+",
});
test(["+", "2", "+"], {
total: "2",
operation: "+",
});
test(["+", "2", "+", "+"], {
total: "2",
operation: "+",
});
test(["+", "2", "+", "5"], {
next: "5",
total: "2",
operation: "+",
});
test(["+", "2", "5"], {
next: "25",
operation: "+",
});
test(["+", "2", "5"], {
next: "25",
operation: "+",
});
test(["+", "6", "+", "5", "="], {
total: "11",
});
test(["0", ".", "4"], {
next: "0.4",
});
test([".", "4"], {
next: "0.4",
});
test([".", "4", "-", ".", "2"], {
total: "0.4",
next: "0.2",
operation: "-",
});
test([".", "4", "-", ".", "2", "="], {
total: "0.2",
});
// should clear the operator when AC is pressed
test(["1", "+", "2", "AC"], {});
test(["+", "2", "AC"], {});
test(["4", "%"], {
next: "0.04",
});
test(["4", "%", "x", "2", "="], {
total: "0.08",
});
test(["4", "%", "x", "2"], {
total: "0.04",
operation: "x",
next: "2",
});
// the percentage sign should also act as '='
test(["2", "x", "2", "%"], {
total: "0.04",
});
//Test that pressing the multiplication or division sign multiple times should not affect the current computation
test(["2", "x", "x"], {
total: "2",
operation: "x"
});
test(["2", "÷", "÷"], {
total: "2",
operation: "÷"
});
test(["2", "÷", "x", "+", "-", "x"], {
total: "2",
operation: 'x'
});
test(["2", "x", "2", "x", "2", "x","2","x","2","="], {
total: "32",
});
});
计算器数据对象包含:
*total:String运行总数
*下一步:将要操作的下一个数字与总数串在一起
*操作:字符串+、-,等等。
*/
export default function calculate(obj, buttonName) {
if (buttonName === "AC") {
return {
total: null,
next: null,
operation: null,
};
}
if (isNumber(buttonName)) {
if (buttonName === "0" && obj.next === "0") {
return {};
}
// If there is an operation, update next
if (obj.operation) {
if (obj.next) {
return { next: obj.next + buttonName };
}
return { next: buttonName };
}
// If there is no operation, update next and clear the value
if (obj.next) {
const next = obj.next === "0" ? buttonName : obj.next + buttonName;
return {
next,
total: null,
};
}
return {
next: buttonName,
total: null,
};
}
//点击% 等于是除以100的值
if (buttonName === "%") {
if (obj.operation && obj.next) {
const result = operate(obj.total, obj.next, obj.operation);
return {
total: Big(result)
.div(Big("100"))
.toString(),
next: null,
operation: null,
};
}
if (obj.next) {
return {
next: Big(obj.next)
.div(Big("100"))
.toString(),
};
}
return {};
}
if (buttonName === ".") {
if (obj.next) {
// ignore a . if the next number already has one
if (obj.next.includes(".")) {
return {};
}
return { next: obj.next + "." };
}
return { next: "0." };
}
if (buttonName === "=") {
if (obj.next && obj.operation) {
return {
total: operate(obj.total, obj.next, obj.operation),
next: null,
operation: null,
};
} else {
// '=' with no operation, nothing to do
return {};
}
}
if (buttonName === "+/-") {
if (obj.next) {
return { next: (-1 * parseFloat(obj.next)).toString() };
}
if (obj.total) {
return { total: (-1 * parseFloat(obj.total)).toString() };
}
return {};
}
if (obj.operation) {
return {
total: operate(obj.total, obj.next, obj.operation),
next: null,
operation: buttonName,
};
}
//还没有操作,但用户键入了一个
//用户尚未键入数字,请保存操作
if (!obj.next) {
return { operation: buttonName };
}
// save the operation and shift 'next' into 'total'
return {
total: obj.next,
next: null,
operation: buttonName,
};
}
操作js的代码
import Big from "big.js";
export default function operate(numberOne, numberTwo, operation) {
const one = Big(numberOne || "0");
const two = Big(numberTwo || (operation === "÷" || operation === 'x' ? "1": "0")); //If dividing or multiplying, then 1 maintains current value in cases of null
if (operation === "+") {
return one.plus(two).toString();
}
if (operation === "-") {
return one.minus(two).toString();
}
if (operation === "x") {
return one.times(two).toString();
}
if (operation === "÷") {
if (two === "0") {
alert("Divide by 0 error");
return "0";
} else {
return one.div(two).toString();
}
}
throw Error(`Unknown operation '${operation}'`);
}