Search K
Appearance
Appearance
📊 SEO元描述:2024年最新JavaScript组件通信模式教程,详解父子组件通信、兄弟组件通信、跨层级通信。包含完整代码示例,适合前端开发者快速掌握组件通信。
核心关键词:JavaScript组件通信2024、组件通信模式、父子组件通信、兄弟组件通信、跨层级通信
长尾关键词:组件通信怎么实现、JavaScript组件数据传递、组件通信最佳实践、事件总线通信、组件间状态共享
通过本节JavaScript组件通信模式完整教程,你将系统性掌握:
组件通信模式是什么?这是构建复杂前端应用时必须解决的核心问题。组件通信模式是指不同组件之间传递数据、共享状态、协调行为的方法和机制,它是组件化架构中实现组件协作的基础,也是数据流管理的重要组成部分。
💡 通信设计建议:选择合适的通信模式对于应用的可维护性和性能都至关重要。不同的场景应该采用不同的通信策略。
父子组件通信是最常见和最基础的组件通信模式:
// 🎉 父子组件通信基础实现
class EventEmitter {
constructor() {
this.events = new Map();
}
on(event, callback) {
if (!this.events.has(event)) {
this.events.set(event, []);
}
this.events.get(event).push(callback);
// 返回取消订阅函数
return () => {
const callbacks = this.events.get(event);
const index = callbacks.indexOf(callback);
if (index !== -1) {
callbacks.splice(index, 1);
}
};
}
emit(event, data) {
if (this.events.has(event)) {
this.events.get(event).forEach(callback => {
try {
callback(data);
} catch (error) {
console.error(`Error in event callback for ${event}:`, error);
}
});
}
}
off(event, callback) {
if (this.events.has(event)) {
const callbacks = this.events.get(event);
const index = callbacks.indexOf(callback);
if (index !== -1) {
callbacks.splice(index, 1);
}
}
}
}
// 🎉 基础组件类
class Component extends EventEmitter {
constructor(props = {}) {
super();
this.props = props;
this.state = {};
this.children = [];
this.parent = null;
this.element = null;
this.mounted = false;
this.initializeState();
}
initializeState() {
// 子类可重写
}
setState(newState, callback) {
const prevState = { ...this.state };
this.state = { ...this.state, ...newState };
// 触发状态变化事件
this.emit('stateChange', {
prevState,
currentState: this.state,
component: this
});
if (this.mounted) {
this.forceUpdate();
}
if (callback) {
callback();
}
}
addChild(child) {
if (child instanceof Component) {
child.parent = this;
this.children.push(child);
// 建立父子通信链路
this.setupChildCommunication(child);
}
}
removeChild(child) {
const index = this.children.indexOf(child);
if (index !== -1) {
child.parent = null;
this.children.splice(index, 1);
// 清理通信链路
this.cleanupChildCommunication(child);
}
}
setupChildCommunication(child) {
// 监听子组件事件
child.on('*', (event, data) => {
// 向上冒泡事件
this.emit(`child:${event}`, { child, data });
});
}
cleanupChildCommunication(child) {
// 清理事件监听
child.off('*');
}
// 向父组件发送消息
sendToParent(event, data) {
if (this.parent) {
this.parent.emit(`child:${event}`, { child: this, data });
}
}
// 向子组件广播消息
broadcastToChildren(event, data) {
this.children.forEach(child => {
child.emit(`parent:${event}`, { parent: this, data });
});
}
// 向特定子组件发送消息
sendToChild(childId, event, data) {
const child = this.children.find(c => c.id === childId);
if (child) {
child.emit(`parent:${event}`, { parent: this, data });
}
}
render() {
throw new Error('render method must be implemented');
}
mount(container) {
this.element = this.render();
if (container && this.element) {
container.appendChild(this.element);
}
this.mounted = true;
this.emit('mounted');
}
forceUpdate() {
if (this.mounted && this.element) {
const newElement = this.render();
if (this.element.parentNode) {
this.element.parentNode.replaceChild(newElement, this.element);
this.element = newElement;
}
}
}
}
// 🎉 父组件示例 - 用户列表
class UserList extends Component {
initializeState() {
this.state = {
users: [
{ id: 1, name: 'John Doe', email: 'john@example.com', active: true },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', active: false },
{ id: 3, name: 'Bob Johnson', email: 'bob@example.com', active: true }
],
selectedUser: null,
filter: 'all' // all, active, inactive
};
}
render() {
const container = document.createElement('div');
container.className = 'user-list';
// 标题
const title = document.createElement('h2');
title.textContent = 'User Management';
container.appendChild(title);
// 过滤器
const filterContainer = this.renderFilter();
container.appendChild(filterContainer);
// 用户列表
const listContainer = document.createElement('div');
listContainer.className = 'user-items';
const filteredUsers = this.getFilteredUsers();
filteredUsers.forEach(user => {
const userItem = new UserItem({
user: user,
selected: this.state.selectedUser?.id === user.id,
onSelect: (userData) => this.handleUserSelect(userData),
onToggleActive: (userData) => this.handleToggleActive(userData),
onDelete: (userData) => this.handleUserDelete(userData)
});
this.addChild(userItem);
userItem.mount(listContainer);
});
container.appendChild(listContainer);
// 用户详情
if (this.state.selectedUser) {
const userDetail = new UserDetail({
user: this.state.selectedUser,
onUpdate: (userData) => this.handleUserUpdate(userData),
onClose: () => this.handleCloseDetail()
});
this.addChild(userDetail);
userDetail.mount(container);
}
return container;
}
renderFilter() {
const container = document.createElement('div');
container.className = 'filter-container';
const filters = [
{ value: 'all', label: 'All Users' },
{ value: 'active', label: 'Active Users' },
{ value: 'inactive', label: 'Inactive Users' }
];
filters.forEach(filter => {
const button = document.createElement('button');
button.textContent = filter.label;
button.className = `filter-btn ${this.state.filter === filter.value ? 'active' : ''}`;
button.addEventListener('click', () => this.setFilter(filter.value));
container.appendChild(button);
});
return container;
}
getFilteredUsers() {
switch (this.state.filter) {
case 'active':
return this.state.users.filter(user => user.active);
case 'inactive':
return this.state.users.filter(user => !user.active);
default:
return this.state.users;
}
}
setFilter(filter) {
this.setState({ filter });
}
handleUserSelect(user) {
this.setState({ selectedUser: user });
// 通知其他组件用户被选中
this.emit('userSelected', user);
}
handleToggleActive(user) {
const updatedUsers = this.state.users.map(u =>
u.id === user.id ? { ...u, active: !u.active } : u
);
this.setState({ users: updatedUsers });
// 如果当前选中的用户被更新,同步更新选中状态
if (this.state.selectedUser?.id === user.id) {
this.setState({
selectedUser: { ...this.state.selectedUser, active: !this.state.selectedUser.active }
});
}
this.emit('userUpdated', { ...user, active: !user.active });
}
handleUserDelete(user) {
const updatedUsers = this.state.users.filter(u => u.id !== user.id);
this.setState({ users: updatedUsers });
// 如果删除的是当前选中的用户,清除选中状态
if (this.state.selectedUser?.id === user.id) {
this.setState({ selectedUser: null });
}
this.emit('userDeleted', user);
}
handleUserUpdate(updatedUser) {
const updatedUsers = this.state.users.map(u =>
u.id === updatedUser.id ? updatedUser : u
);
this.setState({
users: updatedUsers,
selectedUser: updatedUser
});
this.emit('userUpdated', updatedUser);
}
handleCloseDetail() {
this.setState({ selectedUser: null });
}
}
// 🎉 子组件示例 - 用户项
class UserItem extends Component {
render() {
const { user, selected } = this.props;
const item = document.createElement('div');
item.className = `user-item ${selected ? 'selected' : ''} ${user.active ? 'active' : 'inactive'}`;
// 用户头像
const avatar = document.createElement('div');
avatar.className = 'user-avatar';
avatar.textContent = user.name.charAt(0).toUpperCase();
item.appendChild(avatar);
// 用户信息
const info = document.createElement('div');
info.className = 'user-info';
const name = document.createElement('h4');
name.textContent = user.name;
info.appendChild(name);
const email = document.createElement('p');
email.textContent = user.email;
info.appendChild(email);
const status = document.createElement('span');
status.className = `status ${user.active ? 'active' : 'inactive'}`;
status.textContent = user.active ? 'Active' : 'Inactive';
info.appendChild(status);
item.appendChild(info);
// 操作按钮
const actions = document.createElement('div');
actions.className = 'user-actions';
const selectBtn = document.createElement('button');
selectBtn.textContent = 'Select';
selectBtn.className = 'btn btn-primary';
selectBtn.addEventListener('click', () => this.handleSelect());
actions.appendChild(selectBtn);
const toggleBtn = document.createElement('button');
toggleBtn.textContent = user.active ? 'Deactivate' : 'Activate';
toggleBtn.className = `btn ${user.active ? 'btn-warning' : 'btn-success'}`;
toggleBtn.addEventListener('click', () => this.handleToggleActive());
actions.appendChild(toggleBtn);
const deleteBtn = document.createElement('button');
deleteBtn.textContent = 'Delete';
deleteBtn.className = 'btn btn-danger';
deleteBtn.addEventListener('click', () => this.handleDelete());
actions.appendChild(deleteBtn);
item.appendChild(actions);
return item;
}
handleSelect() {
// 通过props回调向父组件传递数据
if (this.props.onSelect) {
this.props.onSelect(this.props.user);
}
// 通过事件向父组件发送消息
this.sendToParent('userSelect', this.props.user);
}
handleToggleActive() {
if (this.props.onToggleActive) {
this.props.onToggleActive(this.props.user);
}
this.sendToParent('userToggleActive', this.props.user);
}
handleDelete() {
if (confirm(`Are you sure you want to delete ${this.props.user.name}?`)) {
if (this.props.onDelete) {
this.props.onDelete(this.props.user);
}
this.sendToParent('userDelete', this.props.user);
}
}
}
// 🎉 子组件示例 - 用户详情
class UserDetail extends Component {
initializeState() {
this.state = {
editing: false,
formData: { ...this.props.user }
};
}
render() {
const { user } = this.props;
const container = document.createElement('div');
container.className = 'user-detail';
// 标题栏
const header = document.createElement('div');
header.className = 'detail-header';
const title = document.createElement('h3');
title.textContent = 'User Details';
header.appendChild(title);
const closeBtn = document.createElement('button');
closeBtn.textContent = '×';
closeBtn.className = 'close-btn';
closeBtn.addEventListener('click', () => this.handleClose());
header.appendChild(closeBtn);
container.appendChild(header);
// 内容区域
const content = document.createElement('div');
content.className = 'detail-content';
if (this.state.editing) {
content.appendChild(this.renderEditForm());
} else {
content.appendChild(this.renderUserInfo());
}
container.appendChild(content);
return container;
}
renderUserInfo() {
const { user } = this.props;
const info = document.createElement('div');
info.className = 'user-info-detail';
const fields = [
{ label: 'Name', value: user.name },
{ label: 'Email', value: user.email },
{ label: 'Status', value: user.active ? 'Active' : 'Inactive' }
];
fields.forEach(field => {
const fieldDiv = document.createElement('div');
fieldDiv.className = 'info-field';
const label = document.createElement('label');
label.textContent = field.label + ':';
fieldDiv.appendChild(label);
const value = document.createElement('span');
value.textContent = field.value;
fieldDiv.appendChild(value);
info.appendChild(fieldDiv);
});
// 编辑按钮
const editBtn = document.createElement('button');
editBtn.textContent = 'Edit';
editBtn.className = 'btn btn-primary';
editBtn.addEventListener('click', () => this.startEditing());
info.appendChild(editBtn);
return info;
}
renderEditForm() {
const form = document.createElement('form');
form.className = 'edit-form';
form.addEventListener('submit', (e) => this.handleSubmit(e));
// 姓名输入
const nameGroup = this.createFormGroup('name', 'Name', 'text');
form.appendChild(nameGroup);
// 邮箱输入
const emailGroup = this.createFormGroup('email', 'Email', 'email');
form.appendChild(emailGroup);
// 状态选择
const statusGroup = document.createElement('div');
statusGroup.className = 'form-group';
const statusLabel = document.createElement('label');
statusLabel.textContent = 'Status:';
statusGroup.appendChild(statusLabel);
const statusSelect = document.createElement('select');
statusSelect.value = this.state.formData.active ? 'active' : 'inactive';
statusSelect.addEventListener('change', (e) => {
this.setState({
formData: {
...this.state.formData,
active: e.target.value === 'active'
}
});
});
const activeOption = document.createElement('option');
activeOption.value = 'active';
activeOption.textContent = 'Active';
statusSelect.appendChild(activeOption);
const inactiveOption = document.createElement('option');
inactiveOption.value = 'inactive';
inactiveOption.textContent = 'Inactive';
statusSelect.appendChild(inactiveOption);
statusGroup.appendChild(statusSelect);
form.appendChild(statusGroup);
// 按钮组
const buttonGroup = document.createElement('div');
buttonGroup.className = 'button-group';
const saveBtn = document.createElement('button');
saveBtn.type = 'submit';
saveBtn.textContent = 'Save';
saveBtn.className = 'btn btn-success';
buttonGroup.appendChild(saveBtn);
const cancelBtn = document.createElement('button');
cancelBtn.type = 'button';
cancelBtn.textContent = 'Cancel';
cancelBtn.className = 'btn btn-secondary';
cancelBtn.addEventListener('click', () => this.cancelEditing());
buttonGroup.appendChild(cancelBtn);
form.appendChild(buttonGroup);
return form;
}
createFormGroup(field, label, type) {
const group = document.createElement('div');
group.className = 'form-group';
const labelEl = document.createElement('label');
labelEl.textContent = label + ':';
group.appendChild(labelEl);
const input = document.createElement('input');
input.type = type;
input.value = this.state.formData[field];
input.addEventListener('input', (e) => {
this.setState({
formData: {
...this.state.formData,
[field]: e.target.value
}
});
});
group.appendChild(input);
return group;
}
startEditing() {
this.setState({
editing: true,
formData: { ...this.props.user }
});
}
cancelEditing() {
this.setState({
editing: false,
formData: { ...this.props.user }
});
}
handleSubmit(event) {
event.preventDefault();
// 通过props回调向父组件传递更新的数据
if (this.props.onUpdate) {
this.props.onUpdate(this.state.formData);
}
// 通过事件向父组件发送消息
this.sendToParent('userUpdate', this.state.formData);
this.setState({ editing: false });
}
handleClose() {
if (this.props.onClose) {
this.props.onClose();
}
this.sendToParent('closeDetail');
}
}
// 使用示例
console.log('=== 父子组件通信示例 ===');
const userList = new UserList();
// 监听用户列表事件
userList.on('userSelected', (user) => {
console.log('User selected:', user);
});
userList.on('userUpdated', (user) => {
console.log('User updated:', user);
});
userList.on('userDeleted', (user) => {
console.log('User deleted:', user);
});
// 挂载到页面
const container = document.getElementById('app') || document.body;
userList.mount(container);兄弟组件通信需要通过中介来实现,最常见的是通过共同的父组件:
// 🎉 全局事件总线
class EventBus extends EventEmitter {
constructor() {
super();
this.namespaces = new Map();
}
// 创建命名空间
namespace(name) {
if (!this.namespaces.has(name)) {
this.namespaces.set(name, new EventEmitter());
}
return this.namespaces.get(name);
}
// 全局广播
broadcast(event, data) {
this.emit(event, data);
// 同时向所有命名空间广播
this.namespaces.forEach(ns => {
ns.emit(event, data);
});
}
// 获取统计信息
getStats() {
return {
globalListeners: this.events.size,
namespaces: this.namespaces.size,
totalListeners: Array.from(this.namespaces.values())
.reduce((total, ns) => total + ns.events.size, this.events.size)
};
}
}
// 创建全局事件总线实例
const globalEventBus = new EventBus();
// 🎉 购物车组件(兄弟组件1)
class ShoppingCart extends Component {
initializeState() {
this.state = {
items: [],
total: 0,
visible: false
};
// 订阅全局事件
this.setupEventListeners();
}
setupEventListeners() {
// 监听添加商品事件
globalEventBus.on('product:addToCart', (product) => {
this.addItem(product);
});
// 监听移除商品事件
globalEventBus.on('product:removeFromCart', (productId) => {
this.removeItem(productId);
});
// 监听购物车显示/隐藏事件
globalEventBus.on('cart:toggle', () => {
this.toggle();
});
}
render() {
const container = document.createElement('div');
container.className = `shopping-cart ${this.state.visible ? 'visible' : 'hidden'}`;
// 购物车头部
const header = document.createElement('div');
header.className = 'cart-header';
const title = document.createElement('h3');
title.textContent = `Shopping Cart (${this.state.items.length})`;
header.appendChild(title);
const toggleBtn = document.createElement('button');
toggleBtn.textContent = this.state.visible ? 'Hide' : 'Show';
toggleBtn.className = 'btn btn-secondary';
toggleBtn.addEventListener('click', () => this.toggle());
header.appendChild(toggleBtn);
container.appendChild(header);
if (this.state.visible) {
// 购物车内容
const content = document.createElement('div');
content.className = 'cart-content';
if (this.state.items.length === 0) {
const empty = document.createElement('p');
empty.textContent = 'Your cart is empty';
empty.className = 'cart-empty';
content.appendChild(empty);
} else {
// 商品列表
const itemsList = document.createElement('div');
itemsList.className = 'cart-items';
this.state.items.forEach(item => {
const itemElement = this.renderCartItem(item);
itemsList.appendChild(itemElement);
});
content.appendChild(itemsList);
// 总计
const total = document.createElement('div');
total.className = 'cart-total';
total.innerHTML = `<strong>Total: $${this.state.total.toFixed(2)}</strong>`;
content.appendChild(total);
// 结账按钮
const checkoutBtn = document.createElement('button');
checkoutBtn.textContent = 'Checkout';
checkoutBtn.className = 'btn btn-primary';
checkoutBtn.addEventListener('click', () => this.checkout());
content.appendChild(checkoutBtn);
}
container.appendChild(content);
}
return container;
}
renderCartItem(item) {
const itemDiv = document.createElement('div');
itemDiv.className = 'cart-item';
const info = document.createElement('div');
info.className = 'item-info';
info.innerHTML = `
<h4>${item.name}</h4>
<p>$${item.price.toFixed(2)} x ${item.quantity}</p>
`;
itemDiv.appendChild(info);
const actions = document.createElement('div');
actions.className = 'item-actions';
const decreaseBtn = document.createElement('button');
decreaseBtn.textContent = '-';
decreaseBtn.className = 'btn btn-sm';
decreaseBtn.addEventListener('click', () => this.updateQuantity(item.id, item.quantity - 1));
actions.appendChild(decreaseBtn);
const quantity = document.createElement('span');
quantity.textContent = item.quantity;
quantity.className = 'quantity';
actions.appendChild(quantity);
const increaseBtn = document.createElement('button');
increaseBtn.textContent = '+';
increaseBtn.className = 'btn btn-sm';
increaseBtn.addEventListener('click', () => this.updateQuantity(item.id, item.quantity + 1));
actions.appendChild(increaseBtn);
const removeBtn = document.createElement('button');
removeBtn.textContent = 'Remove';
removeBtn.className = 'btn btn-danger btn-sm';
removeBtn.addEventListener('click', () => this.removeItem(item.id));
actions.appendChild(removeBtn);
itemDiv.appendChild(actions);
return itemDiv;
}
addItem(product) {
const existingItem = this.state.items.find(item => item.id === product.id);
let updatedItems;
if (existingItem) {
updatedItems = this.state.items.map(item =>
item.id === product.id
? { ...item, quantity: item.quantity + 1 }
: item
);
} else {
updatedItems = [...this.state.items, { ...product, quantity: 1 }];
}
const total = this.calculateTotal(updatedItems);
this.setState({ items: updatedItems, total });
// 通知其他组件购物车已更新
globalEventBus.emit('cart:updated', {
items: updatedItems,
total,
itemCount: updatedItems.reduce((sum, item) => sum + item.quantity, 0)
});
}
removeItem(productId) {
const updatedItems = this.state.items.filter(item => item.id !== productId);
const total = this.calculateTotal(updatedItems);
this.setState({ items: updatedItems, total });
globalEventBus.emit('cart:updated', {
items: updatedItems,
total,
itemCount: updatedItems.reduce((sum, item) => sum + item.quantity, 0)
});
}
updateQuantity(productId, newQuantity) {
if (newQuantity <= 0) {
this.removeItem(productId);
return;
}
const updatedItems = this.state.items.map(item =>
item.id === productId
? { ...item, quantity: newQuantity }
: item
);
const total = this.calculateTotal(updatedItems);
this.setState({ items: updatedItems, total });
globalEventBus.emit('cart:updated', {
items: updatedItems,
total,
itemCount: updatedItems.reduce((sum, item) => sum + item.quantity, 0)
});
}
calculateTotal(items) {
return items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
}
toggle() {
this.setState({ visible: !this.state.visible });
}
checkout() {
if (this.state.items.length === 0) {
alert('Your cart is empty!');
return;
}
// 触发结账事件
globalEventBus.emit('cart:checkout', {
items: this.state.items,
total: this.state.total
});
// 清空购物车
this.setState({ items: [], total: 0 });
alert(`Checkout completed! Total: $${this.state.total.toFixed(2)}`);
}
}
// 🎉 商品列表组件(兄弟组件2)
class ProductList extends Component {
initializeState() {
this.state = {
products: [
{ id: 1, name: 'Laptop', price: 999.99, category: 'Electronics' },
{ id: 2, name: 'Mouse', price: 29.99, category: 'Electronics' },
{ id: 3, name: 'Keyboard', price: 79.99, category: 'Electronics' },
{ id: 4, name: 'Monitor', price: 299.99, category: 'Electronics' },
{ id: 5, name: 'Headphones', price: 149.99, category: 'Electronics' }
],
cartItemCount: 0
};
this.setupEventListeners();
}
setupEventListeners() {
// 监听购物车更新事件
globalEventBus.on('cart:updated', (cartData) => {
this.setState({ cartItemCount: cartData.itemCount });
});
// 监听结账事件
globalEventBus.on('cart:checkout', (checkoutData) => {
console.log('Checkout completed:', checkoutData);
// 可以在这里更新库存等
});
}
render() {
const container = document.createElement('div');
container.className = 'product-list';
// 标题和购物车状态
const header = document.createElement('div');
header.className = 'product-header';
const title = document.createElement('h2');
title.textContent = 'Products';
header.appendChild(title);
const cartStatus = document.createElement('div');
cartStatus.className = 'cart-status';
cartStatus.innerHTML = `
<span>Cart: ${this.state.cartItemCount} items</span>
<button class="btn btn-primary" onclick="globalEventBus.emit('cart:toggle')">
Toggle Cart
</button>
`;
header.appendChild(cartStatus);
container.appendChild(header);
// 商品网格
const grid = document.createElement('div');
grid.className = 'product-grid';
this.state.products.forEach(product => {
const productCard = this.renderProductCard(product);
grid.appendChild(productCard);
});
container.appendChild(grid);
return container;
}
renderProductCard(product) {
const card = document.createElement('div');
card.className = 'product-card';
const name = document.createElement('h3');
name.textContent = product.name;
card.appendChild(name);
const category = document.createElement('p');
category.textContent = product.category;
category.className = 'product-category';
card.appendChild(category);
const price = document.createElement('p');
price.textContent = `$${product.price.toFixed(2)}`;
price.className = 'product-price';
card.appendChild(price);
const addBtn = document.createElement('button');
addBtn.textContent = 'Add to Cart';
addBtn.className = 'btn btn-primary';
addBtn.addEventListener('click', () => this.addToCart(product));
card.appendChild(addBtn);
return card;
}
addToCart(product) {
// 通过事件总线通知购物车组件
globalEventBus.emit('product:addToCart', product);
// 显示添加成功的反馈
this.showAddedFeedback(product);
}
showAddedFeedback(product) {
// 创建临时提示
const feedback = document.createElement('div');
feedback.className = 'add-feedback';
feedback.textContent = `${product.name} added to cart!`;
feedback.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: #4CAF50;
color: white;
padding: 10px 20px;
border-radius: 4px;
z-index: 1000;
`;
document.body.appendChild(feedback);
// 3秒后移除
setTimeout(() => {
if (feedback.parentNode) {
feedback.parentNode.removeChild(feedback);
}
}, 3000);
}
}
// 使用示例
console.log('=== 兄弟组件通信示例 ===');
const productList = new ProductList();
const shoppingCart = new ShoppingCart();
// 创建应用容器
const appContainer = document.createElement('div');
appContainer.className = 'app-container';
const productContainer = document.createElement('div');
productContainer.className = 'product-section';
productList.mount(productContainer);
const cartContainer = document.createElement('div');
cartContainer.className = 'cart-section';
shoppingCart.mount(cartContainer);
appContainer.appendChild(productContainer);
appContainer.appendChild(cartContainer);
const mainContainer = document.getElementById('app') || document.body;
mainContainer.appendChild(appContainer);
// 监听全局事件
globalEventBus.on('cart:updated', (data) => {
console.log('Cart updated globally:', data);
});
console.log('Event bus stats:', globalEventBus.getStats());兄弟组件通信的核心模式:
💼 实际应用数据:合理的组件通信设计可以减少40%的组件耦合度,提升50%的代码可维护性,同时使数据流向更加清晰和可预测。
通过本节JavaScript组件通信模式完整教程的学习,你已经掌握:
A: 根据组件关系选择:父子组件用props和回调;兄弟组件用事件总线或状态提升;跨层级组件用Context或全局状态管理。
A: 合理使用不会有问题。注意及时清理事件监听器,避免内存泄漏;使用命名空间避免事件冲突;对频繁触发的事件进行节流处理。
A: 当多个不相关组件需要共享状态、状态变化逻辑复杂、需要状态持久化或时间旅行调试时,考虑使用全局状态管理。
A: 明确数据流向,遵循单向数据流原则;使用中介者模式解耦组件;避免双向绑定,使用事件通知代替直接调用。
A: 保持数据流向清晰;最小化组件间的耦合;使用类型检查确保数据正确性;提供清晰的API文档;及时清理事件监听器。
// 问题:组件销毁时没有清理事件监听器
// 解决:实现自动清理机制
class SafeComponent extends Component {
constructor(props) {
super(props);
this.eventCleanups = [];
}
safeOn(emitter, event, callback) {
emitter.on(event, callback);
// 记录清理函数
const cleanup = () => emitter.off(event, callback);
this.eventCleanups.push(cleanup);
return cleanup;
}
beforeUnmount() {
// 清理所有事件监听器
this.eventCleanups.forEach(cleanup => cleanup());
this.eventCleanups = [];
}
}// 问题:多个组件间的数据状态不同步
// 解决:实现数据同步机制
class DataSyncManager {
constructor() {
this.data = {};
this.subscribers = new Map();
}
subscribe(key, callback) {
if (!this.subscribers.has(key)) {
this.subscribers.set(key, []);
}
this.subscribers.get(key).push(callback);
// 立即同步当前数据
if (this.data[key] !== undefined) {
callback(this.data[key]);
}
}
update(key, value) {
this.data[key] = value;
// 通知所有订阅者
if (this.subscribers.has(key)) {
this.subscribers.get(key).forEach(callback => {
callback(value);
});
}
}
}"掌握组件通信模式,构建高效协作的组件系统。通过合理的通信设计,让组件间的数据流动变得清晰和可控!"