1、React组件之间常用的通信方式
1. 父子组件通信(最常用!)
👉 方式:props
- 父组件通过 props 向子组件传递数据、函数。
- 子组件通过调用 props 中的函数向父组件“通信”。
// 父组件
function Parent() {
const sayHi = () => alert("Hi from Parent!");
return <Child name="React" onGreet={sayHi} />;
}
// 子组件
function Child({ name, onGreet }) {
return (
<div>
Hello, {name}
<button onClick={onGreet}>Greet</button>
</div>
);
}
🤝 2. 兄弟组件通信
👉 方式:
- 提升状态到共同父组件;
- 或者使用全局状态(如 context、Redux)。
function Parent() {
const [value, setValue] = useState("");
return (
<>
<SiblingA onChange={setValue} />
<SiblingB value={value} />
</>
);
}
function SiblingA({ onChange }) {
return <input onChange={(e) => onChange(e.target.value)} />;
}
function SiblingB({ value }) {
return <p>{value}</p>;
}
🏗 3. 祖孙组件通信
👉 方式:
- 用 React Context 来共享状态或函数。
const ThemeContext = React.createContext();
function App() {
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
);
}
function Child() {
return <GrandChild />;
}
function GrandChild() {
const theme = useContext(ThemeContext);
return <div>Current theme: {theme}</div>;
}
🌐 4. 跨组件/全局通信
👉 方式:
- Redux / Zustand / Recoil 等全局状态管理;
- React Context(适合轻量需求);
- EventEmitter(非常规,但有用)。
📢 5. 其他方式(少用)
- Ref 传递 + 调用子组件方法
- 父组件获取子组件的 ref,调用其内部方法。
- 自定义事件系统
- 适合大型应用中解耦模块,或者页面外通信(如 WebSocket 推送通知)。
2、常用的React Hooks
🌟 核心 Hooks(必背!)
| Hook 名称 | 作用说明 |
|---|---|
useState | 声明状态变量 |
useEffect | 处理副作用(如:请求、订阅、定时器) |
useContext | 使用上下文 context 的值 |
useRef | 获取 DOM 节点或保存可变值不触发渲染 |
useMemo | 缓存计算结果,避免重复计算(性能优化) |
useCallback | 缓存函数引用,避免子组件不必要更新 |
useReducer | 更复杂状态管理逻辑(像 Redux 的 reducer) |
🔁 生命周期类替代 Hook
| class组件生命周期 | 对应 Hook 使用方式 |
|---|---|
componentDidMount | useEffect(() => {}, []) |
componentDidUpdate | useEffect(() => {...}, [依赖]) |
componentWillUnmount | useEffect(() => { return () => {...} }, []) |
📦 其他常用 Hooks
| Hook 名称 | 用法说明 |
|---|---|
useLayoutEffect | 与 useEffect 类似,但同步执行,适合操作 DOM 尺寸、位置 |
useImperativeHandle | 自定义 ref 暴露的实例方法(配合 forwardRef) |
useId (React 18+) | 用于生成唯一 ID,适合表单控件等 |
useTransition / useDeferredValue | 控制 UI 更新优先级(适合大数据量场景) |
3、stopPropagation和preventDefault
⛔event.preventDefault()
👉 作用:阻止默认行为
例子:
- 阻止
<a href="">跳转 - 阻止
<form>提交 - 阻止右键菜单弹出(context menu)
document.querySelector('a').addEventListener('click', (e) => {
e.preventDefault(); // 不会跳转了!
});
⛔ event.stopPropagation()
👉 作用:阻止事件冒泡(不传递给父元素)
例子:
<div id="outer">
<button id="inner">点我</button>
</div>
document.getElementById('outer').addEventListener('click', () => {
console.log('外层被点了');
});
document.getElementById('inner').addEventListener('click', (e) => {
e.stopPropagation();
console.log('按钮被点了');
});
结果:点击按钮只会触发
inner的事件,不会触发outer。
🎁 小贴士:可以一起用
有时候我们既不想让它有默认行为,又不想事件冒泡,比如:
input.addEventListener('keydown', (e) => {
e.preventDefault();
e.stopPropagation();
});
4、CSS实现居中对齐有哪些方式
💬 一、文本居中
text-align: center;
🧱 二、块级元素水平居中
1. margin: 0 auto;(最常见)
条件:元素要有固定宽度
.box {
width: 300px;
margin: 0 auto;
}
2. display: flex; 父容器居中
.parent {
display: flex;
justify-content: center;
}
适用于:子元素水平居中,配合 align-items 还能垂直居中👇
三、水平 + 垂直都居中
1. Flex
.parent {
display: flex;
justify-content: center;
align-items: center;
}
元素无论宽高是否已知都能居中!
2. Grid 布局
.parent {
display: grid;
place-items: center;
}
3. 绝对定位 + transform
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
适用于:宽高未知的元素居中,经典必备技巧。
4. line-height 垂直居中(仅适用于单行文字)
.line-text {
height: 50px;
line-height: 50px;
text-align: center;
}
📌 小结对照表:
| 方式 | 用途 | 是否支持宽高未知 |
|---|---|---|
margin: 0 auto | 块级元素水平居中 | ❌ 需要固定宽度 |
text-align: center | 行内元素 / 文本 | ✅ |
| Flex | 任意居中 | ✅ |
| Grid | 任意居中 | ✅ |
position + transform | 任意居中 | ✅ |
line-height | 单行文字垂直居中 | ❌ |
5、浏览器输入url后发生了什么
🌐 1. DNS 解析
浏览器要把域名 example.com 转换为 IP 地址。
流程是这样:
- 浏览器缓存中查找
- 操作系统缓存查找
- 本地
hosts文件查找 - 找 DNS 服务器(可能是 ISP 的、也可能是你设置的 8.8.8.8 等公共 DNS)
- DNS 服务器查权威 DNS 得到最终 IP
🔎 最终得到比如:
93.184.216.34
📡 2. 建立 TCP 连接(含 TLS)
- 建立 TCP 连接(三次握手)
- 若是
https://,则进入 TLS 握手阶段(证书验证 + 对称加密协商)
🔐 这时浏览器和服务器之间建立了一个安全的“隧道”
📨 3. 发起 HTTP 请求
浏览器构造 HTTP 请求并发送,比如:
GET / HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0...
Accept: text/html,...
服务器接收请求,准备响应。
🏭 4. 服务器处理请求
后端根据请求路径处理逻辑,比如:
- 查询数据库
- 处理业务逻辑
- 渲染模板 / 返回 JSON
- 读取静态资源文件
并最终返回一个响应,比如 HTML 页面:
HTTP/1.1 200 OK
Content-Type: text/html
<!DOCTYPE html>
<html>
<head><title>Hello</title></head>
<body>Hello World!</body>
</html>
📥 5. 浏览器接收响应并渲染
- 浏览器根据响应头判断内容类型,比如是 HTML
- 解析 HTML → 构建 DOM
- 遇到
<link>加载 CSS,构建 CSSOM - 遇到
<script>加载 JS,执行逻辑 - 遇到
<img>等资源继续发起请求
最终:
- DOM + CSSOM → 合成渲染树
- 计算布局(Layout)
- 绘制页面(Paint)
🔁 6. 页面交互 & 后续请求
页面加载完后,JS 脚本可能会:
- 监听用户事件
- 发起 Ajax / Fetch 请求
- 动态更新 DOM
🎁 总结一句话:
浏览器输入 URL → DNS → TCP/TLS → HTTP 请求 → 服务器响应 → 浏览器解析渲染 → 用户看到页面!
6、Symbol用途
Symbol 是 ES6 引入的一种原始数据类型,用来表示独一无二的值。它非常适合用在对象属性中,避免命名冲突,是一种创建私有属性的“技巧”。
✅ 1. 用作对象的唯一属性键,防止属性名冲突
const key1 = Symbol('key');
const key2 = Symbol('key'); // 和 key1 虽然描述一样,但值不同
const obj = {
[key1]: 'hello',
[key2]: 'world'
};
console.log(obj[key1]); // hello
console.log(obj[key2]); // world
✅ 2. 模拟私有属性
const secret = Symbol('secret');
class Person {
constructor(name) {
this.name = name;
this[secret] = 'my secret';
}
getSecret() {
return this[secret];
}
}
const p = new Person('Tom');
console.log(p.secret); // undefined
console.log(p.getSecret()); // 'my secret'
👉 虽然不是完全私有(可以通过 Object.getOwnPropertySymbols() 拿到),但足以避免无意访问。
✅ 3. 内置 Symbol 提供特殊行为
JavaScript 提供了一些内置 Symbol,可以自定义对象在特定操作下的行为:
| 内置 Symbol | 作用 |
|---|---|
Symbol.iterator | 控制对象的可迭代行为(如 for...of) |
Symbol.toStringTag | 控制 Object.prototype.toString.call(obj) 的结果 |
Symbol.toPrimitive | 控制对象转原始类型时的行为 |
Symbol.hasInstance | 控制 instanceof 行为 |
Symbol.match、Symbol.replace | 用于自定义字符串操作方法的行为 |
示例:
const obj = {
[Symbol.toPrimitive](hint) {
if (hint === 'number') return 42;
return 'I am a Symbolic Object!';
}
};
console.log(+obj); // 42
console.log(`${obj}`); // I am a Symbolic Object!
✅ 4. 用于实现常量枚举(避免魔法字符串)
const SHAPE_TYPE = {
CIRCLE: Symbol('circle'),
SQUARE: Symbol('square')
};
function draw(shape) {
switch (shape) {
case SHAPE_TYPE.CIRCLE:
console.log('Drawing circle');
break;
case SHAPE_TYPE.SQUARE:
console.log('Drawing square');
break;
default:
throw new Error('Unknown shape');
}
}
❗ Symbol 注意点:
- 无法通过
for...in或Object.keys()枚举出来 - 可以通过
Object.getOwnPropertySymbols()访问 - 无法隐式转换成字符串(需显式
.toString())
let s = Symbol('abc');
console.log(String(s)); // Symbol(abc)