菜鸟教程 -- 学的不仅是技术,更是梦想!

React 教程
(追記) (追記ここまで)

React Props

在 React 中,Props(属性)是用于将数据从父组件传递到子组件的机制,Props 是只读的,子组件不能直接修改它们,而是应该由父组件来管理和更新。

state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。


使用 Props

传递 Props 语法:

<ComponentName propName={propValue} />

以下实例演示了如何在组件中使用 props:

React 实例

functionHelloMessage(props){return <h1>Hello{props.name}!</h1>; }constelement = <HelloMessagename="Runoob"/>; constroot = ReactDOM.createRoot(document.getElementById("root")); root.render(element);

尝试一下 »

实例中 name 属性通过 props.name 来获取。


默认 Props

你可以通过组件类的 defaultProps 属性为 props 设置默认值,实例如下:

React 实例

classHelloMessageextendsReact.Component{render(){return( <h1>Hello, {this.props.name}</h1> ); }}HelloMessage.defaultProps = {name: 'Runoob'}; constelement = <HelloMessage/>; constroot = ReactDOM.createRoot(document.getElementById("root")); root.render(element);

尝试一下 »

多个 Props

可以传递多个属性给子组件。

实例

const UserCard = (props) => {
return (
<div>
<h2>{props.name}</h2>
<p>Age: {props.age}</p>
<p>Location: {props.location}</p>
</div>
);
};

const App = () => {
return (
<UserCard name="Alice" age={25} location="New York" />
);
};

ReactDOM.render(<App />, document.getElementById('root'));

propTypes 验证

propTypes 是 React 提供的一种工具,用于对组件的 props 进行类型检查。

可以使用 prop-types 库对组件的 props 进行类型检查。

在 React 中,propTypes 作为组件的一个静态属性来定义。首先,你需要安装 prop-types 包:

npm install prop-types

然后,在你的组件文件中引入 prop-types,并定义 propTypes 属性。下面是一个示例

实例

import PropTypes from 'prop-types';

const Greeting = (props) => {
return <h1>Hello, {props.name}!</h1>;
};

Greeting.propTypes = {
name: PropTypes.string.isRequired
};

const App = () => {
return (
<div>
<Greeting name="Alice" />
{/* <Greeting /> // 这行代码会导致控制台警告,因为 name 是必需的 */}
</div>
);
};

ReactDOM.render(<App />, document.getElementById('root'));

传递回调函数作为 Props

可以将函数作为 props 传递给子组件,子组件可以调用这些函数来与父组件进行通信。

实例

class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.state = { message: '' };
}

handleMessage = (msg) => {
this.setState({ message: msg });
};

render() {
return (
<div>
<ChildComponent onMessage={this.handleMessage} />
<p>Message from Child: {this.state.message}</p>
</div>
);
}
}

const ChildComponent = (props) => {
const sendMessage = () => {
props.onMessage('Hello from Child!');
};

return (
<div>
<button onClick={sendMessage}>Send Message</button>
</div>
);
};

ReactDOM.render(<ParentComponent />, document.getElementById('root'));

解构 Props

在函数组件中,可以通过解构 props 来简化代码。

实例

const Greeting = ({ name }) => {
return <h1>Hello, {name}!</h1>;
};

const App = () => {
return <Greeting name="Alice" />;
};

ReactDOM.render(<App />, document.getElementById('root'));

小结

  • 传递和使用 Props:父组件传递数据给子组件,子组件通过 props 接收。
  • 默认 Props:使用 defaultProps 设置组件的默认属性值。
  • PropTypes 验证:使用 prop-types 库对 props 进行类型检查。
  • 传递回调函数:父组件可以将函数作为 props 传递给子组件,以实现组件间通信。
  • 解构 Props:在函数组件中解构 props 以简化代码。

State 和 Props

以下实例演示了如何在应用中组合使用 state 和 props 。我们可以在父组件中设置 state, 并通过在子组件上使用 props 将其传递到子组件上。在 render 函数中, 我们设置 name 和 site 来获取父组件传递过来的数据。

React 实例

classWebSiteextendsReact.Component{constructor(){super(); this.state = {name: "菜鸟教程", site: "https://www.runoob.com"}}render(){return( <div> <Namename={this.state.name} /> <Linksite={this.state.site} /> </div> ); }}classNameextendsReact.Component{render(){return( <h1>{this.props.name}</h1> ); }}classLinkextendsReact.Component{render(){return( <ahref={this.props.site}> {this.props.site} </a> ); }}constroot = ReactDOM.createRoot(document.getElementById("root")); root.render( <WebSite /> );

尝试一下 »

Props 验证

React.PropTypes 在 React v15.5 版本后已经移到了 prop-types 库。

<script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/prop-types/15.8.1/prop-types.min.js" type="application/javascript"></script>

