learn——react
语法补充
类的定义
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// ES5中如何定义类
// function Person(name, age) {
// this.name = name;
// this.age = age;
// }
// Person.prototype.running = function() {
// console.log(this.name, this.age, "running");
// }
// var p = new Person("why", 18);
// console.log(p.name, p.age);
// p.running();
// ES6中通过class创建类
class Person {
// 构造方法
constructor(name, age) {
this.name = name;
this.age = age;
}
// 定义方法
running() {
console.log(this);
console.log(this.name, this.age, "running");
}
}
const p = new Person("why", 18);
console.log(p.name, p.age);
p.running();
// this绑定题目
let func = p.running;
// func();
var obj = {
name: "kobe",
age: 40
}
// func.call(obj);
// 重新给func赋值
func = func.bind(obj);
func();
</script>
</body>
</html>
类的继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
/**
* 面向对象有三大特性: 封装\继承\多态
* 继承: 1.减少重复的代码 2.多态的前提(鸭子类型)
*/
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
running() {
console.log("running");
}
}
class Student extends Person {
constructor(name, age, sno) {
super(name, age);
this.sno = sno;
}
}
const stu = new Student("why", 18, 110);
console.log(stu.name, stu.age, stu.sno);
stu.running();
class Teacher extends Person {
constructor(name, age, title) {
// 子类中是必须初始化父类对象
super(name, age);
this.title = title;
}
}
const teacher = new Teacher("kobe", 40, "教练");
console.log(teacher.name, teacher.age, teacher.title);
teacher.running();
// class Student {
// constructor(name, age, sno) {
// this.name = name;
// this.age = age;
// this.sno = sno;
// }
// running() {
// console.log("running");
// }
// }
// class Teacher {
// constructor(name, age, title) {
// this.name = name;
// this.age = age;
// this.title = title;
// }
// running() {
// console.log("running");
// }
// }
</script>
</body>
</html>
generator的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// generator: 生成器
// 1.普通函数
// function foo() {
// console.log("foo被执行");
// }
// foo();
// 2.生成器函数的定义
// 生成器函数
function* foo() {
console.log("111");
yield "Hello";
console.log("222");
yield "World";
console.log("333");
yield "coderwhy";
console.log("444");
}
// iterator: 迭代器
const result = foo();
console.log(result);
// 3.使用迭代器
// 调用一次next, 就会消耗一次迭代器
// const res1 = result.next();
// console.log(res1);
// const res2 = result.next();
// console.log(res2);
// const res3 = result.next();
// console.log(res3);
// const res4 =result.next();
// console.log(res4);
// 4.生成器函数中代码的执行顺序
// 5.练习: 定义一个生成器函数, 依次可以生成1~10的数字
function* generateNumber() {
for (var i = 1; i <= 10; i++) {
yield i;
}
}
// const numIt = generateNumber();
// console.log(numIt.next().value);
// 6.generator和Promise一起来使用
function* bar() {
console.log("1111");
const result = yield new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello Generator");
}, 3000);
});
console.log(result);
}
const it = bar();
it.next().value.then(res => {
it.next(res)
})
(preValue = 0, item) => {};
(preState = defaultState, action) => {};
["abc", "cba"].reduce((preValue, item) => {}, 0)
</script>
</body>
</html>
Hello React
原生实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2 class="title"></h2>
<button class="btn">改变文本</button>
<script>
// 命令式编程: 每做一个操作,都是给计算机(浏览器)一步步命令
// 声明式编程:
// 1.定义数据
let message = "Hello World";
// 2.将数据显示在h2元素中
const titleEl = document.getElementsByClassName("title")[0];
titleEl.innerHTML = message;
// 3.点击按钮,界面的数据发生改变
const btnEl = document.getElementsByClassName("btn")[0];
btnEl.addEventListener("click", e => {
message = "Hello React";
titleEl.innerHTML = message;
})
</script>
</body>
</html>
react实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>Header</div>
<div id="app">dafdasf</div>
<div>Footer</div>
<!-- 添加React的依赖 -->
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- 开始开发 -->
<!-- 注意事项: 使用jsx, 并且希望script中的jsx的代码被解析, 必须在script标签中添加一个属性 -->
<script type="text/babel">
// <h2></h2>: jsx代码
let message = "Hello World";
ReactDOM.render(<h2>{message}</h2>, document.getElementById("app"))
</script>
</body>
</html>
button实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<!-- 添加React的依赖 -->
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- 开始开发 -->
<!-- 注意事项: 使用jsx, 并且希望script中的jsx的代码被解析, 必须在script标签中添加一个属性 -->
<!-- jsx特点: 多个标签最外层(根)只能有一个标签 -->
<script type="text/babel">
let message = "Hello World";
function btnClick() {
message = "Hello React";
console.log(message);
render();
}
// <h2></h2>: jsx代码
function render() {
ReactDOM.render(
<div>
<h2>{message}</h2>
<button onClick={btnClick}>改变文本</button>
</div>,
document.getElementById("app")
);
}
render();
</script>
</body>
</html>
组件化实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<!-- 添加React的依赖 -->
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- 开始开发 -->
<script type="text/babel">
// 封装App组件
class App extends React.Component {
constructor() {
super();
// this.message = "Hello World";
this.state = {
message: "Hello World"
}
}
render() {
return (
<div>
<h2>{this.state.message}</h2>
<button onClick={this.btnClick.bind(this)}>改变文本</button>
</div>
)
}
btnClick() {
// this.message = "Hello React";
// this.state.message = "Hello React";
// console.log(this.state);
this.setState({
message: "Hello React"
})
}
}
// 渲染组件
ReactDOM.render(<App/>, document.getElementById("app"));
</script>
</body>
</html>
jsx核心语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="../react/react.development.js"></script>
<script src="../react/react-dom.development.js"></script>
<script src="../react/babel.min.js"></script>
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
firstname: "kobe",
lastname: "bryant",
isLogin: false
}
}
render() {
const { firstname, lastname, isLogin } = this.state;
return (
<div>
{/*1.运算符表达式*/}
<h2>{ firstname + " " + lastname }</h2>
<h2>{20 * 50}</h2>
{/*2.三元表达式*/}
<h2>{ isLogin ? "欢迎回来~": "请先登录~" }</h2>
{/*3.进行函数调用*/}
<h2>{this.getFullName()}</h2>
</div>
)
}
getFullName() {
return this.state.firstname + " " + this.state.lastname;
}
}
ReactDOM.render(<App/>, document.getElementById("app"));
</script>
</body>
</html>
jsx绑定属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<div style="color: red; font-size: 30px;"></div>
<script src="../react/react.development.js"></script>
<script src="../react/react-dom.development.js"></script>
<script src="../react/babel.min.js"></script>
<script type="text/babel">
function getSizeImage(imgUrl, size) {
return imgUrl + `?param=${size}x${size}`
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
title: "标题",
imgUrl: "http://p2.music.126.net/L8IDEWMk_6vyT0asSkPgXw==/109951163990535633.jpg",
link: "http://www.baidu.com",
active: true
}
}
render() {
const { title, imgUrl, link, active } = this.state;
return (
<div>
{/* 1.绑定普通属性 */}
<h2 title={title}>我是标题</h2>
<img src={getSizeImage(imgUrl, 140)} alt=""/>
<a href={link} target="_blank">百度一下</a>
{/* 2.绑定class */}
<div className="box title">我是div元素</div>
<div className={"box title " + (active ? "active": "")}>我也是div元素</div>
<label htmlFor=""></label>
{/* 3.绑定style */}
<div style={{color: "red", fontSize: "50px"}}>我是div,绑定style属性</div>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById("app"));
</script>
</body>
</html>
jsx绑定事件与this处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="../react/react.development.js"></script>
<script src="../react/react-dom.development.js"></script>
<script src="../react/babel.min.js"></script>
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
message: "你好啊",
counter: 100
}
this.btnClick = this.btnClick.bind(this);
}
render() {
return (
<div>
{/* 1.方案一: bind绑定this(显示绑定) */}
<button onClick={this.btnClick}>按钮1</button>
<button onClick={this.btnClick}>按钮2</button>
<button onClick={this.btnClick}>按钮3</button>
{/* 2.方案二: 定义函数时, 使用箭头函数 */}
<button onClick={this.increment}>+1</button>
{/* 2.方案三(推荐): 直接传入一个箭头函数, 在箭头函数中调用需要执行的函数*/}
<button onClick={() => { this.decrement("why") }}>-1</button>
</div>
)
}
btnClick() {
console.log(this.state.message);
}
// increment() {
// console.log(this.state.counter);
// }
// 箭头函数中永远不绑定this
// ES6中给对象增加属性: class fields
increment = () => {
console.log(this.state.counter);
}
decrement(name) {
console.log(this.state.counter, name);
}
}
ReactDOM.render(<App/>, document.getElementById("app"));
</script>
</body>
</html>
传递参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="btn">按钮</button>
<script>
document.getElementsByClassName("btn")[0].addEventListener("click", (e) => {
console.log(e);
})
</script>
<div id="app"></div>
<script src="../react/react.development.js"></script>
<script src="../react/react-dom.development.js"></script>
<script src="../react/babel.min.js"></script>
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
movies: ["大话西游", "海王", "流浪地球", "盗梦空间"]
}
this.btnClick = this.btnClick.bind(this);
}
render() {
return (
<div>
<button onClick={this.btnClick}>按钮</button>
<ul>
{
this.state.movies.map((item, index, arr) => {
return (
<li className="item"
onClick={ e => { this.liClick(item, index, e) }}
title="li">
{item}
</li>
)
})
}
</ul>
</div>
)
}
btnClick(event) {
console.log("按钮发生了点击", event);
}
liClick(item, index, event) {
console.log("li发生了点击", item, index, event);
}
}
ReactDOM.render(<App/>, document.getElementById("app"));
</script>
</body>
</html>
jsx本质
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="btn">按钮</button>
<script>
document.getElementsByClassName("btn")[0].addEventListener("click", (e) => {
console.log(e);
})
</script>
<div id="app"></div>
<script src="../react/react.development.js"></script>
<script src="../react/react-dom.development.js"></script>
<script src="../react/babel.min.js"></script>
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
movies: ["大话西游", "海王", "流浪地球", "盗梦空间"]
}
this.btnClick = this.btnClick.bind(this);
}
render() {
return (
<div>
<button onClick={this.btnClick}>按钮</button>
<ul>
{
this.state.movies.map((item, index, arr) => {
return (
<li className="item"
onClick={ e => { this.liClick(item, index, e) }}
title="li">
{item}
</li>
)
})
}
</ul>
</div>
)
}
btnClick(event) {
console.log("按钮发生了点击", event);
}
liClick(item, index, event) {
console.log("li发生了点击", item, index, event);
}
}
ReactDOM.render(<App/>, document.getElementById("app"));
</script>
</body>
</html>
learn-componment
import React, { Component } from 'react';
// export default class App extends Component {
// constructor() {
// super();
// this.state = {
// message: "你好啊,李银河"
// }
// }
// render() {
// return (
// <div>
// <span>我是App组件</span>
// {/* alt + shift + f: 对代码进行格式化 */}
// <h2>{this.state.message}</h2>
// </div>
// )
// }
// }
/**
* 函数式组件的特点:
* 1.没有this对象
* 2.没有内部的状态
*/
export default function App() {
return (
<div>
<span>我是function的组件: App组件</span>
<h2>counter</h2>
<button>+1</button>
<h2>你好啊,王小波</h2>
</div>
)
}
组件生命周期
import React, { Component } from 'react';
class Cpn extends Component {
render() {
return <h2>我是Cpn组件</h2>
}
componentWillUnmount() {
console.log("调用了Cpn的componentWillUnmount方法");
}
}
export default class App extends Component {
constructor() {
super();
this.state = {
counter: 0,
isShow: true
}
console.log("执行了组件的constructor方法");
}
render() {
console.log("执行了组件的render方法");
return (
<div>
我是App组件
<h2>当前计数: {this.state.counter}</h2>
<button onClick={e => this.increment()}>+1</button>
<hr/>
<button onClick={e => this.changeCpnShow()}>切换</button>
{this.state.isShow && <Cpn/>}
</div>
)
}
increment() {
this.setState({
counter: this.state.counter + 1
})
}
changeCpnShow() {
this.setState({
isShow: !this.state.isShow
})
}
componentDidMount() {
console.log("执行了组件的componentDidMount方法");
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log("执行了组件的componentDidUpdate方法");
}
}
组件间通信
import React, { Component } from 'react';
import TabControl from './TabControl';
export default class App extends Component {
constructor(props) {
super(props);
this.titles = ['新款', '精选', '流行'];
this.state = {
currentTitle: "新款",
currentIndex: 0
}
}
render() {
const {currentTitle} = this.state;
return (
<div>
<TabControl itemClick={index => this.itemClick(index)} titles={this.titles} />
<h2>{currentTitle}</h2>
</div>
)
}
itemClick(index) {
this.setState({
currentTitle: this.titles[index]
})
}
}
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class TabControl extends Component {
constructor(props) {
super(props);
this.state = {
currentIndex: 0
}
}
render() {
const { titles } = this.props;
const {currentIndex} = this.state;
return (
<div className="tab-control">
{
titles.map((item, index) => {
return (
<div key={item}
className={"tab-item " + (index === currentIndex ? "active": "")}
onClick={e => this.itemClick(index)}>
<span>{item}</span>
</div>
)
})
}
</div>
)
}
itemClick(index) {
this.setState({
currentIndex: index
})
const {itemClick} = this.props;
itemClick(index);
}
}
TabControl.propTypes = {
titles: PropTypes.array.isRequired
}
react实现slot
跨组件通信
import React, { Component } from 'react';
// 创建Context对象
const UserContext = React.createContext({
nickname: "aaaa",
level: -1
})
const ThemeContext = React.createContext({
color: "black"
})
function ProfileHeader() {
// jsx -> 嵌套的方式
return (
<UserContext.Consumer>
{
value => {
return (
<ThemeContext.Consumer>
{
theme => {
return (
<div>
<h2 style={{color: theme.color}}>用户昵称: {value.nickname}</h2>
<h2>用户等级: {value.level}</h2>
<h2>颜色: {theme.color}</h2>
</div>
)
}
}
</ThemeContext.Consumer>
)
}
}
</UserContext.Consumer>
)
}
function Profile(props) {
return (
<div>
<ProfileHeader />
<ul>
<li>设置1</li>
<li>设置2</li>
<li>设置3</li>
<li>设置4</li>
</ul>
</div>
)
}
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
nickname: "kobe",
level: 99
}
}
render() {
return (
<div>
<UserContext.Provider value={this.state}>
<ThemeContext.Provider value={{ color: "red" }}>
<Profile />
</ThemeContext.Provider>
</UserContext.Provider>
</div>
)
}
}
setState的使用
import React, { Component } from 'react';
function Home(props) {
// Hello World
return <h1>{props.message}</h1>
}
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
message: "Hello World"
}
}
render() {
return (
<div>
<h2>当前计数: {this.state.message}</h2>
<button onClick={e => this.changeText()}>改变文本</button>
<Home message={this.state.message}/>
</div>
)
}
componentDidUpdate() {
// 方式二: 获取异步更新的state
console.log(this.state.message);
}
changeText() {
// 2.setState是异步更新
// this.setState({
// message: "你好啊,李银河"
// })
// console.log(this.state.message); // Hello World
// 方式一: 获取异步更新后的数据
// setState(更新的state, 回调函数)
this.setState({
message: "你好啊,李银河"
}, () => {
console.log(this.state.message);
})
}
}
import React, { Component } from 'react';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
message: "Hello World"
}
}
render() {
return (
<div>
<h2>{this.state.message}</h2>
<button onClick={e => this.changeText()}>改变文本</button>
<button id="btn">改变文本2</button>
</div>
)
}
componentDidMount() {
document.getElementById("btn").addEventListener("click", (e) => {
this.setState({
message: "你好啊,李银河"
})
console.log(this.state.message);
})
// this.setState({
// message: "你好啊,李银河"
// })
// console.log(this.state.message);
}
changeText() {
// 情况一: 将setState放入到定时器中
setTimeout(() => {
this.setState({
message: "你好啊,李银河"
})
console.log(this.state.message);
}, 0);
}
}
import React, { Component } from 'react'
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0
}
}
render() {
return (
<div>
<h2>当前计数: {this.state.counter}</h2>
<button onClick={e => this.increment()}>+1</button>
</div>
)
}
increment() {
// 1.setState本身被合并
this.setState({
counter: this.state.counter + 1
});
this.setState({
counter: this.state.counter + 1
});
this.setState({
counter: this.state.counter + 1
});
// 2.setState合并时进行累加
this.setState((prevState, props) => {
return {
counter: prevState.counter + 1
}
});
this.setState((prevState, props) => {
return {
counter: prevState.counter + 1
}
});
this.setState((prevState, props) => {
return {
counter: prevState.counter + 1
}
});
}
}
React性能优化
key:
import React, { Component } from 'react'
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
movies: ["星际穿越", "盗梦空间"]
}
}
render() {
return (
<div>
<h2>电影列表</h2>
<ul>
{
this.state.movies.map((item, index) => {
return <li key={item}>{item}</li>
})
}
</ul>
<button onClick={e => this.insertMovie()}>添加电影</button>
</div>
)
}
insertMovie() {
// this.setState({
// movies: [...this.state.movies, "大话西游"]
// })
this.setState({
movies: ["大话西游", ...this.state.movies]
})
}
}
组件嵌套render的调用
import React, { Component } from 'react';
// Header
function Header() {
console.log("Header被调用");
return <h2>我是Header组件</h2>
}
// Main
class Banner extends Component {
render() {
console.log("Banner render函数被调用");
return <h3>我是Banner组件</h3>
}
}
function ProductList() {
console.log("ProductList被调用");
return (
<ul>
<li>商品列表1</li>
<li>商品列表2</li>
<li>商品列表3</li>
<li>商品列表4</li>
<li>商品列表5</li>
</ul>
)
}
class Main extends Component {
render() {
console.log("Main render函数被调用");
return (
<div>
<Banner/>
<ProductList/>
</div>
)
}
}
// Footer
function Footer() {
console.log("Footer被调用");
return <h2>我是Footer组件</h2>
}
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0
}
}
render() {
console.log("App render函数被调用");
return (
<div>
<h2>当前计数: {this.state.counter}</h2>
<button onClick={e => this.increment()}>+1</button>
<Header/>
<Main/>
<Footer/>
</div>
)
}
increment() {
this.setState({
counter: this.state.counter + 1
})
}
}
shouldComponentUpdate的使用
、import React, {Component} from 'react';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0,
message: "Hello World"
}
}
render() {
console.log("App render函数被调用");
return (
<div>
<h2>当前计数: {this.state.counter}</h2>
<button onClick={e => this.increment()}>+1</button>
<button onClick={e => this.changeText()}>改变文本</button>
</div>
)
}
shouldComponentUpdate(nextProps, nextState) {
if (this.state.counter !== nextState.counter) {
return true;
}
return false;
}
increment() {
this.setState({
counter: this.state.counter + 1
})
}
changeText() {
this.setState({
message: "你好啊,李银河"
})
}
}
PureComponent的使用
import React, { PureComponent } from 'react';
// Header
function Header() {
console.log("Header被调用");
return <h2>我是Header组件</h2>
}
// Main
class Banner extends PureComponent {
render() {
console.log("Banner render函数被调用");
return <h3>我是Banner组件</h3>
}
}
function ProductList() {
console.log("ProductList被调用");
return (
<ul>
<li>商品列表1</li>
<li>商品列表2</li>
<li>商品列表3</li>
<li>商品列表4</li>
<li>商品列表5</li>
</ul>
)
}
class Main extends PureComponent {
render() {
console.log("Main render函数被调用");
return (
<div>
<Banner/>
<ProductList/>
</div>
)
}
}
// Footer
function Footer() {
console.log("Footer被调用");
return <h2>我是Footer组件</h2>
}
export default class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
counter: 0
}
}
render() {
console.log("App render函数被调用");
return (
<div>
<h2>当前计数: {this.state.counter}</h2>
<button onClick={e => this.increment()}>+1</button>
<Header/>
<Main/>
<Footer/>
</div>
)
}
increment() {
this.setState({
counter: this.state.counter + 1
})
}
}
memo的使用
import React, { PureComponent, memo } from 'react';
// Header
const MemoHeader = memo(function Header() {
console.log("Header被调用");
return <h2>我是Header组件</h2>
})
// Main
class Banner extends PureComponent {
render() {
console.log("Banner render函数被调用");
return <h3>我是Banner组件</h3>
}
}
const MemoProductList = memo(function ProductList() {
console.log("ProductList被调用");
return (
<ul>
<li>商品列表1</li>
<li>商品列表2</li>
<li>商品列表3</li>
<li>商品列表4</li>
<li>商品列表5</li>
</ul>
)
})
class Main extends PureComponent {
render() {
console.log("Main render函数被调用");
return (
<div>
<Banner/>
<MemoProductList/>
</div>
)
}
}
// Footer
const MemoFooter = memo(function Footer() {
console.log("Footer被调用");
return <h2>我是Footer组件</h2>
})
export default class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
counter: 0
}
}
render() {
console.log("App render函数被调用");
return (
<div>
<h2>当前计数: {this.state.counter}</h2>
<button onClick={e => this.increment()}>+1</button>
<MemoHeader/>
<Main/>
<MemoFooter/>
</div>
)
}
increment() {
this.setState({
counter: this.state.counter + 1
})
}
}
受控与非受控组件
refs的使用
import React, { PureComponent, createRef, forwardRef } from 'react';
class Home extends PureComponent {
render() {
return <h2>Home</h2>
}
}
// 高阶组件forwardRef
const Profile = forwardRef(function(props, ref) {
return <p ref={ref}>Profile</p>
})
export default class App extends PureComponent {
constructor(props) {
super(props);
this.titleRef = createRef();
this.homeRef = createRef();
this.profileRef = createRef();
}
render() {
return (
<div>
<h2 ref={this.titleRef}>Hello World</h2>
<Home ref={this.homeRef}/>
<Profile ref={this.profileRef} name={"why"}/>
<button onClick={e => this.printRef()}>打印ref</button>
</div>
)
}
printRef() {
console.log(this.titleRef.current);
console.log(this.homeRef.current);
console.log(this.profileRef.current);
}
}
import React, { PureComponent, createRef, Component } from 'react';
class Counter extends PureComponent {
constructor(props) {
super(props);
this.state = {
counter: 0
}
}
render() {
return (
<div>
<h2>当前计数: {this.state.counter}</h2>
<button onClick={e => this.increment()}>+1</button>
</div>
)
}
increment() {
this.setState({
counter: this.state.counter + 1
})
}
}
export default class App extends PureComponent {
constructor(props) {
super(props);
this.titleRef = createRef();
this.counterRef = createRef();
this.titleEl = null;
}
render() {
return (
<div>
{/* <h2 ref=字符串/对象/函数>Hello React</h2> */}
<h2 ref="titleRef">Hello React</h2>
{/* 目前React推荐的方式 */}
<h2 ref={this.titleRef}>Hello React</h2>
<h2 ref={arg => this.titleEl = arg}>Hello React</h2>
<button onClick={e => this.changeText()}>改变文本</button>
<hr/>
<Counter ref={this.counterRef}/>
<button onClick={e => this.appBtnClick()}>App按钮</button>
</div>
)
}
changeText() {
// 1.使用方式一: 字符串(不推荐, 后续的更新会删除)
this.refs.titleRef.innerHTML = "Hello Coderwhy";
// 2.使用方式二: 对象方式
this.titleRef.current.innerHTML = "Hello JavaScript";
// 3.使用方式三: 回调函数方式
this.titleEl.innerHTML = "Hello TypeScript";
}
appBtnClick() {
this.counterRef.current.increment();
}
}
class App extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Counter title={}></Counter>
</div>
)
}
}
高阶组件使用
import React, { PureComponent } from 'react';
// 定义一个高阶组件
function enhanceRegionProps(WrappedComponent) {
return props => {
return <WrappedComponent {...props} region="中国"/>
}
}
class Home extends PureComponent {
render() {
return <h2>Home: {`昵称: ${this.props.nickname} 等级: ${this.props.level} 区域: ${this.props.region}`}</h2>
}
}
class About extends PureComponent {
render() {
return <h2>About: {`昵称: ${this.props.nickname} 等级: ${this.props.level} 区域: ${this.props.region}`}</h2>
}
}
const EnhanceHome = enhanceRegionProps(Home);
const EnhanceAbout = enhanceRegionProps(About);
class App extends PureComponent {
render() {
return (
<div>
App
<EnhanceHome nickname="coderwhy" level={90}/>
<EnhanceAbout nickname="kobe" level={99}/>
</div>
)
}
}
export default App;
鉴权
import React, { PureComponent } from 'react';
class LoginPage extends PureComponent {
render() {
return <h2>LoginPage</h2>
}
}
function withAuth(WrappedComponent) {
const NewCpn = props => {
const {isLogin} = props;
if (isLogin) {
return <WrappedComponent {...props}/>
} else {
return <LoginPage/>
}
}
NewCpn.displayName = "AuthCpn"
return NewCpn;
}
// 购物车组件
class CartPage extends PureComponent {
render() {
return <h2>CartPage</h2>
}
}
const AuthCartPage = withAuth(CartPage);
export default class App extends PureComponent {
render() {
return (
<div>
<AuthCartPage isLogin={true}/>
</div>
)
}
}
生命周期劫持
import React, { PureComponent } from 'react';
function withRenderTime(WrappedComponent) {
return class extends PureComponent {
// 即将渲染获取一个时间 beginTime
UNSAFE_componentWillMount() {
this.beginTime = Date.now();
}
// 渲染完成再获取一个时间 endTime
componentDidMount() {
this.endTime = Date.now();
const interval = this.endTime - this.beginTime;
console.log(`${WrappedComponent.name}渲染时间: ${interval}`)
}
render() {
return <WrappedComponent {...this.props}/>
}
}
}
class Home extends PureComponent {
render() {
return <h2>Home</h2>
}
}
class About extends PureComponent {
render() {
return <h2>About</h2>
}
}
const TimeHome = withRenderTime(Home);
const TimeAbout = withRenderTime(About);
export default class App extends PureComponent {
render() {
return (
<div>
<TimeHome />
<TimeAbout />
</div>
)
}
}
class Person {
}
console.log(Person.name);
组件内容补充
全局事件
import React, { PureComponent } from 'react';
import { EventEmitter } from 'events';
// 事件总线: event bus
const eventBus = new EventEmitter();
class Home extends PureComponent {
componentDidMount() {
eventBus.addListener("sayHello", this.handleSayHelloListener);
}
componentWillUnmount() {
eventBus.removeListener("sayHello", this.handleSayHelloListener);
}
handleSayHelloListener(num, message) {
console.log(num, message);
}
render() {
return (
<div>
Home
</div>
)
}
}
class Profile extends PureComponent {
render() {
return (
<div>
Profile
<button onClick={e => this.emmitEvent()}>点击了profile按钮</button>
</div>
)
}
emmitEvent() {
eventBus.emit("sayHello", 123, "Hello Home");
}
}
export default class App extends PureComponent {
render() {
return (
<div>
<Home/>
<Profile/>
</div>
)
}
}
learn-router
import React, { PureComponent } from 'react';
import { renderRoutes } from 'react-router-config';
import routes from './router';
import {
BrowserRouter,
Link,
Route,
NavLink,
Switch,
withRouter
} from 'react-router-dom';
import './App.css';
import Home from './pages/home';
import About from './pages/about';
import Profile from './pages/profile';
import User from './pages/user';
import NoMatch from './pages/noMatch';
import Login from './pages/login';
import Product from './pages/product';
import Detail from './pages/detail';
import Detail2 from './pages/detail2';
import Detail3 from './pages/detail3';
class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
links: [
{ to: "/", title: "首页" },
{ to: "/about", title: "首页" },
{ to: "/", title: "首页" },
]
}
}
render() {
const id = "123";
const info = {name: "why", age: 18, height: 1.88};
return (
<div>
{/* <Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Link to="/profile">我的</Link> */}
{/* 1.NavLink的使用 */}
{/* <NavLink exact to="/" activeStyle={{color: "red", fontSize: "30px"}}>首页</NavLink>
<NavLink to="/about" activeStyle={{color: "red", fontSize: "30px"}}>关于</NavLink>
<NavLink to="/profile" activeStyle={{color: "red", fontSize: "30px"}}>我的</NavLink> */}
<NavLink exact to="/" activeClassName="link-active">首页</NavLink>
<NavLink to="/about" activeClassName="link-active">关于</NavLink>
<NavLink to="/profile" activeClassName="link-active">我的</NavLink>
<NavLink to="/abc" activeClassName="link-active">abc</NavLink>
<NavLink to="/user" activeClassName="link-active">用户</NavLink>
<NavLink to={`/detail/${id}`} activeClassName="link-active">详情</NavLink>
<NavLink to={`/detail2?name=why&age=18`} activeClassName="link-active">详情2</NavLink>
<NavLink to={{
pathname: "/detail3",
search: "name=abc",
state: info
}}
activeClassName="link-active">
详情3
</NavLink>
<button onClick={e => this.jumpToProduct()}>商品</button>
{/* 2.Switch组件的作用: 路径和组件之间的映射关系 */}
{/* <Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
<Route path="/:id" component={User} />
<Route path="/user" component={User} />
<Route path="/login" component={Login} />
<Route path="/product" component={Product} />
<Route path="/detail/:id" component={Detail} />
<Route path="/detail2" component={Detail2} />
<Route path="/detail3" component={Detail3} />
<Route component={NoMatch} />
</Switch> */}
{renderRoutes(routes)}
</div>
)
}
jumpToProduct() {
this.props.history.push("/product");
}
}
export default withRouter(App);
reacthooks的使用
useState
import React, {useState} from 'react';
export default function CounterHook() {
const [count, setCount] = useState(() => 10);
console.log("CounterHook渲染");
function handleBtnClick() {
// setCount(count + 10);
// setCount(count + 10);
// setCount(count + 10);
// setCount(count + 10);
setCount((prevCount) => prevCount + 10);
setCount((prevCount) => prevCount + 10);
setCount((prevCount) => prevCount + 10);
setCount((prevCount) => prevCount + 10);
}
return (
<div>
<h2>当前计数: {count}</h2>
<button onClick={e => setCount(count + 1)}>+1</button>
<button onClick={e => setCount((prevCount) => prevCount + 10)}>+10</button>
<button onClick={handleBtnClick}>+10</button>
<button onClick={e => setCount(count - 1)}>-1</button>
</div>
)
}
useEffect
import React, { useEffect, useState } from 'react'
export default function EffectHookCancelDemo() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("订阅一些事件");
return () => {
console.log("取消订阅事件")
}
}, []);
return (
<div>
<h2>EffectHookCancelDemo</h2>
<h2>{count}</h2>
<button onClick={e => setCount(count + 1)}>+1</button>
</div>
)
}
usecallback
import React, {useState, useCallback, memo} from 'react';
/**
* useCallback在什么时候使用?
* 场景: 在将一个组件中的函数, 传递给子元素进行回调使用时, 使用useCallback对函数进行处理.
*/
const HYButton = memo((props) => {
console.log("HYButton重新渲染: " + props.title);
return <button onClick={props.increment}>HYButton +1</button>
});
export default function CallbackHookDemo02() {
console.log("CallbackHookDemo02重新渲染");
const [count, setCount] = useState(0);
const [show, setShow] = useState(true);
const increment1 = () => {
console.log("执行increment1函数");
setCount(count + 1);
}
const increment2 = useCallback(() => {
console.log("执行increment2函数");
setCount(count + 1);
}, [count]);
return (
<div>
<h2>CallbackHookDemo01: {count}</h2>
{/* <button onClick={increment1}>+1</button>
<button onClick={increment2}>+1</button> */}
<HYButton title="btn1" increment={increment1}/>
<HYButton title="btn2" increment={increment2}/>
<button onClick={e => setShow(!show)}>show切换</button>
</div>
)
}
usememo
import React, { useState, memo, useMemo } from 'react';
const HYInfo = memo((props) => {
console.log("HYInfo重新渲染");
return <h2>名字: {props.info.name} 年龄: {props.info.age}</h2>
});
export default function MemoHookDemo02() {
console.log("MemoHookDemo02重新渲染");
const [show, setShow] = useState(true);
// const info = { name: "why", age: 18 };
const info = useMemo(() => {
return { name: "why", age: 18 };
}, []);
return (
<div>
<HYInfo info={info} />
<button onClick={e => setShow(!show)}>show切换</button>
</div>
)
}
useRef
import React, { useEffect, useRef } from 'react';
class TestCpn extends React.Component {
render() {
return <h2>TestCpn</h2>
}
}
function TestCpn2(props) {
return <h2>TestCpn2</h2>
}
export default function RefHookDemo01() {
const titleRef = useRef();
const inputRef = useRef();
const testRef = useRef();
const testRef2 = useRef();
function changeDOM() {
titleRef.current.innerHTML = "Hello World";
inputRef.current.focus();
console.log(testRef.current);
console.log(testRef2.current);
}
return (
<div>
<h2 ref={titleRef}>RefHookDemo01</h2>
<input ref={inputRef} type="text"/>
<TestCpn ref={testRef}/>
<TestCpn2 ref={testRef2}/>
<button onClick={e => changeDOM()}>修改DOM</button>
</div>
)
}
import React, { useRef, useState, useEffect } from 'react'
export default function RefHookDemo02() {
const [count, setCount] = useState(0);
const numRef = useRef(count);
useEffect(() => {
numRef.current = count;
}, [count])
return (
<div>
{/* <h2>numRef中的值: {numRef.current}</h2>
<h2>count中的值: {count}</h2> */}
<h2>count上一次的值: {numRef.current}</h2>
<h2>count这一次的值: {count}</h2>
<button onClick={e => setCount(count + 10)}>+10</button>
</div>
)
}
useImperativeHandle
import React, { useRef, forwardRef, useImperativeHandle } from 'react';
const HYInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}), [inputRef])
return <input ref={inputRef} type="text"/>
})
export default function UseImperativeHandleHookDemo() {
const inputRef = useRef();
return (
<div>
<HYInput ref={inputRef}/>
<button onClick={e => inputRef.current.focus()}>聚焦</button>
</div>
)
}
useLayoutEffect
import React, { useRef, forwardRef, useImperativeHandle } from 'react';
const HYInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}), [inputRef])
return <input ref={inputRef} type="text"/>
})
export default function UseImperativeHandleHookDemo() {
const inputRef = useRef();
return (
<div>
<HYInput ref={inputRef}/>
<button onClick={e => inputRef.current.focus()}>聚焦</button>
</div>
)
}