什么是组件?
一个组件就是用户界面的一部分,它可以有自己的逻辑和外观。
组件之间可以互相嵌套,也可以复用多次
为什么要用组件?
组件能让开发者像搭积木一样快速构建一个完整的庞大应用,大大提升了开发效率,降低了维护成本,因此当下前端的主流开发模式即组件化开发
定义组件
react 中的组件有以下特征:
- 是一个首字母大写的函数
- 函数的返回值是一段 JSX 代码,用于渲染页面
- 通常每个组件都用独立的
.jsx
文件描述,并用export default
对外导出 - return 返回的语句写在一行,则可以省略() ,但只要不在一行,就必须要 () ,所以建议总是加上 ()
return <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />;
范例 Demo.jsx
function Demo() {
return <div>你好</div>;
}
export default Demo;
也可以写成箭头函数
const Demo = () => {
return <div>你好</div>;
};
export default Demo;
使用组件
以在 App.jsx 中使用为例:
先导入
import Demo from './Demo.js';
再使用
function App() {
return (
<>
<Demo />
</>
);
}
可以单标签自闭,也可以像 html 一样双标签配对
<Demo></Demo>
组件通信
即组件间相互传递数据
父组件传值给子组件
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
子组件获取父组件的传值 props
function Avatar({ person, size }) {
// 直接访问 person 和 size 即可
}
或
function Avatar(props) {
let person = props.person;
let size = props.size;
}
指定 props 的默认值
function Avatar({ person, size = 100 }) {
}
给 props 添加类型校验 propTypes
PropTypes
是 React 提供的一个用于类型检查的库。它可以用来验证组件的属性(props)是否符合预期的类型和格式
import PropTypes from "prop-types";
写在组件函数外
Avatar.propTypes = {
person: PropTypes.object,
size: PropTypes.number,
};
添加必填校验 .isRequired
在末尾添加 .isRequired
Avatar.propTypes = {
person: PropTypes.object.isRequired,
size: PropTypes.number,
};
数据类型检查器
-
PropTypes.string
-
PropTypes.symbol
-
PropTypes.number
-
PropTypes.bigint
-
PropTypes.bool
-
PropTypes.func
-
PropTypes.array
-
PropTypes.object
节点类型检查器
- PropTypes.node
- PropTypes.element
- PropTypes.elementType
父组件给子组件传递 JSX 内容(插槽) children
使用子组件时,其标签内的内容(即插槽),在子组件中可通过 children 获取到
父组件
import Child from "./child.jsx";
function Father() {
return (
<>
<Child>你好</Child>
</>
);
}
export default Father;
子组件
function Child({ children }) {
return (
<>
<h1>我是子组件</h1>
<div>父组件传入的插槽内容为:{children}</div>
</>
);
}
export default Child;
子组件传值给父组件
实现方案:在子组件中调用父组件中的函数并传递参数
父组件
import { useState } from "react";
import Child from "./child.jsx";
function Father() {
const [name, setName] = useState("朝阳");
function changeName() {
setName("新的朝阳");
}
return (
<>
<h1>我是父组件</h1>
<p>父组件中的变量 name 的值为:{name}</p>
<Child changeName={changeName}></Child>
</>
);
}
export default Father;
子组件
import PropTypes from "prop-types";
function Child({ changeName }) {
return (
<>
<h1>我是子组件</h1>
<button onClick={changeName}>修改父组件的名字为“新的朝阳”</button>
</>
);
}
Child.propTypes = {
changeName: PropTypes.func,
};
export default Child;
兄弟组件通信
father.jsx
import { useState } from "react";
import ChildA from "./childA.jsx";
import ChildB from "./childB.jsx";
function Father() {
const [msgA, setMsgA] = useState("");
function sendMsgToB(msg) {
setMsgA(msg);
}
return (
<>
<ChildA sendMsgToB={sendMsgToB} />
<ChildB msgA={msgA} />
</>
);
}
export default Father;
childA.jsx
import PropTypes from "prop-types";
function ChildA({ sendMsgToB }) {
const dataA = "子组件A的数据";
return (
<>
<div>
<h1>我是子组件A</h1>
<button onClick={() => sendMsgToB(dataA)}>向子组件B传递数据</button>
</div>
</>
);
}
ChildA.propTypes = {
sendMsgToB: PropTypes.func,
};
export default ChildA;
childB.jsx
import PropTypes from "prop-types";
function ChildB({ msgA }) {
return (
<>
<div>
<h1>我是子组件B</h1>
<p>子组件A传来的数据为:{msgA}</p>
</div>
</>
);
}
ChildB.propTypes = {
msgA: PropTypes.string,
};
export default ChildB;
跨层组件通信
详见 https://blog.csdn.net/weixin_41192489/article/details/138700487