Props 验证使用 propTypes,它可以保证我们的应用组件被正确使用,React.PropTypes 提供很多验证器 (validator) 来验证传入数据是否有效。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。

以下实例创建一个 Mytitle 组件,属性 title 是必须的且是字符串,非字符串类型会自动转换为字符串 :

React 16.4 实例

vartitle = "菜鸟教程"; // var title = 123;classMyTitleextendsReact.Component{render(){return( <h1>Hello, {this.props.title}</h1> ); }}MyTitle.propTypes = {title: PropTypes.string}; constroot = ReactDOM.createRoot(document.getElementById("root")); root.render( <MyTitletitle={title} /> );

尝试一下 »

React 15.4 实例

vartitle = "菜鸟教程"; // var title = 123;varMyTitle = React.createClass({propTypes: {title: React.PropTypes.string.isRequired, }, render: function(){return <h1> {this.props.title} </h1>; }}); constroot = ReactDOM.createRoot(document.getElementById("root")); root.render( <MyTitletitle={title} /> );

尝试一下 »

当然,可以为你介绍更多的 PropTypes 验证器以及如何使用它们。以下是一些常用的 PropTypes 验证器说明:

基本数据类型

  • PropTypes.string:字符串
  • PropTypes.number:数字
  • PropTypes.boolean:布尔值
  • PropTypes.object:对象
  • PropTypes.array:数组
  • PropTypes.func:函数
  • PropTypes.symbol:Symbol

特殊类型

  • PropTypes.node:任何可以被渲染的内容:数字、字符串、元素或数组(包括这些类型)
  • PropTypes.element:React元素
  • PropTypes.instanceOf(Class):某个类的实例

组合类型

  • PropTypes.oneOf(['option1', 'option2']):枚举类型,值必须是所提供选项之一
  • PropTypes.oneOfType([PropTypes.string, PropTypes.number]):多个类型中的一个
  • PropTypes.arrayOf(PropTypes.number):某种类型组成的数组
  • PropTypes.objectOf(PropTypes.number):某种类型组成的对象
  • PropTypes.shape({ key: PropTypes.string, value: PropTypes.number }):具有特定形状的对象

其他

  • PropTypes.any:任何类型
  • PropTypes.exact({ key: PropTypes.string }):具有特定键的对象,且不能有其他多余的键

以下是一些示例代码,展示了如何使用不同的 PropTypes 验证器:

实例

import React from 'react';
import ReactDOM from 'react-dom/client';
import PropTypes from 'prop-types';

class MyComponent extends React.Component {
static propTypes = {
title: PropTypes.string.isRequired, // 必须是字符串且必需
age: PropTypes.number, // 可选的数字
isAdmin: PropTypes.bool, // 可选的布尔值
user: PropTypes.shape({ // 必须是具有特定形状的对象
name: PropTypes.string,
email: PropTypes.string
}),
items: PropTypes.arrayOf(PropTypes.string), // 必须是字符串数组
callback: PropTypes.func, // 可选的函数
children: PropTypes.node, // 可选的可以渲染的内容
options: PropTypes.oneOf(['option1', 'option2']), // 必须是特定值之一
};

render() {
return (
<div>
<h1>{this.props.title}</h1>
{this.props.age && <p>Age: {this.props.age}</p>}
{this.props.isAdmin && <p>Admin</p>}
{this.props.user && (
<div>
<p>Name: {this.props.user.name}</p>
<p>Email: {this.props.user.email}</p>
</div>
)}
{this.props.items && (
<ul>
{this.props.items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
)}
{this.props.callback && (
<button onClick={this.props.callback}>Click me</button>
)}
{this.props.children}
{this.props.options && <p>Option: {this.props.options}</p>}
</div>
);
}
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<MyComponent
title="Hello, World!"
age={30}
isAdmin={true}
user={{ name: "John Doe", email: "[email protected]" }}
items={['Item 1', 'Item 2', 'Item 3']}
callback={() => alert('Button clicked!')}
options="option1"
>
<p>This is a child element</p>
</MyComponent>
);
AI 思考中...

4 篇笔记 写笔记

  1. #0

    年轻的C同学

    tco***[email protected]

    25

    上次在 React 组件看到这篇笔记没看懂,原来是这里的,现在贴过来分享一下。但是自己现在还是不太懂,希望过几天再来看的时候能够明白。

    对创建多个组件的代码,做了点小修改,帮助大家理解。

    <WebSite name="菜鸟教程" site=" http://www.runoob.com" />,这种形式传入的 name 和 url 值,只能在 WebSit 组件中用 this.props.xxx 来使用。虽然原来的代码中,Name 和 Site 组件中也是以同样的形式使用的,但并不是因为这条语句的作用,而是因为 <Name name={this.props.name} /> <Link site={this.props.site} /> 。所以我特意将这几行代码做了修改,方便大家感受感受!

