可以向子组件传递数据 prop,同样可以向子组件传递 event prop 即函数 prop。
数据 prop 实现向下通信, 函数 prop 实现向上通信。
要实现向上通信,先在父组件中定义函数以及形参,然后,以函数指针的形式( 也就是不加括号,不带参数),以属性传递给子组件,由子组件提供对应实参并调用。
举例,表单提交数据,然后通过中间组件传递给App.js:
ExpenseForm -> NewExpense -> App,
// App.js
import React from "react";
import NewExpense from "./components/NewExpense/NewExpense";
import Expenses from "./components/Expenses/Expenses";
const App = () => {
const expenses = [
{
id: "e4",
title: "New Desk (Wooden)",
amount: 450,
date: new Date(2021, 5, 12),
},
];
//-----------------------------------------
// 这里, 能获得第3层组件的提交的数据expense
const addExpenseHandler=(expense) => {
console.log('In App.js');
console.log(expense);
}
//------------------------------------------
return (
<div>
<NewExpense onAddExpense={addExpenseHandler} />
<Expenses expenses={expenses} />
</div>
);
};
export default App;
// NewExpense.js
import React from "react";
import "./NewExpense.css";
import ExpenseForm from "./ExpenseForm";
const NewExpense = (props) => {
//----------------------------------------------
// 此函数提供给 ExpenseForm 调用,
// 实参由 ExpenseForm 提供。
const saveExpenseDataHandler = (enteredExpenseData) => {
const expenseData = {
...enteredExpenseData,
id: Math.random().toString(),
};
props.onAddExpense(expenseData);
};
//-----------------------------------------------
return (
<div className="new-expense">
<ExpenseForm onSaveExpenseData={saveExpenseDataHandler} />
</div>
);
};
export default NewExpense;
// ExpenseForm.js
import React, { useState } from "react";
import "./ExpenseForm.css";
const ExpenseForm = (props) => {
// const [userInput, setUserInput] = useState({
// enteredTitle: "",
// enteredAmount: "",
// enteredDate: "",
// });
// const titleChangeHandler = (event) => {
// setUserInput({ ...userInput, enteredTitle: event.target.value });
// };
// const titleChangeHandler = (event) => {
// // 调用函数更新状态是安全的写法!
// setUserInput((prevState) => {
// return { ...userInput, enteredTitle: event.target.value }
// });
// };
const [enteredTitle, setEnteredTitle] = useState("");
const titleChangeHandler = (event) => {
setEnteredTitle(event.target.value);
};
const [enteredAmount, setEnteredAmount] = useState("");
const amountChangeHandler = (event) => {
setEnteredAmount(event.target.value);
};
const [enteredDate, setEnteredDate] = useState("");
const dateChangeHandler = (event) => {
setEnteredDate(event.target.value);
};
const submitHandler = (event) => {
event.preventDefault();
const ExpenseData = {
title: enteredTitle,
amount: enteredAmount,
date: new Date(enteredDate),
};
//----------------------------------
// 调用上层函数!
props.onSaveExpenseData(ExpenseData);
//----------------------------------
setEnteredTitle("");
setEnteredAmount("");
setEnteredDate("");
};
return (
<form onSubmit={submitHandler}>
<div className="new-expense__controls">
<div className="new-expense__control">
<label>Title</label>
<input
type="text"
value={enteredTitle}
onChange={titleChangeHandler}
/>
</div>
<div className="new-expense__control">
<label>Amount</label>
<input
type="number"
min="0.01"
step="0.01"
value={enteredAmount}
onChange={amountChangeHandler}
/>
</div>
<div className="new-expense__control">
<label>Date</label>
<input
type="date"
min="2019-01-01"
max="2022-12-31"
value={enteredDate}
onChange={dateChangeHandler}
/>
</div>
</div>
<div className="new-expense__actions">
<button type="submit">Add Expense</button>
</div>
</form>
);
};
export default ExpenseForm;
与之相比较,Vue 通过 this.$emit()
方法发出事件,实现向上通信。