React-组件&Props
组件
函数组件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
"函数组件"本质上就是 JavaScript 函数
class组件
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
渲染组件
当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)以及子组件(children)转换为单个对象传递给组件,这个对象被称之为 “props”。
例如,这段代码会在页面上渲染 “Hello, Sara”:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
const element = <Welcome name="Sara" />;
root.render(element);
回顾一下这个例子中发生了什么:
- 调用
root.render()函数,并传入<Welcome name="Sara" />作为参数。 - React 调用
Welcome组件,并将{name: 'Sara'}作为props传入。 - Welcome 组件将
<h1>Hello, Sara</h1>元素作为返回值。 - React DOM 将 DOM 高效地更新为
<h1>Hello, Sara</h1>。
注意: 组件名称必须以大写字母开头!!!
React 会将以小写字母开头的组件视为原生 DOM 标签。例如,<div />代表 HTML 的 div 标签,而<Welcome />则代表一个组件,并且需在作用域内使用Welcome。
组合组件
组件可以在其输出中引用其他组件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
提取组件
将组件拆分为更小的组件。
参考如下Comment组件:
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
该组件由于嵌套的关系,变得难以维护,且很难复用它的各个部分。因此,让我们从中提取一些组件出来。
首先,我们将提取 Avatar 组件:
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
Avatar 不需知道它在 Comment 组件内部是如何渲染的。因此,我们给它的 props 起了一个更通用的名字:user,而不是 author。
我们建议从
组件自身的角度命名props,而不是依赖于调用组件的上下文命名。
我们现在针对 Comment 做些微小调整:
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
接下来,将提取 UserInfo 组件,该组件在用户名旁渲染 Avatar 组件:
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div> );
}
进一步简化 Comment 组件:
function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
小总结:提取组件可能繁重,但值得
Props 的只读性
组件无论是使用函数声明还是通过 class 声明,都绝不能修改自身的 props。
React 非常灵活,但它也有一个严格的规则:
所有 React 组件都必须像纯函数一样保护它们的 props 不被更改
组件通讯
父组件传递数据给子组件
- 1.父组件提供要传递的
state数据 - 2.给子组件标签添加属性,值为
state中的数据 - 3.子组件中通过
props接收父组件中传递的数据
class Parent extends React.Component{
state ={lastName:'王'}
render(){
return(
<div>
传递数据给子组件:<Child name={this.state.lastName}/>
</div>
)
}
}
function Child(props){
return<div>子组件接收到数据:{props.name}</div>
}
子组件传递数据给父组件
思路:利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数。
- 1.父组件提供一个回调函数(用于接收数据)
- 2.将该函数作为属性的值,传递给子组件
class Parent extends React.Component{
getchildMsg = (msg)=>{
console.log('接收到子组件数据',msg)
}
render(){
return(
<div>
子组件:<Child getMsg={this.getchildMsg}/>
</div>
)
}
}
- 3.子组件通过props调用回调函数
class Child extends React.Component{
state ={childMsg:'React'}
handleClick =()=>{
this.props.getMsg(this.state.childMsg)
}
render(){
return(
<button onClick={this.handleClick}>点我,给父组件传递数据</button>
)
}
}
兄弟组件
- 将共享状态提升到最近的
公共父组件中,由公共父组件管理这个状态 - 思想:
状态提升 - 公共父组件职责:
- 1.提供共享
状态 - 2.提供操作共享状态的
方法
- 1.提供共享
- 要通讯的子组件只需通过
pops接收状态或操作状态的方法
class Counter extends React.Component{
//提供共享状态
state={
count:0
}
//提供修改状态的方法
onIncrement =()=>{
this.setstate({
count:this.state.count + 1
})
}
render(){
return(
<div>
<Child1 count={this.state.count} />
<Child2 onIncrement={this.onIncrement} />
</div>
)
}
}
const child1=props =>{
return<h1>计数器:{props.count}</h1>
}
const child2=props =>{
return <button onClick={()=>props.onIncrement()}>+1</button>
}

浙公网安备 33010602011771号