通过调用 setState
默认是异步的 在更新数据的时候不会影响主线程代买继续往下执行 但是在计时器里面是同步的
普通函数:函数内部的 this 默认 undefined,需要显示的绑定 this 的执行。 箭头函数:箭头函数里面的 this 默认执行当前组件。直接调用即可 绑定 this 的执行: onClick = {this.chang.bind(this)} 组件初始化的时候就给 check 绑定 this constructor(){ super() this.chang = this.chang.bind(this) } 一般组件开发过程中推荐使用箭头函数
无法直接加载本地图片,使用相对路径找不到图片
1.import 模块化的方式导入: import logo from "../../"
2.require 模块化的方式导入
<img src={require(${imgSrc}
).defult}/> 3.使用网络图片跟之前一样
http://web.woniulab.com:8082/img/i1.jpg
http://web.woniulab.com:8082/img/i2.jpg
http://web.woniulab.com:8082/img/i3.jpg
Props 对象 组件可以通过 props 这个对象获取外部数据 props 用于父子之间通信 一旦父组件发生改变 子组件立即更新 也可以使用扩展的方式传递 子组件在生命周期里获取传递的参数 componentDidMount() { console.log(this); console.log(this.props); }
如果指定传给子组件的数据是数字
函数组件获取父组件传递的值 export default function Chlid2(props) { console.log(props); return ( // 函数组件没有 this
); }Props 默认值 父组件传数据给子组件,可能接收不到指定的值,可以设置默认值防止报错 函数组件和类组件都是一样的 Child.defaultProps = { username:"默认值" }
Props 验证器 验证器的作用就是就是设置 Props 传递进来的类型,要求的类型是 String 传递进来的是 Number 默认会抛出警告
在头部引入 import PropTypes from "prop-types";
Child.propTypes = {
age: PropTypes.number.isRequired,
msg: PropTypes.string.isRequired,
user: PropTypes.object.isRequired,
};
子组件传递父组件 Vue 中自定义事件 $emit() React 中 props 值也不能修改 满足单项数据流程。 子组件里你可以修改 Prop 里面传递过来的引用类型只要不该地址里面的内容随便改。 在 React 中父组件传递事件给子组件,子组件直接调用。
语法一: 无需将表单和 state 进行绑定 直接在表单元素身上增加一个 ref 属性,ref 属性接收一个回调函数 返回一个 element 节点 通过节点获取到数据 <input type="text" ref={(ele) => {this.username = ele;}}/> 语法二: 可以在构造函数里面定义一个变量,通过变量来创建组件引用,就可以获取到这个节点
new Vue({
data(){
consloe.log(1) 2
return {
number:2
}
},
beforceCreate(){
console.log(this.number) 1
},
created(){
console.log(this.number) 3
},
mounted(){}
})
React 生命周期钩子函数 分为三个阶段 1.挂载阶段(初始换节点) 组件内部 state、props 进行初始换节点完成渲染阶段 2.更新节点(运行阶段) 这个是组件最长的一个阶段,只对组件数据进行更新,页面重绘和回流 3.卸载阶段(销毁阶段) 这个阶段是组件的销毁阶段,组件从页面移出执行这个阶段,资源回收的一些工作 组件挂载阶段执行的顺序
import React, { Component } from "react";
export default class Comm extends Component {
constructor() {
super();
console.log("1、构造器执行");
}
componentDidMount() {
console.log("3、组件挂载完成后执行");
}
render() {
console.log("2、render 方法渲染");
return <div>comm</div>;
}
}
componentDidMount 可以在这个钩子函数中执行异步请求,也可以获取带节点,在这个函数中执行定时器任务 这个组件只会在生命周期阶段里执行一次
组件时间最长的阶段,主要的作用监控组件的数据是否发生改变。state 内部数据 props 外部数据
在更新阶段提供两个生命周期钩子函数
shouldComponentUpdate 更新之前要执行的代码,必须提供 一个 boolean 返回值,true 更新页面,false 不更新
shouldComponentUpdate() {
console.log("组件更新");
return true;
}
componentDidUpdate 再给组件更新过后执行的钩子函数,可以获取到更新后的节点
componentWillUnmount
组件销毁阶段可以清理运行资源 定时器清空 时间函数解绑
路由的概念:
spa 单页开发:将页面的 UI 拆分为一个一个组件,通过路由的方式进行组件的切换
多页面开发:不存在路由的说法,超链接直接跳转。
yarn add react-router-dom@5.2.0
import {
{HashRouter,
BrowserRouter,}//路由模式
{Switch,
Route,}//路由匹配器,目的就是为了匹配你对应要访问的组件
/*
Switch 表示跟js中的Switch一个意思,匹配某一个case 一旦匹配成功就不会匹配其他内容
Route 将url地址和组件映射在一起,通过匹配这个地址就能匹配对应组件
*/
Redirect,//重定向
} from "react-router-dom";
import Login from "./pages/Login";
import Register from "./pages/Register";
import Home from "./pages/Home";
<HashRouter>
<Switch>
<Redirect exact from="/" to="/login"></Redirect>
<Route path={"/register"} component={Register}></Route>
<Route path={"/login"} component={Login}></Route>
<Route path={"/home"} component={Home}></Route>
</Switch>
</HashRouter>
Route 使用过程中 会用到一些内容
exact 精确匹配路由, 不加该属性默认模糊匹配
Link、NavLink
如果你的组件是使用 Route 组价动态加载的,那 props 对象上会动态添加三个属性
history:包含**push、replace、listen(**路由监听器)
location:里面包含的hash值,search传递的参数等等
match:获取到匹配后的结果,也可以接收参数
this.props.history.push("/home");
this.props.history.replace("/home");
//push可以记录之前的路径返回
//peplace不会记录之前的地址,浏览器无法返回
组件的分类:
1.路由组件:通过 Route 组件俩进行加载的组件我们称为路由组价,一般放在 pages 文件夹
2.非路由组件:import 引入的组件
非路由组件可以使用 **withRouter ** 高阶组件来包装一下 动态转换成路由组件
import React, { Component } from "react";
import { withRouter } from "react-router-dom";
class Header extends Component {
logout = () => {
// console.log(this.props);
this.props.history.replace("/login");
};
render() {
return (
<div>
<button
onClick={() => {
this.logout();
}}
style={{ float: "right" }}
>
退出登录
</button>
</div>
);
}
}
export default withRouter(Header);
const wichRouter = (cpm) => {
return () => {
return <Route component={cpm}></Route>;
};
};
<Route path='/path/:name' component={Path}/>
<link to="/path/2">xxx</Link>
this.props.history.push({pathname:"/path/" + name});
读取参数用:this.props.match.params.name
<Route path='/query' component={Query}/>
navLogin = () => {
this.props.history.push({
pathname: "/login",
query: {
id: "1",
name: "小明",
},
});
};
<Link to={{ path : ' /query' , query : { name : 'sunny' }}}>
this.props.history.push({pathname:"/query",query: { name : 'sunny' }});
读取参数用: this.props.location.query.name
/*
优点是是参数不会显示在地址栏
缺点是刷新页面参数都会消失
*/
<Route path='/web/departManange ' component={DepartManange}/>
<link to="web/departManange?tenantId=12121212">xxx</Link>
this.props.history.push({pathname:"/web/departManange?tenantId" + row.tenantId});
读取参数用: this.props.location.search
//在地址栏新增属性,可以完成页面传递参数,这种方式传递过去需要字节解析字符串
使用第三方插件
yarn add react-loadable
// 引入懒加载插件
import loadable from "react-loadable";
const Login = loadable({
loading: () => <Loading></Loading>,
loader: () => import("./pages/Login"),
});
官方
**React.Suspense:**组件需要将路由器包裹起来,路由器对应组将就可以用到懒加载
**React.lazy():**调用这个函数可以动态 import 需要的组件
**fallback{}:**接收一个动画组价,网络慢的情况下可以加载动画
<React.Suspense fallback={<Loading></Loading>}>
<HashRouter>
<Switch>
<Route
path={"/login"}
component={React.lazy(() => import("./page/login"))}
></Route>
<Route path={"/register"} component={Register}></Route>
<Route path={"/home"} component={Home}></Route>
</Switch>
</HashRouter>
</React.Suspense>