飞道的博客

「React 基础」关于组件属性(props)与状态(state)的入门介绍

220人阅读  评论(0)

大家好,在上一篇文章里,我们一起学习了如何创建第一个 React 组件,我相信通过上一篇文章的学习我们已经基本熟悉了什么是 React 组件,但是还有更多关于组件的内容值得我们去深入学习。本篇文章,我将和大家一起复习下如何使用组件的属性(props)与状态(state)。

如何使用组件的属性(props)

和其它应用程序一样,组件应具备重用性。接下来我们将基于上一节的例子,分别创建以下组件:头部组件( Header), 内容组件(Content), 和底部组件(Footer),将其分组放置在 layout 文件夹中,通过 props 传递属性(属性或子组件),并验证属性值的合法性。

1、首先我们来看下 App.js 文件中的 Header部分:


   
  1. import React from 'react';
  2. import logo from '../shared/images/logo.svg';
  3. import './App.css';
  4. // 这里我们引入了 Home 组件
  5. import Home from "./Home/Home";
  6. function App() {
  7. return (
  8. <div className= "App">
  9. <header className= "App-header">
  10. <img src={logo} className= "App-logo" alt= "logo" />
  11. <a
  12. className= "App-link"
  13. href= "https://reactjs.org"
  14. target= "_blank"
  15. rel= "noopener noreferrer"
  16. >
  17. Learn React
  18. </a>
  19. </header>
  20. { /* 在这里我们添加 Home 组件在页面里进行渲染*/}
  21. <Home/>
  22. </div>
  23. );
  24. }
  25. export default App;
  26. //File: src/components/App.js

2、接下来,我们需要将 header 内容部分拿走,放到我们的 Header 组件里,然后通过 import 的方式引入到 App.js 文件中。因为类似这样的头部、尾部组件是公共布局组件,我们需要创建一个共享布局组件目录(layout)到我们的共享目录里(src/shared/components/layout)。

3、在此之前,我们需要安装 prop-types 依赖包,因为我们需要在 Header 组件里定义属性类型及相关验证逻辑,打开控制台将其运行环境切换至项目目录,并输入以下命令完成安装:

 npm install prop-types

4、PropTypes 最初是作为 React 核心模块之一一起发布的,将其应用到 React 组件中,我们用来判断组件的属性传递是否符合设置的预期,如果传递的属性与其不匹配,将会有警告提示。最终我们完成的 Header 组件代码如下:


   
  1. import React, { Component } from "react";
  2. import ProTypes from 'prop-types';
  3. import logo from '../../images/logo.svg';
  4. class Header extends Component{
  5. // 这里定影属性类型和规则
  6. static proTypes={
  7. title:ProTypes.string.isRequired,
  8. url:ProTypes.string
  9. };
  10. render() {
  11. const {
  12. title= 'Welcome to React',
  13. url= 'https://www.qianduandaren.com'
  14. } =this.props;
  15. return (
  16. <header className= "App-header">
  17. <img src={logo} className= "App-logo" alt= "logo" />
  18. <a
  19. className= "App-link"
  20. href={url}
  21. target= "_blank"
  22. rel= "noopener noreferrer"
  23. >
  24. {title}
  25. </a>
  26. </header>
  27. );
  28. }
  29. }
  30. export default Header;
  31. //File: src/shared/components/layout/Header.js

5、通过定义静态 PropTypes 属性对象用来验证是否符合预期,你可以定义相关的属性类型 array, bool, func, number, object, string, 和 symbol。除了这些基本类型,你还可以定义一些特殊的类型,比如 node, element, instanceOf, oneOf, oneOfType, arrayOf, objectOf, shape 和 any 等。我们可以在任何类型后添加一个 isRequired 的属性,用来验证这个类型属性是否定义,如果未定义,则会产生警告。

6、然后我们将 Header 组件添加至 App.js 文件中


   
  1. import React from 'react';
  2. import './App.css';
  3. import Header from "../shared/components/Header/Header";
  4. // 这里我们引入了 Home 组件
  5. import Home from "./Home/Home";
  6. function App() {
  7. return (
  8. <div className= "App">
  9. <Header title= "欢迎来到前端达人官网"/>
  10. { /* 在这里我们添加 Home 组件在页面里进行渲染*/}
  11. <Home/>
  12. </div>
  13. );
  14. }
  15. export default App;
  16. //File: src/components/App.js

小贴士:你有可能会对 <Header/> 感到迷惑,这里不同于 HTML5 的 标签,这也是为什么 React 最佳实践中要求类名或组件名首字母大写的原因吧。

7、需要给组件传递什么属性,你需要在props这个属性里进行定义,你可能注意到了我们值添加了 title 属性,因为这是唯一需要要定义的属性,url 属性是可选的,并且我们已通过解构赋值的方法将其默认赋值,这里属性值为:https://www.qianduandaren.com。接下来我们在做个尝试,如果我们将title属性和值都删掉,看看会发生什么,你会在浏览器开发者工具中看到如下图所示的提示:

