組件和組件屬性
[傳送門(mén)](組件 & Props – React (reactjs.org))
組件:包含內(nèi)容檩电、樣式和功能的UI單元
創(chuàng)建一個(gè)組件
特別注意:組件的名稱(chēng)首字母必須大寫(xiě)
如果你的組件的名稱(chēng)首字母小寫(xiě)了窘面,react會(huì)認(rèn)為這個(gè)一個(gè)普通的react元素,在組件中可以使用的很多屬性就無(wú)法在你的組件中使用了
- 函數(shù)組件
返回一個(gè)React元素
(1).定義一個(gè)函數(shù)組件
import React from 'react'
export default function MyFuncComp(props) {
// return <h1>函數(shù)組件的內(nèi)容</h1>
return <h1>函數(shù)組件代芜,目前的數(shù)字:{props.number}</h1>
}
(2).函數(shù)組件的用法
a.當(dāng)成普通函數(shù)來(lái)調(diào)用
比如以下案例:
import React from "react";
import ReactDOM from 'react-dom';
const container=document.getElementById('root');
function MyFuncComp(props) {
return <h1>函數(shù)組件</h1>
}
ReactDOM.render(
<div>
{MyFuncComp()}
</div>,container);
這個(gè)時(shí)候運(yùn)行項(xiàng)目,打開(kāi)瀏覽器窗口莱找,就可以看到組件已經(jīng)被渲染到窗口里了,這個(gè)方式?jīng)]有構(gòu)建組件結(jié)構(gòu)堰怨,
因此在后面如果我們要對(duì)組件做一些優(yōu)化的時(shí)候就會(huì)比較麻煩兔簇,日常開(kāi)發(fā)中一般很少使用這種方式來(lái)渲染組件啊鸭,而會(huì)使用以下方式渲染我們的組件
b.當(dāng)react元素來(lái)使用
import React from "react";
import ReactDOM from 'react-dom';
const container=document.getElementById('root');
function MyFuncComp(props) {
return <h1>函數(shù)組件,當(dāng)前數(shù)字為{props.number}</h1>
}
//使用組件锹淌,生成的,仍然是一個(gè)React元素赠制,變化的赂摆,只是type值
ReactDOM.render(
<MyFuncComp number={10} />,container);
這個(gè)方式渲染的組件擁有清晰的組件結(jié)構(gòu),對(duì)于我們后面進(jìn)行調(diào)試钟些,優(yōu)化都很方便
- 類(lèi)組件
必須繼承React.Component
必須提供render函數(shù)烟号,用于渲染組件
組件的屬性
- 對(duì)于函數(shù)組件,屬性會(huì)作為一個(gè)對(duì)象的屬性政恍,傳遞給函數(shù)的參數(shù)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>函數(shù)組件,當(dāng)前數(shù)字為{props.number}</h1>
};
ReactDOM.render(
<>
<MyFuncComp number={10} obj={{name:'zhangsan',age:18}}></MyFuncComp>
</>,container);
- 對(duì)于類(lèi)組件汪拥,屬性會(huì)作為一個(gè)對(duì)象的屬性,傳遞給構(gòu)造函數(shù)的參數(shù)
//在父組件中使用
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 {
//這里不需要我們手動(dòng)去繼承父組件的props篙耗,react會(huì)幫我們完成這件事
//所以以下這段注釋掉的代碼存不存在都不影響我們呢在render函數(shù)中通過(guò) this.props.obj來(lái)訪問(wèn)父組件傳遞過(guò)來(lái)的obj對(duì)象
// constructor(props){
// console.log(props,'propsClassCom');
// super(props);
// }
render() {
return (
<div>
年齡:{this.props.obj.age}
<br></br>
姓名:{this.props.obj.name}
</div>
)
}
}
注意:組件的屬性喷楣,應(yīng)該使用小駝峰命名法
之前學(xué)習(xí)的React元素,本質(zhì)上鹤树,就是一個(gè)組件(內(nèi)置組件)
組件無(wú)法改變父組件傳遞過(guò)來(lái)的屬性铣焊。(單向數(shù)據(jù)流)
React中的哲學(xué):數(shù)據(jù)屬于誰(shuí),誰(shuí)才有權(quán)力改動(dòng)
React中的數(shù)據(jù)罕伯,自頂而下流動(dòng)
import React from 'react'
export default function MyFuncComp(props) {
console.log(props,'props');//{number: 10, obj: {name: 'zhangsan', age: 18}}
// props.number=11;//嘗試修改父組件傳遞過(guò)來(lái)的屬性 導(dǎo)致瀏覽器報(bào)錯(cuò)
props.obj.name='lisi';//修改對(duì)象身上的屬性則不會(huì)報(bào)錯(cuò) 值也能修改成功 但是強(qiáng)烈不建議去修改父組件傳遞過(guò)來(lái)的屬性 數(shù)據(jù)屬于誰(shuí) 誰(shuí)才有權(quán)力去修改
return <h1>函數(shù)組件,當(dāng)前數(shù)字為{props.obj.name}</h1>
}
demo:寫(xiě)一個(gè)學(xué)生列表的demo曲伊,練習(xí)一下組件的內(nèi)容
StuInfo組件,負(fù)責(zé)展示每一個(gè)學(xué)生的信息
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組件追他,負(fù)責(zé)把所有的學(xué)生信息集合在一起展示
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": "周強(qiáng)", "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);
組件狀態(tài)
組件狀態(tài)
組件狀態(tài):組件可以自行維護(hù)的數(shù)據(jù)
組件狀態(tài)僅在類(lèi)組件中有效
狀態(tài)(state)坟募,本質(zhì)上是類(lèi)組件的一個(gè)屬性,是一個(gè)對(duì)象
狀態(tài)初始化
狀態(tài)的變化
不能直接改變狀態(tài):因?yàn)镽eact無(wú)法監(jiān)控到狀態(tài)發(fā)生了變化
必須使用this.setState({})改變狀態(tài)
一旦調(diào)用了this.setState邑狸,會(huì)導(dǎo)致當(dāng)前組件重新渲染
組件中的數(shù)據(jù)
- props:該數(shù)據(jù)是由組件的使用者傳遞的數(shù)據(jù)懈糯,所有權(quán)不屬于組件自身,因此組件無(wú)法改變?cè)摂?shù)據(jù)
- state:該數(shù)據(jù)是由組件自身創(chuàng)建的单雾,所有權(quán)屬于組件自身赚哗,因此組件有權(quán)改變?cè)摂?shù)據(jù)
demo:封裝一個(gè)倒計(jì)時(shí)組件
import React, { Component } from 'react'
export default class Tick extends Component {
constructor(props){
super(props);
console.log(props,'props');
//初始化狀態(tài)
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>倒計(jì)時(shí)時(shí)間:{this.state.left}</h1>
</div>
)
}
}