7.Hooks API
-
React 16.7 以后开始
-
npm info react versions
-
函数组件中也可以有自己的状态,不非得Class组件了
-
Hooks can only be called inside the body of a function component
-
React Class 组件写法
import React from "react";
export default class App extends React.Component {
constructor() {
super();
this.state = {
count: 0
};
}
add = () => {
this.setState({
count: this.state.count + 1
});
};
minus = () => {
this.setState({
count: this.state.count - 1
});
};
render() {
return (
<div>
<div>{this.state.count}</div>
<div>
<button onClick={this.add}>+1</button>
<button onClick={this.minus}>-1</button>
</div>
</div>
);
}
}
7.1 useState
import { useState } from "react";
let [值,更新函数] = useState(初始值);
import React from "react";
import "./styles.css";
import { useState } from "react";
export default function App() {
// let count = 0;
// let add = function () {};
const [count, setCount] = useState(100);
const [user, setUser] = useState({
name: "paul",
age: 18,
hobbies: ["抽烟", "喝酒", "烫头"]
});
const add = () => {
setCount(count + 1);
};
const minus = () => {
setCount(count - 1);
};
const old = () => {
setUser({
...user,
age: user.age + 1
});
};
const addHobby = () => {
let newHobby = "打麻将";
setUser({
...user,
hobbies: [...user.hobbies, newHobby]
});
};
return (
<div>
<div>{count}</div>
<div>
<button onClick={add}>+1</button>
<button onClick={minus}>-1</button>
</div>
<div>{user.age}</div>
<div>{user.hobbies.join("-")}</div>
<div>
<button onClick={old}>+1</button>
<button onClick={addHobby}>增加爱好</button>
</div>
</div>
);
}
7.2 useEffect
- 副作用(Side Effect): 函数或者表达式的行为依赖于外部世界
function fn1() {console.log(1, 2)} // console.log就是副作用,外部的
function fn2(a, b) {return a + b}
// 如果修改了 console.log = function() {},再执行fn1(),结果不受控制
fn1是一个有副作用的函数,fn2是一个纯函数
- Effect Hook为函数式组件增添了执行 side Effect的能力
- Effect Hook 可以让你在函数组件中执行副作用操作
- 把副作用都写在useEffect中
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
// document 就是外部来的浏览器API
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
8. React-Router
8.1 使用hash做路由
-
- 获取用户hash值(window.location.hash)
-
- 根据hash跳转
-
- 分享带hash的地址
- codesandbox.io/s/intellige…
- wmnrt.csb.app/#signup
import React, { useState } from "react";
import "./styles.css";
function Box1() {
return <div class="box">注册</div>;
}
function Box2() {
return <div class="box">登录</div>;
}
export default function App() {
let hash = window.location.hash;
let initUi = hash === "#signup" ? "注册" : "登录";
let [ui, setUi] = useState(initUi);
const onClickLogin = () => {
setUi("登录");
window.location.hash = "login";
};
const onClickSignUp = () => {
setUi("注册");
window.location.hash = "signup";
};
return (
<div className="App">
<button onClick={onClickLogin}>登录</button>
<button onClick={onClickSignUp}>注册</button>
<div>{ui === "注册" ? <Box1 /> : <Box2 />}</div>
</div>
);
}
- 直接改path,浏览器会认定为跳转页面,会刷新
- 会404
window.location.pathname = '/login'
window.location.pathname = '/signup'
- Html5提供的pushState API,不会刷新页面
- 但是后端如果将所有请求路径指向首页,可以这么做
- 否则会404
window.history.pushState(null, '', '/login')
let path = window.location.pathname
hash 和 history.pushState 在处理多路由情况下非常局限
8.2 React-Router
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import "./styles.css";
function Box1() {
return <div class="box">注册</div>;
}
function Box2() {
return <div class="box">登录</div>;
}
function Welcome() {
return <div class="box">欢迎</div>;
}
function App() {
return <div className="App">App</div>;
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<Router>
<div>
<div>
<Link to="/">
<button>首页</button>
</Link>
|<Link to="/login">登录</Link> |<Link to="/signup">注册</Link> |
<Link to="/welcome">欢迎</Link>
</div>
<Route path="/" exact component={App} />
<Route path="/login" component={Box2} />
<Route path="/signup" component={Box1} />
<Route path="/welcome" component={Welcome} />
</div>
</Router>,
rootElement
);
8. 生命周期
8.1 Vanilla.js
// 研究红色框框的生老病死
let app = document.getElementById("app");
// create div 在内存中
let div = document.createElement("div");
div.style.border = "1px solid red";
let state = 1;
// componentWillMount()
// render && update
div.innerHTML = `
<p>${state}</p>
<button>+1</button>
<button>die</button>
`;
// mount div 挂载
app.appendChild(div);
div.querySelector("button").onclick = () => {
state += 1;
// update div
div.querySelector("p").innerText = state;
};
// destory all
div.querySelectorAll("button")[1].onclick = () => {
div.querySelector("button").onclick = null;
div.querySelectorAll("button")[1].onclick = null;
div.remove();
div = null; // destroy div
};
8.2 React中
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
let div = document.createElement("div");
document.body.appendChild(div);
console.log = function(content) {
div.innerHTML += `${content}<br>`;
};
class Baba extends React.Component {
constructor() {
super();
this.state = {
hasChild: true
};
}
onClick() {
this.setState({
hasChild: false
});
}
callSon() {
this.setState({
word: "你还好吧"
});
}
render() {
return (
<div>
我是你爸爸
<button onClick={() => this.onClick()}>kill son</button>
<button onClick={() => this.callSon()}>call son</button>
{this.state.hasChild ? <App word={this.state.word} /> : null}
</div>
);
}
}
class App extends React.Component {
onClick() {
console.log("用户点击了");
this.setState({
n: this.state.n + 1
});
}
updateX() {
this.setState({
x: this.state.x + "!"
});
}
constructor() {
super();
this.state = {
n: 0,
x: "不展示"
};
}
componentWillMount() {
console.log("将要 mount App");
}
render() {
// update
console.log("填充/更新 App 的内容");
return (
<div className="App">
{this.state.n}
<br />
我爸说 {this.props.word}
<br />
<button onClick={() => this.onClick()}>+1</button>
<button onClick={() => this.updateX()}>update x</button>
</div>
);
}
componentDidMount() {
console.log("mount App 完毕");
}
componentWillUpdate() {
console.log("update App 之前");
}
shouldComponentUpdate(nextProps, nextState) {
console.log("要不要更新呢?");
if (this.state.n === nextState.n) {
return false;
} else {
return true;
}
}
//update is render
componentDidUpdate() {
console.log("update App 之后");
}
componentWillUnmount() {
console.log("App 快要死了,记得喂狗");
}
componentWillReceiveProps() {
console.log("我爸说话了");
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Baba />, rootElement);