8、接下来我们来创建公共底部组件Footer,示例代码如下


   
  1. import React,{Component} from "react";
  2. class Footer extends Component{
  3. render() {
  4. return (
  5. <footer>
  6. &copy; 前端达人 {( new Date()).getFullYear()}
  7. </footer>
  8. );
  9. }
  10. }
  11. export default Footer;
  12. //File: src/shared/components/layout/Footer.js

9、到目前为止,我们只是简单的向组件传递了基本的属性类型,但是我们还可以将组件作为属性值进行传递(<Component>Children Content</Component>),接下来我们来创建一个Content组件,并将 Home 做为子元素进行传递,示例代码如下:


   
  1. import React,{Component} from 'react';
  2. import Protypes from 'prop-types';
  3. class Content extends Component{
  4. static proTypes={
  5. children:Protypes.element.isRequired
  6. };
  7. render(){
  8. const { children } = this.props;
  9. return(
  10. <main>
  11. {children}
  12. </main>
  13. )
  14. }
  15. }
  16. export default Content;
  17. // File: src/shared/components/layout/Content.js

10、最后,我们来修改 App.js 文件,示例代码如下:


   
  1. import React from 'react';
  2. import './App.css';
  3. // 引入布局相关的组件
  4. import Header from "../shared/components/Header/Header";
  5. import Content from "../shared/components/Content/Content";
  6. import Footer from "../shared/components/Footer/Footer";
  7. // 这里我们引入了 Home 组件
  8. import Home from "./Home/Home";
  9. function App() {
  10. return (
  11. <div className= "App">
  12. <Header title= "前端达人"/>
  13. <Content>
  14. <Home/>
  15. </Content>
  16. <Footer/>
  17. </div>
  18. );
  19. }
  20. export default App;
  21. // File: src/components/App.js

本部分内容小节

PropTypes 验证对于开发人员非常重要,因为我们需要规范定义我们组件接收的属性类型,并严格验证是否符合预期,如果你按照上述流程操作完成,你将会看到如下图所示的内容:

如你所见,我们有很多方法去传递属性给组件,同时还存在很多方法接收值,比如 Redux 和 React Router,我将会在接下来的文章里进行介绍。

如何使用状态(state)

local state 是 React 的基本功能,用于创建动态组件。每个组件都可以设置自己的 local state,你可以在组件内部初始化值,值如果发生改变时,将触发组件重新渲染。Local state 可以用于组件内部的 DOM 交互,表单的处理。如果我们想在不同组件之间共享数据,我们可以使用 Redux 状态管理,在接下来的文章里,我将会详细介绍。好了,废话不多说,我们来看看如何使用 local state 的。

我们先来为组件定义初始化状态,看看其状态更新时组件是如何渲染的。

1、我们基于 Home 组件,添加一个构造函数,并在内部定义状态并进行初始化。


   
  1. import React,{Component} from "react";
  2. // 在这里引入我们创建的 Home.css 文件
  3. import './Home.css';
  4. export default class Home extends Component{
  5. constructor() {
  6. // 请注意 super() 方法需在最前面定义,必须定义
  7. // 否则无法调用 this
  8. super();
  9. // 这里初始化本地状态对象
  10. this.state={
  11. name: '阿森'
  12. };
  13. }
  14. render() {
  15. //声明样式对象
  16. const buttonStyle={
  17. backgroundColor: 'gray',
  18. border: '1px solid black'
  19. };
  20. return(
  21. <div className= "Home">
  22. <h1>Welcome to Codejobs</h1>
  23. <p>
  24. In this recipe you will learn how to add styles to
  25. components. If you want to learn more you can visit
  26. our Channel at
  27. <a href= "https://www.qianduandaren.com"> 前端达人</a>.
  28. </p>
  29. <p>
  30. 大家好,我叫{this.state.name},欢迎来到前端达人!
  31. </p>
  32. <p>
  33. <button style={buttonStyle}>
  34. Click me!
  35. </button>
  36. </p>
  37. </div>
  38. );
  39. }
  40. }
  41. // File: src/components/Home/Home.js

2、在上述代码中,我们定义了一个构造函数,并初始化了我们的本地状态,并在界面中,直接进行输出显示。请注意我们在构造函数的开头调用了super()函数,主要用于调用父构造函数(React.Component),如果你不调用的话,将会收到以下错误内容:

3、在添加 super()函数 之后,我们添加了初始化状态对象:


   
  1. this.state={
  2. name: '阿森'
  3. };

