当前位置:   article > 正文

React组件定义种类,容器型组件,展示型(UI)组件,受控组件,props和state的区别,setState_react的类型定义

react的类型定义

创建组件有两种方法

注意:用function构造函数创建无状态组件,只有props,无自己的私有数据和生命周期---用的不多;  

注意:class关键字创建有状态组件,有自己的私有属性(this.state)和声明周期---用的比较多

有状态组件和无状态组件的本质区别有无state属性、有无生命周期

 

类组件(class component)和函数式组件(functional component)的区别

1)当组件只是接受props属性,并将组件自身渲染到页面,用纯函数定义----展示组件

2)类组件---容器型组件,用ES6的class关键字创建,有自身的状态、生命周期钩子。让组件直接访问store,维持状态

 

什么情况下使用有状态组件?什么情况下使用无状态组件?

1)一个组件需要有自己的私有数据(this.state),推荐使用class创建的有状态组件

2)一个组件不需要有自己的私有数据,推荐使用function创建的无状态组件

 

声明类组件时,如果有定义自己的属性,必须在组件的constructor()里面调用super(props)的原因

在 super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问 this.props

 

 

组件中的props和state的区别

a)props是组件的配置,props 由父组件传递给子组件,并且就子组件而言,props 是不可变的(immutable)。组件不能改变自身的 props,但是可以把其子组件的 props 放在一起(统一管理)。Props可以包含数据和回调函数

b)state中是一种数据结构,用于组件挂载时所需数据的默认值,state数据都是组件私有的(通过ajax获取回来的数据,一般都是私有数据);state中的数据可读可写,可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果;

1)只能通过setState()方法修改state的值,不能 直接修改state因为这样不会重新渲染组件;

2)this.state必须在constructor中初始化为一个对象;

3)state的更新可能是异步的,所以setState()方法最好用回调函数;

  1. //前一个状态---prevState,更新时的props
  2. this.setState((prevState, props) => ({
  3. counter: prevState.counter + props.increment
  4. }));

4)state会被合并,调用setState()的时候,将函数中的参数对象合并到当前组件的状态对象里面

 

为什么建议传递给setState()方法的参数是一个callback而不是一个object?

react为了优化性能,有可能会将多个 setState() 调用合并为一次更新(如连续多次调用setState方法,间隔短,会将多次合并为一次setState,然后利用diff算法在更新变化的部分,达到性能优化的目的)

this.props 和 this.state 的更新可能是异步的,不能依赖它们的值去计算下一个 state

 

 

无状态组件

  1. function Person(props){
  2. return (
  3. <div>
  4. <p>props.name</p>
  5. <p>props.age</p>
  6. </div>
  7. );
  8. }
  9. // 调用
  10. <Person name="jiang" age="1"/>

 

 

用ES6语法定义React组件----有状态组件

在项目中用到ajax方法,可以在项目的根目录下安装jquery

cnpm install jquery --save-dev

然后在要使用的地方引进jquery

import $ from 'jquery';

这样就可以通过全局对象,使用$对象中的方法了

 

 

Comment.js组件的内容

  1. import React,{Component} from 'react';
  2. import './css/Comment.css'
  3. class Comment extends Component{
  4. render(){
  5. return (
  6. <div className='comment'>
  7. {/* 需要从父组件哪里获得数据 */}
  8. <span className='author'>{this.props.author}</span>
  9. <div className='metadata'>
  10. <span className='date'>{this.props.date}</span>
  11. </div>
  12. {/* this.props.children的内容就是CommentList.js中的<Comment>的子节点内容 */}
  13. <div className='text'>{this.props.children}</div>
  14. </div>
  15. );
  16. }
  17. }
  18. export default Comment;

CommentList.js组件的内容

  1. import React,{Component} from 'react';
  2. import Comment from './Comment';
  3. class CommentList extends Component{
  4. render(){
  5. return (
  6. <div>
  7. {/* 这里的数据是从服务端获得数据的 */}
  8. <Comment author='jiang' date='five minutes ago'>it is a good day!</Comment>
  9. <Comment author='jiang' date='five minutes ago'>it is a good day!</Comment>
  10. <Comment author='jiang' date='five minutes ago'>it is a good day!</Comment>
  11. <Comment author='jiang' date='five minutes ago'>it is a good day!</Comment>
  12. </div>
  13. );
  14. }
  15. }
  16. export default CommentList;

以上是书写静态页面的内容,是为了将静态页面的样式给调出来。

 

下面,是模拟服务器传送回来的数据,一般获取服务器的数据请求是在App.js,在App.js下面书写模拟的数据

App.js中用一个数据json格式模拟数据

  1. import React, { Component } from 'react';
  2. import CommentBox from './comment/CommentBox';
  3. import {Container} from 'semantic-ui-react';
  4. import 'semantic-ui-cssmantic.min.css';
  5. // 模拟数据
  6. const comments = [
  7. {'author':'jiang','date':'five minutes ago','text':'it is a good weather'},
  8. {'author':'ke','date':'three minutes ago','text':'i am happy'},
  9. ];
  10. class App extends Component {
  11. render() {
  12. return (
  13. <Container style={{padding: '10px'}}>
  14. {/* 传递数据给子组件 */}
  15. <CommentBox data={comments}/>
  16. </Container>
  17. );
  18. }
  19. }
  20. export default App;