    WebSite 组件中:

    <Name title={this.props.name}/> 
    // 将this.props.name以title名称传给Name组件,Name通过this.props.title来使用其值
    <Url site={this.props.url}/> 
    // 将this.props.url以site名称传给Url组件,Url通过this.props.site来使用其值

    Name 组件中:

    <h1>{this.props.title}</h1>

    Site 组件中:<a href={this.props.site}>{this.props.site}</a>

    年轻的C同学

    tco***[email protected]

    8年前 (2018年08月08日)
  2. #0

    xjjuser

    xjj***[email protected]

    45

    来补充一下上面那位同学所说的。很多情况下,子控件需要父控件所有的 props 参数,这个时候我们一个一个参数的写会很麻烦,比如:

    <Name name={this.props.name} url={this.props.url} .../>

    那么我们怎么样吧父属性直接赋值给子组件的props参数呢?如下写法即可:

    <Name props={this.props}/>

    这样写就非常简洁了,也就子控件和父控件都有了同样数据结构的 props 参数。

    很多情况下我们调试页面时,看到的参数名在父控件和子控件中部一样,但是表示的值是同一个,写这段代码的人可能还记得这个参数是转译的,但是其他人阅读时就会摸不着头脑,在效率上是处于弱势的,所以我们一般建议引用父组件参数尽量保持名称不变,以便以后维护。

    xjjuser

    xjj***[email protected]

    8年前 (2018年08月10日)
  3. #0

    Props 实现父与子通信:

    import React from 'react';
    import ReactDOM from 'react-dom';
    export default class CptBody extends React.Component{
     constructor(){
     super();
     this.state = {username : "父级名称"}; //可以传json等很多格式(这个是初始化赋值)
     }
     //click事件函数
     changeAge(){
     this.setState({username:"父级名称--修改"})
     }
     //change事件函数
     changeUsername(event){
     this.setState({username:event.target.value})
     }
     render(){
     return(
     <div>
     <h1>这里是主体内容部分</h1>
     <p>{this.state.username}</p>
     <input type="button" value="点击改变username" onClick={this.changeAge.bind(this)}/>
     <BodyChild changeUsername={this.changeUsername.bind(this)}/>
     </div>
     )
     }
    }
    class BodyChild extends React.Component{
     render(){
     return(
     <div>
     <p>子页面输出:<input type='text' onChange={this.props.changeUsername} /></p>
     </div>
     )
     }
    }

    如果想实现"父级"同步"子级"的数据,则需要在子级数据发生改变的时候,调用执行父级props传来的回调,从而达到父级同步更新的效果。

    8年前 (2018年11月22日)
  4. #0

    独孤尚良

    yut***[email protected]

    35

    借助楼上的代码,做了个改良,下面的父子模块互相传递参数。

    class CptBody extends React.Component{
     constructor(){
     super();
     this.state = {username : 1}; //可以传json等很多格式(这个是初始化赋值)
     }
     //click事件函数
     changeAge(){
     this.setState({username:1+this.state.username})
     }
     //change事件函数
     changeUsername(event){
     this.setState({username:parseInt(event.target.value)})
     }
     render(){
     return(
     <div>
     <h1>下面的操作有惊喜</h1>
     <p>{this.state.username}</p>
     <input type="button" value="点击改变username" onClick={()=>this.changeAge()}/>
     <BodyChild changeUsername={this.changeUsername.bind(this)} getname={this.state.username}/>
     </div>
     )
     }
    }
    class BodyChild extends React.Component{
     render(){
     return(
     <div>
     <p>子页面输入:<input type='text' value={this.props.getname} onChange={this.props.changeUsername} /></p>
     </div>
     )
     }
    }
    ReactDOM.render(
     <CptBody />,
     document.getElementById('example')
    );

    尝试一下 »

    BodyChild 组件的 render 函数返回值 jsx 中 <p> 的 value 是从父组件获取的 getname 这个变量值,onChange 获取的是 changeUsername 这个函数,所以如果文本框中的值改变了,改变值这个事件会触发 changeUsername 这个函数,这个函数会获得事件的值,即我们文本框修改后的值,并将其赋值给父组件的 state.username 这个变量。而父组件的这个变量改变后,state 随之改变,这时候,render 会重新启动,所以我们会看到修改后的值。

    父组件的 jsx 中有一个箭头函数,有一个 bind 函数,这两者有什么区别吗?经验证,这两者是可以互换的。

    onClick={this.changeAge.bind(this)}onClick={()=>this.changeAge()} 可以互换。

    独孤尚良

    yut***[email protected]

    7年前 (2019年05月26日)

点我分享笔记

  • 昵称 (必填)
  • 邮箱 (必填)
  • 引用地址

AltStyle によって変換されたページ (->オリジナル) /