react核心概念-组件

组件和组件属性

[传送门](组件 & Props – React (reactjs.org))
组件:包含内容、样式和功能的UI单元

创建一个组件

特别注意:组件的名称首字母必须大写

如果你的组件的名称首字母小写了,react会认为这个一个普通的react元素,在组件中可以使用的很多属性就无法在你的组件中使用了

  1. 函数组件

返回一个React元素
(1).定义一个函数组件

import React from 'react'

export default function MyFuncComp(props) {
    // return <h1>函数组件的内容</h1>
    return <h1>函数组件,目前的数字:{props.number}</h1>
}

(2).函数组件的用法
a.当成普通函数来调用
比如以下案例:

import React from "react";
import ReactDOM from 'react-dom';
const container=document.getElementById('root');

function MyFuncComp(props) {
   return <h1>函数组件</h1>
}
ReactDOM.render(
   <div>
   {MyFuncComp()}
</div>,container);

这个时候运行项目,打开浏览器窗口,就可以看到组件已经被渲染到窗口里了,这个方式没有构建组件结构,
因此在后面如果我们要对组件做一些优化的时候就会比较麻烦,日常开发中一般很少使用这种方式来渲染组件,而会使用以下方式渲染我们的组件
b.当react元素来使用

import React from "react";
import ReactDOM from 'react-dom';

const container=document.getElementById('root');

function MyFuncComp(props) {
    return <h1>函数组件,当前数字为{props.number}</h1>
}
//使用组件,生成的,仍然是一个React元素,变化的,只是type值
ReactDOM.render(
  <MyFuncComp number={10} />,container);

这个方式渲染的组件拥有清晰的组件结构,对于我们后面进行调试,优化都很方便

  1. 类组件

必须继承自React.Component

必须提供render函数,用于渲染组件

组件的属性

  1. 对于函数组件,属性会作为一个对象的属性,传递给函数的参数props
import React from "react";
import ReactDOM from 'react-dom';


const container=document.getElementById('root');

function MyFuncComp(props) {
    console.log(props,'props');//{number: 10, obj: {name: 'zhangsan', age: 18}}
    return <h1>函数组件,当前数字为{props.number}</h1>
};
ReactDOM.render(
  <>
  <MyFuncComp number={10} obj={{name:'zhangsan',age:18}}></MyFuncComp>
  </>,container);
  1. 对于类组件,属性会作为一个对象的属性,传递给构造函数的参数
  //在父组件中使用
  import ClassCom from './components/ClassCom.jsx'
  ReactDOM.render(
  <>
  <ClassCom number={10} obj={{name:'zhangsan',age:18}}></ClassCom>
  </>,container);

// ClassCom组件
import React, { Component } from 'react'
export default class ClassCom extends Component {
    //这里不需要我们手动去继承父组件的props,react会帮我们完成这件事 
    //所以以下这段注释掉的代码存不存在都不影响我们在render函数中通过 this.props.obj来访问父组件传递过来的obj对象
    // constructor(props){
    //     console.log(props,'propsClassCom');
    //     super(props);
    // }
  render() {
    return (
      <div>
        年龄:{this.props.obj.age}
        <br></br>
        姓名:{this.props.obj.name}
      </div>
    )
  }
}

注意:组件的属性,应该使用小驼峰命名法
之前学习的React元素,本质上,就是一个组件(内置组件)

组件无法改变父组件传递过来的属性。(单向数据流)

React中的哲学:数据属于谁,谁才有权力改动

React中的数据,自顶而下流动

import React from 'react'

export default function MyFuncComp(props) {
    console.log(props,'props');//{number: 10, obj: {name: 'zhangsan', age: 18}}
    // props.number=11;//尝试修改父组件传递过来的属性 导致浏览器报错
    props.obj.name='lisi';//修改对象身上的属性不会报错 值也能修改成功 但是强烈不建议去修改父组件传递过来的属性 数据属于谁 谁才有权力去修改
    return <h1>函数组件,当前数字为{props.obj.name}</h1>
}

demo:写一个学生列表的demo,练习一下组件的内容
StuInfo组件,负责展示每一个学生的信息