在CommentBox中接受从父组件App.js中传递归来的数据data属性

  1. import React,{Component} from 'react';
  2. import {Divider} from 'semantic-ui-react';
  3. import CommentList from './CommonList';
  4. import CommenForm from './CommentForm';
  5. class CommentBox extends Component{
  6. render(){
  7. return (
  8. <div>
  9. <h2>评论</h2>
  10. <Divider />
  11. {/* 从父组件接收数据,这里又充当父组件然后传递数据给子组件 */}
  12. <CommentList data={this.props.data}/>
  13. <CommenForm />
  14. </div>
  15. );
  16. }a
  17. }
  18. export default CommentBox;

在组件CommentList.js中接收到从父组件中传递过来的数据

  1. import React,{Component} from 'react';
  2. import Comment from './Comment';
  3. class CommentList extends Component{
  4. render(){
  5. // 循环处理接收到从父组件中传递的数据
  6. const commentNodes = this.props.data.map(comment => {
  7. return (
  8. <Comment author={comment.author} date={comment.date} key={comment.text}>
  9. {comment.text}
  10. </Comment>
  11. );
  12. });
  13. return (
  14. <div>
  15. {/* 这里的数据是从服务端获得数据的 */}
  16. {commentNodes}
  17. </div>
  18. );
  19. }
  20. }
  21. export default CommentList;

 

state属性是用于用户和UI进行交互的,也就是内容可以更改,是组件内部私有的属性,this.state初始化的时候是一个对象,然后通过this.setState()方法进行更改相应的state属性的值;从服务器得到数据,那么使用state属性存储从服务器传回来的数据,因为这个数据可能会变,所以用state来保存

 

父组件传递数据给子组件或者(子组件向父组件传递数据)使用:this.props

 

获取在浏览器中显示的元素,在tag中使用ref属性,在js中使用this.refs.[refname]获得在浏览器中显示的ui元素

  1. class CommentForm extends Component{
  2. constructor(props){
  3. super(props);
  4. this.handleSubmit = this.handleSubmit.bind(this);
  5. }
  6. handleSubmit(event){
  7. event.preventDefault();
  8. console.log('提交表单');
  9. // 在这里获取到相应的UI元素
  10. let author = this.refs.author.value,
  11. text = this.refs.text.value;
  12. console.log(author);
  13. console.log(text);
  14. }
  15. render(){
  16. return (
  17. <Form onSubmit={this.handleSubmit}>
  18. <Form.Field>
  19. <input type='text' placeholder='姓名' ref='author'/>
  20. </Form.Field>
  21. <Form.Field>
  22. {/* 使用ref属性 */}
  23. <textarea placeholder='评论' ref='text'></textarea>
  24. </Form.Field>
  25. <Button type='submit' primary size='mini'>添加评论</Button>
  26. </Form>
  27. );
  28. }
  29. }

 

子组件将数据传递给父组件---还是利用this.props属性,在父组件中CommentBox.js定义的函数会有个参数,然后将该函数在父组件中,传递给子组件CommentForm.js,在子组件中调用该方法并传递参数

比如像在表单里面,即组件CommentForm有人提交了评论,需要将评论传递给组件CommentBox,然后追加显示新的评论

父组件CommentBox.js部分代码

  1. //在父组件定义方法
  2. handleCommentSubmit(comment){
  3. console.log(comment);
  4. }
  5. render(){
  6. return (
  7. <div>
  8. <h2>评论</h2>
  9. <Divider />
  10. {/* 从父组件接收数据,这里又充当父组件然后传递数据给子组件 */}
  11. <CommentList data={this.state.data}/>
  12. {/*在父组件调用子组件,并在子组件定义属性onCommentSubmit*/}
  13. <CommenForm onCommentSubmit={this.handleCommentSubmit}/>
  14. </div>
  15. );
  16. }

子组件CommentForm.js部分代码

  1. handleSubmit(event){
  2. event.preventDefault();
  3. console.log('提交表单');
  4. // 在这里获取到相应的UI元素
  5. let author = this.refs.author.value,
  6. text = this.refs.text.value;
  7. console.log(author);
  8. console.log(text);
  9. //调用从父组件传递过来的函数,并向父组件传递参数
  10. this.props.onCommentSubmit({author,text});
  11. }
  12. <Form onSubmit={this.handleSubmit}>

 

展示组件(presentational component)和容器组件(container component)的区别

1)展示组件就是UI组件,一般用函数式组件定义,负责DOM的显示,数据通过展示组件传过来,通过props属性接受数据和回调(props属性是只读属性),并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态不是数据的状态

2)容器组件用类组件定义,经常是有状态的,是(其它组件的)数据源,负责页面的逻辑,更关心组件是如何运作的。容器组件会为展示组件或者其它容器组件提供数据和行为(behavior),它们会调用 Flux actions,并将其作为回调提供给展示组件

 

受控组件(controlled component)

包含表单元素的组件将会在 state 追踪输入的值,并且每次调用回调函数时,如 onChange 会更新 state重新渲染组件

一个输入表单元素,它的值通过 React 的这种方式来控制,这样的元素就被称为"受控元素"

 

高阶组件(higher  order  component)

高阶组件是一个以组件为参数返回一个新组件的函数

 

 

 

 

 

 

 

 

 

 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/63392?site
推荐阅读
相关标签
  

闽ICP备14008679号