React组件操作
组件传参
父子
子父
非父子
react本身没有非父子传参的策略,所以需要依赖三方的非父子组件传参插件, events
安装
npm i events -S
设置events插件
使用events插件
生命周期
挂载阶段
componentWillMount (vue created)
数据将要挂载,数据存在,但是dom对象没有实例化完成
自动执行一次
render
数据在修改,数据存在,但是dom对象没有实例化完成
自动执行一次
componentDidMount (vue mounted)
挂载完成
自动执行一次
import React, { Component } from 'react'
export default class Smzq extends Component {
state={
msg: "生命周期msg变量"
}
UNSAFE_componentWillMount(){
console.log(this.state.msg,'msg')
var obj = document.querySelector("#msg")
console.log(obj,"p标签对象")
console.log("+++++++++++++++componentWillMount++++++++++++++++++++")
}
render() {
console.log(this.state.msg,'msg')
var obj = document.querySelector("#msg")
console.log(obj,"p标签对象")
console.log("+++++++++++++++render++++++++++++++++++++")
return (
<div>
<p id="msg">{this.state.msg}</p>
</div>
)
}
componentDidMount(){
console.log(this.state.msg,'msg')
var obj = document.querySelector("#msg")
console.log(obj,"p标签对象")
console.log("+++++++++++++++componentDidMount++++++++++++++++++++")
}
}
修改阶段
props 父组件在子组件标签上定义的所有属性
componentWillReceiveProps
在props数据修改之前执行,在子组件才可以执行
第一个参数:修改后的变量 第二参数:修改前的变量
shouldComponentUpdate
判断是否更新数据,必须返回布尔值,如果为ture执行之后的声明周期
如果为false停止执行后面的声明周期
修改之前执行
componentWillUpdate
数据修改之前,数据还没有修改
三个参数
第一个参数:修改前的变量 第二参数:修改后的变量
render
修改中,数据修改完成了
componentDidUpdate
三个参数
修改之后,数据修改完成了
第一个参数:修改后的变量 第二参数:修改前的变量
import React, { Component } from 'react'
export default class Smzq extends Component {
state={
msg: "生命周期msg变量"
}
change(){
this.setState({msg: "hello world"})
}
shouldComponentUpdate(old,news){
console.log(this.state.msg,"shouldComponentUpdate")
if(this.state.msg === news.msg){
console.log("都一样,改个寂寞啊?")
return false
}else{
console.log("改吧,改吧,反正你说了算")
return true
}
}
UNSAFE_componentWillUpdate(){
console.log(this.state.msg,"componentWillUpdate")
}
componentDidUpdate(){
console.log(this.state.msg,"componentDidUpdate")
}
render() {
console.log(this.state.msg,'render')
return (
<div>
<p id="msg">{this.state.msg}</p>
<button onClick={this.change.bind(this)}>修改</button>
</div>
)
}
}
修改父类传递的props数据触发
import React, { Component } from 'react'
export default class Smzq extends Component {
state={
msg: "生命周期msg变量"
}
change(){
this.setState({msg: "hello world"})
}
UNSAFE_componentWillReceiveProps(){
console.log(arguments,'componentWillReceiveProps')
}
render() {
console.log(this.state.msg,'render')
return (
<div>
<p id="msg">{this.state.msg}</p>
<button onClick={this.change.bind(this)}>修改</button>
<p>{this.props.message}</p>
</div>
)
}
}
销毁阶段
componentWillUnmount
销毁之前执行
子组件
释放内存
import React, { Component } from 'react'
export default class Smzq extends Component {
state={
msg: "生命周期msg变量"
}
componentWillUnmount(){
console.log(arguments)
console.log("componentWillUnmount")
}
render() {
return (
<div>
<p id="msg">{this.state.msg}</p>
</div>
)
}
}
控制部分
import React from 'react'
import Child1 from './child1'
import Child2 from './child2'
import Smzq from './Smzq'
class Parents extends React.Component{
state={
msg: "父组件的消息",
isShow: true
}
recv_date(message){
this.setState({msg:message})
}
change(){
this.setState({msg: "hello world"})
}
render(){
return <div>
<p style={{background: 'skyblue'}}>这是父元素的p</p>
<Child1 message={this.state.msg}></Child1>
<Child2 recver={this.recv_date.bind(this)}></Child2>
{/* <Smzq message={this.state.msg}></Smzq> */}
{this.state.isShow?<Smzq message={this.state.msg}></Smzq>:""}
<button onClick={this.change.bind(this)}>修改父类的msg</button>
<button onClick={()=>this.setState({isShow: !this.state.isShow})}>切换命名周期组件</button>
</div>
}
}
ref
react和vue一样,使用虚拟dom技术。
import React, { Component } from 'react'
import About from './About'
export default class Home extends Component {
componentDidMount(){
console.log(this.refs)
this.refs.h3_ref.style.backgroundColor="pink"
this.refs.about_ref.say_hello()
}
render() {
return (
<div>
<h3 ref="h3_ref">hello world</h3>
<About ref="about_ref"></About>
</div>
)
}
}
About子组件
import React, { Component } from 'react'
export default class About extends Component {
say_hello(){
console.log("hello world")
}
render() {
return (
<div>
</div>
)
}
}
this.refs在不久的将来可能被弃用,所以有了两种特色的写法
手动设置虚拟dom元素
直观写法
表单绑定
受控组件
import React, { Component } from 'react'
export default class Home extends Component {
state = {
username: "张飞",
gender: "女",
hobby: ["唱","跳","rap"],
city: "南阳",
description: "睁眼睡觉"
}
changeCheckBox(e){
var value = e.target.value
if(this.state.hobby.includes(value)){
const index = this.state.hobby.indexOf(value)
this.state.hobby.splice(index,1)
}else{
this.state.hobby.push(value)
}
this.setState({hobby: this.state.hobby})
}
render() {
return (
<div>
<p>{this.state.username}</p>
<p>{this.state.gender}</p>
<p>{this.state.hobby}</p>
<p>{this.state.city}</p>
<p>{this.state.description}</p>
<form>
<div>
<input type="text" value={this.state.username} onChange={e=>this.setState({username: e.target.value})} placeholder="姓名"/>
</div>
<div>
性别
<input type="radio" checked={this.state.gender === "男"} onChange={e=>this.setState({gender: e.target.value})} name="gender" value="男"/> 男
<input type="radio" checked={this.state.gender === "女"} name="gender" onChange={e=>this.setState({gender: e.target.value})} value="女"/> 女
</div>
<div>
爱好
<input type="checkbox" checked={this.state.hobby.includes("唱")} name="hobby" onChange={e=>this.changeCheckBox(e)} value="唱"/> 唱
<input type="checkbox" checked={this.state.hobby.includes("跳")} name="hobby" onChange={e=>this.changeCheckBox(e)} value="跳"/> 跳
<input type="checkbox" checked={this.state.hobby.includes("rap")} name="hobby" onChange={e=>this.changeCheckBox(e)} value="rap"/> rap
</div>
<div>
城市
<select defaultValue={this.state.city} onChange={e=>this.setState({city: e.target.value})}>
<option value="涿郡">涿郡</option>
<option value="荆州">荆州</option>
<option value="南阳">南阳</option>
<option value="许昌">许昌</option>
<option value="洛阳">洛阳</option>
<option value="长安">长安</option>
</select>
</div>
<div>
自我介绍
<textarea value={this.state.description} onChange={e=>this.setState({description: e.target.value})}></textarea>
</div>
</form>
</div>
)
}
}
非受控组件
import React, { Component } from 'react'
export default class Home extends Component {
getValue(){
console.log(this.input_ref.value)
}
render() {
return (
<div>
<input ref={dom=>this.input_ref=dom} />
<button onClick={this.getValue.bind(this)}>获取值</button>
</div>
)
}
}
react内置组件
React.Fragment
作用: 给组件的视图提供一个唯一的根标签, 并且渲染之后, 不会产生额外的标签包裹
或者写为
React.PureComponent
作用: 避免组件的无效更新
使用: 使用我们的页面组件直接继承React.PureComponent
应用场景: 进行性能优化
import React, { PureComponent } from 'react'
export default class Home extends PureComponent {
state={
msg: "hello world"
}
change(){
this.setState({msg: "hi world"})
}
UNSAFE_componentWillUpdate(){
console.log("发生修改了")
}
render() {
return (
<>
{this.state.msg}
<button onClick={this.change.bind(this)}>修改</button>
</>
)
}
}
react HOC高阶组件
1、High Order Component
2、高阶组件是react中复用组件的一种策略
本质: 一个函数, 这个函数可以接收一个组件, 会返回一个新的组件,就是对组件的嵌套
高阶组件再其他语言当中也是存在的,可能被称为装饰器或函数嵌套,实际上就是组件复用的过程。
给不同组件添加相同的数据,
function 班长(){
console.log("新年快乐,班费交一下")
}
function 学习委员(){
console.log("新年快乐,作业交一下")
}
function 生活委员(){
console.log("新年快乐,宿舍打扫一下")
}
function 装饰器(fun){
console.log("优快云祝大家新年快乐")
fun()
}
装饰器(班长)
装饰器(学习委员)
装饰器(生活委员)
比如电商网站上,订单页,购物车页都需要用户的信息,而信息存在localstorage当中,这个时候我们面对的是是否要多次从localstorage当中获取用户信息的问题。
import React, { PureComponent } from 'react'
import order from './Order'
import buyCar from './BuyCar'
export default class Home extends PureComponent {
setDate(Dom){
var data = "MC老王"
return class extends PureComponent{
render(){
return <Dom user={data}></Dom>
}
}
}
render() {
const Order = this.setDate(order)
const BuyCar = this.setDate(buyCar)
return (
<>
<Order></Order>
<BuyCar></BuyCar>
</>
)
}
}