import React from 'react';
export default function StuInfo(props) {
  return (
   <li>
    <h3>{'{'}姓名{'}'}:{props.stu.name}</h3>
    <p>年龄:{props.stu.age}</p>
    <p>性别:{props.stu.gender===1?'男':'女'}</p>
    <p>出生年份:{props.stu.year}</p>
   </li>
  )
}

StuList组件,负责把所有的学生信息集合在一起展示

import React from 'react'
import StuInfo from './StuInfo.jsx'
export default function StuList(props) {
    console.log(props.stuList,'stuList');
    const lis=props.stuList.map((stu,index)=><StuInfo stu={{...stu}} key={index}></StuInfo>);
  return (
    <ul>
      {lis}  
    </ul>
  )
}

在入口文件中使用

import React from "react";
import ReactDOM from 'react-dom';
import StuList from './components/StuList.jsx'
const container=document.getElementById('root');
const stuList=[
    {"name": "张伟", "age": 21, "gender": 0, "year": 1999},  
    {"name": "李婷", "age": 20, "gender": 1, "year": 2001},  
    {"name": "王明", "age": 22, "gender": 1, "year": 1998},  
    {"name": "赵佳", "age": 21, "gender": 0, "year": 2000},  
    {"name": "刘杰", "age": 24, "gender": 0, "year": 1997},  
    {"name": "陈曦", "age": 22, "gender": 1, "year": 1999},  
    {"name": "孙丽", "age": 21, "gender": 0, "year": 2001},  
    {"name": "周强", "age": 23, "gender": 1, "year": 1998},  
    {"name": "吴敏", "age": 20, "gender": 0, "year": 1999},  
    {"name": "郑磊", "age": 22, "gender": 1, "year": 2000}  
   ];

ReactDOM.render(
  <>
  <StuList stuList={stuList}></StuList>
  </>,container);

组件状态

组件状态

组件状态:组件可以自行维护的数据

组件状态仅在类组件中有效

状态(state),本质上是类组件的一个属性,是一个对象

状态初始化

状态的变化

不能直接改变状态:因为React无法监控到状态发生了变化

必须使用this.setState({})改变状态

一旦调用了this.setState,会导致当前组件重新渲染

组件中的数据

  1. props:该数据是由组件的使用者传递的数据,所有权不属于组件自身,因此组件无法改变该数据
  2. state:该数据是由组件自身创建的,所有权属于组件自身,因此组件有权改变该数据
    demo:封装一个倒计时组件
//类组件实现:
import React, { Component } from 'react'

export default class Tick extends Component {
    constructor(props){
        super(props);
        console.log(props,'props');
        //初始化状态
        this.state={
            left:this.props.number
        }
        this.timer=setInterval(()=>{
            let left=this.state.left;
            if(left===0){
                clearInterval(this.timer); return
            }
            this.setState({
                left:left-1
            })

        },1000);
    }
  render() {
    return (
      <div>
        <h1>倒计时时间:{this.state.left}</h1>
      </div>
    )
  }
}


//函数式组件实现
import React, { useState, useEffect } from "react";

// 封装一个倒计时组件
export default function Tick({ left=60,duration = 1000 }) {
    // 使用useState来管理剩余时间,初始值设为60
    let [time, setTime] = useState(left||60);
    useEffect(() => {
        // 创建定时器
        const timer = setInterval(() => {
            if (time > 0) {
                // 前置自减,先将时间减1再更新状态
                let newTime=--time
                setTime(newTime);
            } else {
                // 时间到了,清除定时器
                clearInterval(timer);
            }
        }, duration);

        // 返回清除定时器的回调函数,用于组件卸载或依赖项变化时清理定时器
        return () => clearInterval(timer);
    }, []); // 这里依赖项为空数组,表示只在组件挂载和卸载时执行useEffect内的逻辑

    return (
        <div>
            <button>{time}</button>
        </div>
    );
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,755评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,305评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,138评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,791评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,794评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,631评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,362评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,264评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,724评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,900评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,040评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,742评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,364评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,944评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,060评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,247评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,979评论 2 355

推荐阅读更多精彩内容