01.将html静态页面封装成react大组件(html=>react)
组件&Props - React官方文档参考:组件&Props-Reacthttps://zh-hans.reactjs.org/docs/components-and-props.html
函数组件又称UI组件或简单组件,相对于类组件来说,函数组件更简单,类组件又称复杂组件。
一. 函数组件特点
01.定义函数组件
function Welcom(){
// 函数组件一定有返回值return Welcome首字母大写
return <h1>hello world</h1>
}
// 函数组件的使用当成元素标签去使用
const e = <Welcom></Welcom>
02.函数组件的传值
function Welcom(props){
console.log(props);//props是参数
//不传参数为一个空对象,prop接受两种:正常传值和子元素children
//传值的使用:
return <h1>hello {props}</h1>
//应该是具体的值,不能是一个对象
// 直接使用会报错:Objects are not valid as a React child对象不能作为react的children
//应该是具体的值,不应该是对象
// 正确使用:
return <h1>{props.name}</h1>
// 另一种使用方式:解构赋值
const {name} = props
return <h1>hello{name}</h1>
}
const e = <Welcom></Welcom>
// 在属性中传递参数
const e = <Welcom name='张三'></Welcom>
03.组件的复用
function Welcom(props)//props属性传值
//props接受两种方式的传值:一类是正常的属性传值,
//另一类是children:'hello world'子元素传值
const {children,name} = props
return <h1>hello{name}</h1>
return <h1>hello{children}</h1>
return <h1>hello{children + name}</h1>//拼接也可以
return <h1>hello{children} {name}</h1>
}
// 在属性中传递参数,默认children传值
const e = <Welcom name='张三'></Welcom>
const e = <div>
<h1>hello</h1>
<Welcom />//输出NaN未传值
<Welcom>hello world</Welcom>//涉及拼接问题时,所有参数都需要传参,否则拼接不上
<Welcom name='张三'>hello world</Welcom>//子元素传值 输出张三
</div>
04.创建元素和虚拟DOM分析
const e = <div>
<h1>hello page</h1>
<Welcom name='张三'>hello world</Welcom>
</div>
//相当于createElement创建元素
console.log(e);
// 虚拟DOM
// {
// type:'div',
// props:{
// children:[
// {
// type:'h1',
// props:{children:hello page}
// },
// {
// type: Welcom(props),不是写死的变成了虚拟DOM
// props:{children:'hello'}
// }
// ]
// }
// }
判断类型type:
如果是函数:自动执行函数,同时props传入函数,获取返回值,再次渲染,同步到真实DOM中=>渲染容器中
不是函数是正常标签时:虚拟DOM直接渲染生成标签,生成真实DOM=>渲染容器中
ReactDOM.render(e,document.getElementById("app"))
05.PURE:纯函数特点
在普通函数的基础上,传入相同的值,必须返回相同的值,返回值不能改变,函数组件又叫静态组件
function sum(a,b){
return a + b
}
console.log(sum(1,2));//纯函数
//不是纯函数:传入相同的值,返回的值可能改变
let p = 0;
function sum(a,b){
a = ++p
return a + b
}
console.log(sum(1,2));//不纯函数
二. 函数组件组合
需求:展示学校信息:学校school-班级class-老师teacher-学生students
01.请求数据
let data = {
school:{
name:"一中",
classes:[
{
name:'一班',
teacher:"Mr.Wang",
students:[
{
name:'小红1',
gender:0,
age:18,
},
{
name:'小绿1',
gender:1,
age:18,
},
{
name:'小蓝1',
gender:1,
age:18,
},
]
},
{
name:'二班',
teacher:"Mr.Li",
students:[
{
name:'小红2',
gender:0,
age:18,
},
{
name:'小绿2',
gender:1,
age:18,
},
{
name:'小蓝2',
gender:1,
age:18,
},
]
},
{
name:'三班',
teacher:"Mr.Zhang",
students:[
{
name:'小红3',
gender:0,
age:18,
},
{
name:'小绿3',
gender:1,
age:18,
},
{
name:'小蓝3',
gender:1,
age:18,
},
]
},
]
}
}
02.定义组件及组件间关系
1)定义组件,从小到大的定义顺序
2)定义组件间关系
3)传入数据
4)形成组件树,形成数据流-->子组件显示
function Student(props){
// console.log(props);
const {name,gender,age} = props.student
return <div>
<div>学生姓名:{name}</div>
<div>学生性别:{gender}</div>
<div>学生年龄:{age}</div>
</div>
}
function Teacher(props){
const name = props.teacher//teacher部分只有一个name
return <div>老师姓名:{name}</div>
}
function Class(props){
const {name,teacher,students} = props.class
// for循环students,形成数组,替换掉写死的students数组
// return <div>
// <h2>班级名:{name}</h2>
// <Teacher teacher = {teacher}></Teacher>
// <Student student = {students[0]}></Student>
// <Student student = {students[1]}></Student>
// <Student student = {students[2]}></Student>
// </div>
// 改造
return <div>
<h2>班级名:{name}</h2>
<Teacher teacher = {teacher}></Teacher>
{
students.map((item,index)=>{
return <Student student={item} key={index}></Student>
})
}
</div>
}
function School(props){
//解构读取数据
const {name,classes} = props.school
// console.log(school);
// return <div>
// <h2>学校名:{name}</h2>
// <Class class={classes[0]}></Class>
// <Class class={classes[1]}></Class>
// <Class class={classes[2]}></Class>
// </div>
// 改造
return <div>
<h2>学校名:{name}</h2>
{
classes.map((item,index)=>{
return <Class class={item} key={index}></Class>
})
}
</div>
// 正常key中放入标准id,这没有,放index,没有key值正常运行,出现Key的警告
// <Class class={item}></Class>还是js对象
// jsx构成的elemet在函数中能做参数,返回值,还能内部定义变量,本质还是JS对象
//map返回值组组装成新的数组
}
// 组件树:基于props传递数据,单向数据流
// School
// Class *3
// Teacher Student*3
03.显示跟组件,跟组件的定义
const e = <School school = {data.school}></School>
// key命名为school 跟组件为school
ReactDOM.render(e,document.getElementById("app"))
读取数据运行为:
三. 函数组件抽离
实际企业项目开发流程:
需求调研 => 需求分析 => 产品原型 => 保真图 =>
技术分析 => 前台/后台/后端/移动端/数据/app
任务分解 => 具体模块 => 软件工程师 => 静态页面翻译为react组件(html => react大组件) => 抽离组件/组件分析(最小细粒度的组件方便组件复用) => 获取数据(接口数据 => 状态数据) => 数据同步渲染到组件中
01.将html静态页面封装成react大组件(html=>react)
function Comment(props){
// html语言修改为react语言 修改注释样式为{/* */} 修改单标签为<img /> <input /> 修改class为className 修改style为对象形式
return (
<div className="comment">
<div className="UserInfo">
<img className="Avator" src="https://www.13mao.cn/wp-content/uploads/2021/02/2021020521204853-960x540.jpg" alt="girl" style={{height: 230,width: 400}} />
<div className="UserInfo-name">
昵称:
<input type="text" />
</div>
</div>
{/*评论内容*/}
<div className="Comment-text">
评论内容:
<input type="text" />
</div>
{/*评论日期*/}
<div className="Comment-date">
日期2022-04-01
</div>
</div>
)
}
02.react组件抽离
// 头像
function Avatar(props){
// 定义好接收数据的接口
const imgURL = props.imgURL
return(
<img className="Avator" src={imgURL} alt="girl" style={{height: 230,width: 400}} />
)
}
// 评论人
function User(props){
const name = props.name
return(
<div className="UserInfo-name">
{name}
<input type="text" />
</div>
)
}
// 评论内容
function CommentText(props){
const content = props.content
return(
<div className="Comment-text">
{content}
<input type="text" />
</div>
)
}
// 评论日期
function CommentDate(props){
const date = props.data
return (
<div className="Comment-date">
{date}
</div>
)
}
03.组件组合形成组件树
// 组件组合,形成组件树
function Comment(props){
return (
<div class="comment">
<div class="UserInfo">
<Avatar/>
<User/>
</div>
<CommentText/>
<CommentDate/>
</div>
)
}
04.将数据渲染到组件树中
// 数据渲染到组件
function Comment(props){
// 解构拿到数据
const { user,commentText,commentDate} = props.data
return (
<div class="comment">
<div class="UserInfo">
<Avatar imgURL={user.avator} />
<User name={user.name} />
</div>
<CommentText content={commentText}/>
<CommentDate date={commentDate}/>
</div>
)
}
05.获取数据
//接口数据=>状态数据
var data = {
user:{
name:"张三",
avator:"https://www.13mao.cn/wp-content/uploads/2021/02/2021020521204853-960x540.jpg",
},
commentText:'aaaaa',
commentDate:'2022-04-01'
}
06.组件间渲染
const e = <Comment />
ReactDOM.render(e,document.getElementById("app"))
// 或者
// ReactDOM.render(<Comment date={date}/>,document.getElementById("app"))
最终运行页面与静态页面一致: