一、思路
- 根据分析可以得出,根组件不需要自己发送请求,获取数据,也没有自己的私有数据。所以最外层的根组件使用函数组件。
- 想要获得请求的数据结果,需要等到渲染完真实DOM以后,所以应该把它放在生命周期中,不能直接放在constructor (){}中,应该放在componentDidMount(){}中
- 发送请求不再放在最外面,这样获取不到数据。
- 先声明根组件,再生成导航组件和课程组件
- 根据分析,课程组件是由多个Item组成的,所以item也要用组件来完成,里面的数据需要经过请求,拿到私有数据,所以需要用类组件。但是在item的外面,需要有一个大的课程组件来包裹。所以课程组件使用函数组件来完成
二、相关知识点
- 类组件中的render() 方法是必须要有的
- 在render() 方法中使用this.props替换props
- 类组件需要继承与Racte.Component
- 每次组件刷新时render 方法 都会被地调用,但是只要在相同的DOM节点中渲染根组件,就仅有一个根组件的class实例创建并使用
- 类组件中有构造函数constructor(){}, 在该构造函数里面必须有super();
并且这个构造函数中的this.state可以数据初始化 - componentDidMount() 方法会在组件已经被渲染到DOM中后运行。
- 使用this.setState 时刻更新组件state
三、部分代码解释及注意
四、示例代码
//导航条组件: 导航条时序要发送请求。
class Nav extends React.Component {
constructor() {
super();
this.state = {
navs: [], //初始值尽量和后面要保存的数据类型保持一致 ;
};
}
render() {
console.log("生成虚拟DOM");
return (
<div className="nav">
{this.state.navs.map((nav) => (
<button>{nav.style_title}</button>
))}
</div>
);
}
// componentDidMount(): 声明周期函数,组件被渲染为真实DOM时执行
componentDidMount() {
//
console.log("渲染真实DOM");
fetch(
"https://www.lanqb.com/api/course/course-group-list?course_style=1"
)
.then((response) => response.json())
.then(({ course_style }) => {
// this.setState() 会触发render() 组件再次被渲染
this.setState({
navs: course_style,
});
});
}
}
// 声明课程组件
class Course extends React.Component {
constructor() {
super();
this.state = {
courseLists: [],
};
}
render() {
return (
<div className="course">
{this.state.courseLists.map((c) => (
<CourseItem course={c} />
))}
</div>
);
}
componentDidMount() {
fetch(
"https://www.lanqb.com/school/professional?status=show&limit=20&page=1&course_style_ids=&weight=desc"
)
.then((response) => response.json())
.then(({ data }) => {
// this.setState() 会触发render() 组件再次被渲染
this.setState({
courseLists: data,
});
});
}
}
function CourseItem(props) {
return (
<div>
<p>标题:{props.course.title}</p>
</div>
);
}
// 最外层的根组件,使用函数组件。他仅仅是包裹其他组件
function App() {
return (
<div className="app">
<Nav></Nav>
<hr />
<Course />
</div>
);
}
ReactDOM.render(<App />, document.getElementById("main"));