29.9React课程
第02节:react组件化
第2节:02课react组件化
(02课react组件化&)
02课react组件化
初始化显示constructor构造函数,要使用super(),否则没法在内部使用this
2与3之间要对组件进行渲染
componentWillReceiverProps父组件传递的属性发生变化时执行
接收新的props和新的state
state发生更新,shouldComponentUpdate才会被激活,接收当前最新的props和state默认返回值是true
执行完render之后执行DidUpdate
如果为true返回后面内容,如果为false不展示child要执行willunMount
import React, { Component } from "react";
class Child extends React.Component {
componentWillReceiveProps(nextProps, nextState) {
// 父组件传递的属性有变化,做相应响应
console.log(nextProps, nextState, "4.将要接收属性传递");
}
componentWillUnmount() {
// 组件将要卸载, 可做清理工作
console.log("8.组件将要卸载");
}
render() {
return <div>hello child</div>;
}
}
export default class Lifecycle extends Component {
constructor(props) {
super(props);
// 常用于初始化状态
this.state = {
counter: 0,
isShow: true
};
console.log("1.组件构造函数执行");
}
componentWillMount() {
// 此时可以访问状态和属性,可进行api调用等
console.log("2.组件将要挂载");
}
componentDidMount() {
// 组件已挂载,可进行状态更新操作
console.log("3.组件已挂载");
setTimeout(() => {
this.setState({
isShow: false
});
}, 3000);
}
componentWillReceiveProps(nextProps, nextState) {
// 父组件传递的属性有变化,做相应响应
console.log("4.将要接收属性传递");
}
shouldComponentUpdate(nextProps, nextState) {
// 组件是否需要更新,需要返回布尔值结果,优化点
console.log("5.组件是否需要更新?");
return true;
}
componentWillUpdate() {
// 组件将要更新,可做更新统计
console.log("6.组件将要更新");
}
componentDidUpdate() {
// 组件更新
console.log("7.组件已更新");
}
componentWillUnmount() {
// 组件将要卸载, 可做清理工作
console.log("8.组件将要卸载");
}
add = () => {
this.setState({
counter: this.state.counter + 1
});
};
render() {
console.log("组件渲染");
return (
<div onClick={this.add}>
生命周期探究
{this.state.isShow && <Child num={this.state.counter} />}
</div>
);
}
}
16.4新版本的API
(context实现状态共享&)
context实现状态共享&
创建context,接收一个参数作为context的默认值
组件想要使用状态需要用conuser进行包裹,接收参数value就是privider提供的状态
...value以属性展开的方式获取counter值
消费provider提供的状态
传递add方法
一个值发生了变化其他的值一块变化
创建上下文给的默认值,如果没有Provider提供属性值使用默认值
consumer获取共享状态
定义多个组件不会产生冲突
child组件可以接收name属性了,相互独立互不影响
consumer接收的都是provider提供的值
import React, { Component } from "react";
//创建 Context
const Context = React.createContext({ counter: 0 });
// const Context2 = React.createContext({ name: "davy" });
// const Provider2 = Context2.Provider;
// const Consumer2 = Context2.Consumer;
const { Provider, Consumer } = Context;
//withConsumer是高阶组件工厂,他可以根据配置返回一个高阶组件
//Es5写法
function withConsumer(Consumer) {
return function(Comp) {
return function(props) {
return <Consumer>{value => <Comp {...value} />}</Consumer>;
};
};
}
const Child = withConsumer(Consumer)(function(props) {
return (
<div
onClick={() => {
props.add();
}}
>
{props.counter}
{props.name}
</div>
);
});
// function Child(props) {
// return (
// <div
// onClick={() => {
// props.add();
// }}
// >
// {props.counter}
// {props.name}
// </div>
// );
// }
class ContextTest extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0
};
}
add = () => {
this.setState({
counter: this.state.counter + 1
});
};
render() {
return (
<div>
<Provider value={{ counter: this.state.counter, add: this.add }}>
{/* consumer 接收一个函数 当没有provider 会接收context默认值*/}
<Child />
{/* <Consumer2>{value => <Child {...value} />}</Consumer2> */}
<Child />
<Child />
</Provider>
</div>
);
}
}
// // <div>
// <div>
// <Provider2 value={{ name: "han" }}>
// <div>
// <Consumer2>{value => <Child {...value} />}</Consumer2>
// </div>
// </Provider2>
// </div>
// </div >
export default ContextTest;
(高阶组件&)
高阶组件&
本质是工厂函数,接收组件做为参数返回一个新的组件就是高阶组件
为了提升组件的复用率
保证Lession产生新组件,传递index索引根据索引,新的组件展示里面的stage和title
接收一个组件Comp,返回一个新的组件props=>{}
使用的时候LessWidthContent传递进idx索引
最后展示reat - 核心API
高阶组件变形,容易理解
使用高阶组件保证consumer
箭头函数演变,接收一个组件,返回一个组件
(链式调用&)
链式调用&
类组件才有生命周期钩子,传入的所有属性以this.props接收展示
组件设计哲学,一定要把一个ui抽象为最小颗粒度去实现,再通过高阶组件拓展
(装饰器写法&)
装饰器写法&
装饰器不支持函数式组件,
import React, { Component } from "react";
// Lesson保证功能单一,它不关心数据来源,只负责显示
function Lesson(props) {
return (
<div>
{props.stage} - {props.title}
</div>
);
}
// 模拟数据
const lessons = [
{ stage: "React", title: "核心API" },
{ stage: "React", title: "组件化1" },
{ stage: "React", title: "组件化2" }
];
//高阶组件withContent 负责包装这个Lesson
// 包装后的组件具备根据传入的索引,渲染课程
//hoc接收一个组件作为参数,返回一个新的组件
// function withConetnt(Comp) {
// return function(props) {
// const content = lessons[props.idx];
// return <Comp {...content} />;
// };
// }
const withConetnt = Comp => props => {
const content = lessons[props.idx];
return <Comp {...content} />;
};
//高阶组件withlog负责包装传入的组件,具备挂载到Dom上可以输出日志
const withlog = Comp => {
return class extends React.Component {
componentDidMount() {
console.log("has did mount", this.props);
}
render() {
return <Comp {...this.props} />;
}
};
};
//包装Lesson
const LessWidthContent = withlog(withConetnt(Lesson));
// @withlog
@withConetnt
class EndTest extends React.Component {
render() {
return (
<div>
{this.props.stage} - {this.props.title}
</div>
);
}
}
class HocTest extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return <EndTest idx={0} />;
}
}
export default HocTest;
import React from "react";
// import Lifecycle from "./Lifecycle";
// import ContextTest from "./ContextTest";
import HocTest from "./HocTest.tsx";
import CompositionTest from "./CompositionTest";
import ContextTest2 from "./ContextTest2";
class App extends React.Component {
render() {
return (
<div>
<h1>hello react</h1>
{/* 生命周期 */}
{/* <Lifecycle /> */}
{/* context 上下文 达到状态共享 */}
{/* <ContextTest /> */}
<HocTest />
{/* <CompositionTest /> */}
{/* <ContextTest2 /> */}
</div>
);
}
}
export default App;
(组件复合&)
组件复合&
组件只赋值展示,内容外部调用的时候传入,props.children也是jsx是一个对象
作用域插槽,动态传进来的内容不是当前组件作用域而是父组件的作用域,值是内部提供的
()语法糖返回一个对象
props.children变为一个函数可以直接执行,调用来传递参数
通过函数解构出titile和content属性值,并把title和content返回过去
Dialog接收一个返回过来的title和content
调用children函数,children就是Dialog内部的内容,传递什么children就是什么,传递对象props.children就是对象
children也可以以属性的方式传递,同时组件内部有内容
组件内部props.children优先解析组件内部内容,如果内部没有内容就是test
import React, { Component } from "react";
// Dialog定义组件外观和行为
function Dialog(props) {
const messages = {
foo: { title: "foo", content: "foo~" },
bar: { title: "bar", content: "bar~" }
};
console.log(props.children);
const { title, content } = props.children(messages[props.msg]);
return (
<div style={{ border: "1px solid blue" }}>
<div>{title}</div>
<span>---------------</span>
<div>{content}</div>
</div>
);
}
//props.children 什么是Children
//组件的内容部分
class CompositionTest extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<Dialog msg={"bar"} children={"test"}>
{({ title, content }) => ({
title: <h1>{title}</h1>,
content: <p>{content}</p>
})}
{/* jsx
{{
title: <h1>标题2</h1>,
content: <p>内容2</p>
}} */}
</Dialog>
</div>
);
}
}
export default CompositionTest;
(Context API&)
Context API&
import React, { Component } from "react";
const Context = React.createContext({ counter: 30 });
class Child extends Component {
static contextType = Context;
render() {
return <div>{this.context.counter}</div>;
}
}
// Child.contextType = Context;
class ContextTest2 extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
// <Context.Provider value={{ counter: 0 }}>
// <Context.Consumer>{value => <Child {...value} />}</Context.Consumer>
// </Context.Provider>
<div>
<Child />
</div>
);
}
}
export default ContextTest2;
import React, { Component } from "react";
// Lesson保证功能单一,它不关心数据来源,只负责显示
function Lesson(props) {
return (
<div>
{props.stage} - {props.title}
</div>
);
}
// 模拟数据
const lessons = [
{ stage: "React", title: "核心API" },
{ stage: "React", title: "组件化1" },
{ stage: "React", title: "组件化2" }
];
//高阶组件withContent 负责包装这个Lesson
// 包装后的组件具备根据传入的索引,渲染课程
//hoc接收一个组件作为参数,返回一个新的组件
// function withConetnt(Comp) {
// return function(props) {
// const content = lessons[props.idx];
// return <Comp {...content} />;
// };
// }
const withConetnt = Comp => props => {
const content = lessons[props.idx];
return <Comp {...content} />;
};
//高阶组件withlog负责包装传入的组件,具备挂载到Dom上可以输出日志
const withlog = Comp => {
return class extends React.Component {
componentDidMount() {
console.log("has did mount", this.props);
}
render() {
return <Comp {...this.props} />;
}
};
};
//包装Lesson
const LessWidthContent = withlog(withConetnt(Lesson));
// @withlog
@withConetnt
class EndTest extends React.Component {
render() {
return (
<div>
{this.props.stage} - {this.props.title}
</div>
);
}
}
class HocTest extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return <EndTest idx={0} />;
}
}
export default HocTest;