4、接下来我们使用 this.setState() 方法来更新本地状态,目前的组件只是一个静态的组件,无法完成交互和渲染。要实现状态的更新,我们需要使用 this.setState() 方法进行状态的更新,这里我们使用 setTimeout() 函数进行状态的更新,示例代码如下:


   
  1. import React,{Component} from "react";
  2. // 在这里引入我们创建的 Home.css 文件
  3. import './Home.css';
  4. export default class Home extends Component{
  5. constructor() {
  6. // 请注意 super() 方法需在最前面定义,必须定义
  7. // 否则无法调用 this
  8. super();
  9. // 这里初始化本地状态对象
  10. this.state={
  11. name: '阿森'
  12. };
  13. }
  14. render() {
  15. //声明样式对象
  16. const buttonStyle={
  17. backgroundColor: 'gray',
  18. border: '1px solid black'
  19. };
  20. setTimeout(()=> {
  21. this.setState({
  22. name: '前端达人'
  23. });
  24. }, 1000);
  25. console.log( 'Name',this.state.name);
  26. return(
  27. <div className= "Home">
  28. <h1>Welcome to Codejobs</h1>
  29. <p>
  30. In this recipe you will learn how to add styles to
  31. components. If you want to learn more you can visit
  32. our Channel at
  33. <a href= "https://www.qianduandaren.com"> 前端达人</a>.
  34. </p>
  35. <p>
  36. 大家好,我叫{this.state.name},欢迎来到前端达人!
  37. </p>
  38. <p>
  39. <button style={buttonStyle}>
  40. Click me!
  41. </button>
  42. </p>
  43. </div>
  44. );
  45. }
  46. }
  47. // File: src/components/Home/Home.js

5、如果你在浏览器中运行它,你将会看到状态的第一个值是“阿森”,此后每一秒钟打印出“前端达人”的值,主要是我添加了一个console.log() 方法用来记录状态值的改变,如下图所示,你在控制台将会看到以下内容:

6、你可能会疑惑,为啥有这么多的打印输出,道理很简单,这是React的工作方式,每次我们更新状态时,都会导致组件重新渲染,每次渲染时,就会再次调用我们的 setTimeout() 方法,这样就导致了无限循环,一直的调用下去。这样势必会影响程序的性能,我们应该避免这样调用。那我们应该在哪合理安全只调用一次呢,这里我们用到了组件的生命周期方法,componentDidMount()方法(在组件已经完全加载到网页上才会调用被执行,所以可以保证数据的加载。此外,在这方法中调用setState方法,会触发重渲染,所以,官方设计这个方法就是用来加载外部数据用的,或处理其他的副作用代码)。关于组件生命周期的内容,在后面的文章里我会详细介绍到,这里我们只是先简单的了解下其中的一个方法,修改后的代码如下:


   
  1. import React,{Component} from "react";
  2. // 在这里引入我们创建的 Home.css 文件
  3. import './Home.css';
  4. export default class Home extends Component{
  5. constructor() {
  6. // 请注意 super() 方法需在最前面定义,必须定义
  7. // 否则无法调用 this
  8. super();
  9. // 这里初始化本地状态对象
  10. this.state={
  11. name: '阿森'
  12. };
  13. }
  14. componentDidMount() {
  15. setTimeout(()=> {
  16. this.setState({
  17. name: '前端达人'
  18. });
  19. }, 1000);
  20. }
  21. render() {
  22. //声明样式对象
  23. const buttonStyle={
  24. backgroundColor: 'gray',
  25. border: '1px solid black'
  26. };
  27. return(
  28. <div className= "Home">
  29. <h1>Welcome to Codejobs</h1>
  30. <p>
  31. In this recipe you will learn how to add styles to
  32. components. If you want to learn more you can visit
  33. our Channel at
  34. <a href= "https://www.qianduandaren.com"> 前端达人</a>.
  35. </p>
  36. <p>
  37. 大家好,我叫{this.state.name},欢迎来到前端达人!
  38. </p>
  39. <p>
  40. <button style={buttonStyle}>
  41. Click me!
  42. </button>
  43. </p>
  44. </div>
  45. );
  46. }
  47. }
  48. // File: src/components/Home/Home.js

7、如果你打开浏览器开发者工具,你将会在控制台看到如下输出,从而验证是否解决了无限循环打印输出的问题:

本部分小节

本地状态还经常被用于表单内容部分,这部分内容我将会在稍后的文章进行详细介绍,从上述代码中我们了解如何使用componentDidMount()方法避免无限循环的问题,这属于组件生命周期的相关内容,这部分的内容我将通过做实例的方式,进行一一详解,敬请期待。

小节

本篇文章的内容,就给大家介绍到这里,感谢你的阅读,下篇文章里我将会和大家一起学习下如何声明函数组件,敬请期待...

React基础相关文章

在 React 项目中使用 ES6,你需要了解这些(文末送漂亮的 React Redux 后台模板源码)

React 16 中的这几个新特性值得你关注(文末送漂亮的 React Redux 后台模板源码)

在 Windows 下使用 React , 你需要注意这些问题

从创建第一个React组件开始学起

专注分享当下最实用的前端技术。关注前端达人,与达人一起学习进步!

长按关注"前端达人"


转载:https://blog.csdn.net/Ed7zgeE9X/article/details/103725134
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场