(1)函数组件
也叫做静态组件,它没有自己的状态,定义时首字母大写,利用props传值;props是一个对象,是{ name : 'jack' },所以要取name值需要用props.name
function Welcome(props) {
console.log(props);
return <h1>Welcome {props.name}</h1>
}
var element =
<div>
<h1>Welcome</h1>
<Welcome />
<Welcome>aaa</Welcome>
<Welcome name='jack'></Welcome>
</div>
console.log(element);
ReactDOM.render(element, document.getElementById('app'))
这是babel转换后的代码
var element = React.createElement("div", null,
React.createElement("h1", null, "Welcome"),
React.createElement(Welcome, null),
React.createElement(Welcome, null, "aaa"),
React.createElement(Welcome, {
name: "jack"
}));
这是第一个element展开的内容,重点记住props,type和children属性
在创建vDOM,如果type是函数组件则自动执行并把props值传入函数,同步到真实DOM中,进行渲染
(2)单向数据流
就是数据从跟组件一直传到最后的子组件
学校信息练习
function Student(props) {
let {student} = props.student
return (
<div>
<h3>student:{student}</h3>
</div>
)
}
function Teacher(props) {
return (
<div>
<h3>teacher:{props.teacher}</h3>
</div>
)
}
function Class(props) {
console.log(props)
let { classname, teacher, students } = props.class
return (
<div>
<h1>class:{classname}</h1>
<Teacher teacher={teacher}></Teacher>
<Student student={students[0]}></Student>
<Student student={students[1]}></Student>
<Student student={students[2]}></Student>
</div>
)
}
function School(props) {
console.log(props)
let { schoolname, classes } = props.school
return (
<div>
<h1>school:{schoolname}</h1>
<Class class={classes[0]}></Class>
<Class class={classes[1]}></Class>
<Class class={classes[2]}></Class>
</div>
)
}
let data = {
school1: {
schoolname: "林口四中",
classes: [
{
classname: "大一班",
teacher: "老冯",
students: ["1-1", "1-2", "1-3"]
},
{
classname: "二班",
teacher: "老李",
students: ["2-1", "2-2", "2-3"]
},
{
classname: "三班",
teacher: "老刘",
students: ["3-1", "3-2", "3-3"]
},
]
}
}
const e = <School school={data.school1} ></School>
ReactDOM.render(e, document.getElementById('app'))
评论组件练习
function Avatar(props) {
let {avatar} = props
return(
<img className="Avatar"
src={avatar}
alt="girl"
/>
)
}
function User(props) {
let {name,avatar} = props.author
return(
<div className="UserInfo">
<Avatar avatar = {avatar}></Avatar>
<div className="UserInfo-name">
{name}
</div>
</div>
)
}
function Content(props) {
return (
<div className="Comment-text">
{props.content}
</div>
)
}
//用户信息
var aaa = {
author: {
name: 'jack',
avatar: ""
},
content: 'aaa bbb cccc',
date: '2021-08-02'
}
function Comment(props) {
console.log(props);
let {author,content} = props.data
return (
<div className='comment'>
{/*用户信息 */}
<User author = {author}></User>
{/*评论内容 */}
<Content content = {content}></Content>
{/*日期内容 */}
<div className="Comment-date">
2021-08-02
</div>
</div>
)
}
//注意信息在props里存储在data了,data就是key,通过它才能取到
const e = <Comment data={aaa} />
ReactDOM.render(e, document.getElementById('app'))
(3)关于继承的知识
class A{
//③n接收了100
constructor(n){
//this指向B的实例
this.x = n
}
getX(){
console.log(this.x);
}
}
class B extends A{
//②100又通过super传给A
constructor(props){
//super没被调用this不初始化,打印this会报错
super(props)
//给b的实例添加私有属性
this.y = 10
}
//给当前类的实例添加私有属性,和constructor里面增加私有属性一样
z = 300
//给当前类添加静态属性
static m = 400
//添加到B类的原型A上去了,也就是B.prototype.getY,当前类市里的.__proto__.getY
getY(){
console.log(this.y);
}
}
//①100传到B中
let b = new B(100)
//④打印出x值
console.log(b.x);
注意在不同的位置上添加属性的位置是不同的
(4)类组件
类组件有自己的生命周期自己的状态;类组件constructor可以不写但必须要写render,必须要继承父类
class Welcome extends React.Component{
//constructor可以不写,render会帮我们调用
constructor(props){
//在此写super可以使我们在此阶段就能使用this
super(props)
}
//必须写render,在每次props值变化,调用this.setState(),或者刷新时render自动被调用
render(){
//这里的this指向当前类的实例,render调用时会帮我们做this.props = props
//所以我们要取值的话用this.props
return <h1>Hello {this.props.name}</h1>
}
}
创建vDOM,如果type是类组件则进行new调用,并把props值传入函数,同步到真实DOM中,进行渲染
(5)时钟案例
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = { time: new Date().toLocaleTimeString() }
}
render() {
return (
<div>
<h1>Clock</h1>
<h2>{this.state.time}</h2>
{/*onClick里应该放一个函数才能在点击时被触发,不能直接放表达式*/}
<button onClick={() => {
{/*这个DOM方法作用是卸载节点*/}
ReactDOM.unmountComponentAtNode(document.getElementById('app'))
}
}>remove</button>
</div>
)
}
//钩子函数,页面渲染完毕后触发
componentDidMount() {
//强制更新
//this.state.time = "abc"
//this.forceUpdate();
this.timerId = setInterval(() => {
//setState能刷新页面
console.log(111);
//这里setState是异步的,卸载掉后仍占用资源
this.setState({
time: new Date().toLocaleTimeString()
})
}, 1000)
}
//组件被卸载前触发
componentWillUnmount() {
clearInterval(this.timerId)
}
}