Appearance
脚手架
创建 React 项目
shell
# npx
npx create-react-app my-app
# npm
npm init react-app my-app
# yarn
yarn create react-app my-app
目录结构
text
my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json #应用加壳(把网页变成Android/ios 软件)的配置文件
│ └── robots.txt #爬虫规则文件
└── src
├── App.css
├── App.js #根组件
├── App.test.js #用于给 App 组件做测试,一般不用
├── index.css
├── index.js #入口文件
├── logo.svg
├── serviceWorker.js #用于移动端开发, 支持离线浏览的功能
└── setupTests.js #组件单元测试文件,需要 jest-dom 库支持
public/index.html 分析
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<!-- %PUBLIC_URL% 代表 public 文件夹的路径 -->
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<!-- 开启理想视口,用于做移动端网页的适配 -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- 用于配置浏览器页签+地址栏的颜色(仅支持安卓手机浏览器) -->
<meta name="theme-color" content="red" />
<!-- 网站描述 -->
<meta name="description" content="Web site created using create-react-app" />
<!-- 用于指定网页添加到手机主屏幕后的图标 -->
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!-- 应用加壳时的配置文件 -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
</head>
<body>
<!-- 若浏览器不支持 js 则展示标签中的内容 -->
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
样式的模块化
text
├── home
│ ├── index.css
│ └── index.js
└── table
├── index.css
└── index.js
当两个组件内部标签元素有着共同的classname
, 在根组件APP.js
引入两个组件, 相同的classname
会导致样式冲突, 且后引入的会覆盖之前的样式
解决办法
- 将
.css
文件改为module.css
text
├── home
│ ├── index.module.css
│ └── index.js
└── table
├── index.module.css
└── index.js
- 在组件中导入样式
js
import { Component } from "react";
import home from "./index.module.css";
export default class Home extends Component {
render() {
return <h2 className={home.title}>Hello,React!</h2>;
}
}
父子组件之间通信
- 父传子使用
props
- 子传父, 需要父组件给子组件传递一个箭头函数, 子组件调用该函数实现
父组件:
jsx
// 父组件
class Father extends Component {
state: {
todos: [{ id: "001", name: "吃饭", done: true }],
};
addTodo = (todo) => {
const { todos } = this.state;
const newTodos = [todo, ...todos];
this.setState({ todos: newTodos });
};
render() {
// 这里将addTodo方法传递给子组件调用
return <List todos={this.state.todos} addTodo={this.addTodo} />;
}
}
子组件:
jsx
class Son extends Component {
// 由于 addTodo 是箭头函数,this 指向父组件实例对象,因此子组件调用它相当于父组件实例在调用
handleClick = () => {
this.props.addTodo({ id: "002", name: "敲代码", done: false });
};
render() {
return <button onClick={this.handleClick}>添加</button>;
}
}