day18

一、事件

1.事件绑定

(1)es5方式

<button onClick={ this.start }>开始</button>
上面的写法,对应的函数中获取不到this指向
<button onClick={ this.start.bind(this) }>开始</button>

(2)es6方式

<button onClick={ ()=>this.stop() }>停止</button>

示例代码:

import React, { Component } from 'react'
export default class Clock extends Component {
   state = {
       nowtime : '',
       timer:null//定时器编号
  }
   start(){
       var timer = setInterval(()=>{
           this.setState({nowtime:new Date().toLocaleTimeString()})
      },1000)
       this.setState({ timer })
  }
   stop(){
       clearInterval(this.state.timer)
  }
   render() {
       return (
           <div>
               <h1>当前时间:{ this.state.nowtime }</h1>
              {/* es5方式绑定事件,对应的函数名称后不加小括号,如果加了小括号就会自动执行函数 */}
              {/* es5方式绑定事件,对应的事件函数中默认获取不到this指向
                  如果需要获取到this指向,需要通过.bind(this)来绑定this指向 */}
              {/* <button onClick={ this.start }>开始</button> */}
               <button onClick={ this.start.bind(this) }>开始</button>
              {/* es6方式绑定事件,对应的事件函数能够获取this指向 */}
               <button onClick={ ()=>this.stop() }>停止</button>
           </div>
      )
  }
}

2.事件对象

(1)es5方式

<button onClick={ this.handle1.bind(this) }>事件对象-es5</button>

es5方式触发事件,如果在调用函数时没有传递参数,而函数中存在一个形参,那么这个形参就是事件对象

(2)es6方式

<button onClick={ (e)=>this.handle1(e) }>事件对象-es6</button>

es6方式触发事件,需要显式的传递参数,在对应的函数中才能够获取到事件对象

3.传递参数

(1)es5方式

<button onClick={ this.handle2.bind(this,100,'hello') }>es5-传递参数</button>

es5方式调用函数传递参数时,在函数中多出来的形参(最后一个形参)是事件对象

(2)es6方式

<button onClick={ (e)=>this.handle2(100,e,'hello') }>es6-传递参数</button>

es6方式调用函数传递参数,传递的是什么内容,对应函数中形参接收到的就是什么

4.模拟表单元素双向绑定

import React, { Component } from 'react'

export default class Login extends Component {
   state = {
       username:'',
       password:''
  }
   iptChange(event,key){
       var data = this.state;
       //根据对象和键名来修改数据
       data[key] = event.target.value;
       //通过setState来修改状态机中的数据,并重新渲染页面
       this.setState(data);
  }
   dologin(){
       console.log(this.state)
  }
   render() {
       return (
           <div>
              {/* 模拟vue的v-model双向绑定 */}
               <h1>登录</h1>
               <form>
                   <div>
                       <label>用户名:</label>
                       <input type="text" placeholder="请输入用户名"
                           value={ this.state.username } onChange={ (e)=>this.iptChange(e,'username') }
                           autoComplete="off"
                       />
                   </div>
                   <div>
                       <label>密码:</label>
                       <input type="password" placeholder="请输入密码"
                           value={ this.state.password } onChange={ e=>this.iptChange(e,'password') }
                       />
                   </div>
                   <div>
                       <button type="button" onClick={ ()=>this.dologin() }>登录</button>
                   </div>
               </form>
           </div>
      )
  }
}

二、组件通信

1.父子组件

父组件:自定义属性

import Child from './Child'
export default class Home extends Component {
state = { goodsarr:[] }
render() {
      return (
          <div>
              {
                  this.state.goodsarr.map(item=>{
                      return(
                          <Child key={ item.id } info={ item }></Child>
                      )
                  })
              }
          </div>
      )
  }
}

子组件:props

import React, { Component } from 'react'
import '../assets/css/child.css'
export default class Child extends Component {
  render() {
      return (
          <div className="item">
              <img src={ this.props.info.img } alt=""/>
              <p>名称:{ this.props.info.goodsname }</p>
              <p>价格:{ this.props.info.price }</p>
          </div>
      )
  }
}

2.子父组件

父组件,传递数据的同时可以传递自定义事件

delgoods(id){
   // console.log('父组件...',n)
   //n 要删除的商品id
   // var idx = this.state.goodsarr.findIndex(item=> item.id == id)
   var idx = this.state.goodsarr.findIndex(item=> {
  return item.id == id;
  })
   var data = this.state.goodsarr;
   data.splice(idx,1);
   this.setState({ goodsarr:data })
}
render() {
       return (
           <div>
              {
                   this.state.goodsarr.map(item=>{
                       return(
                           <Child key={ item.id }
                           info={ item }
                           homedel={ (id)=>this.delgoods(id) }
                          ></Child>
                      )
                  })
              }
           </div>
      )
  }

子组件:

vue中:通过$emit来触发父组件传递的事件并传递参数给父组件

react中:

function Child(props){
   return(
       <div>
           <div className="item">
               <img src={ props.info.img } alt=""/>
               <p>名称:{ props.info.goodsname }</p>
               <p>价格:{ props.info.price }</p>
               <button onClick={ ()=>props.homedel(props.info.id) }>删除</button>
           </div>
       </div>
  )
}
export default Child;

3.非父子组件

(1)创建一个公用容器

/src/assets/js/bus.js

const EventEmitter = require('events')
const MyEvent = new EventEmitter();
export default MyEvent;

(2)在/src/index.js引入公用的容器,并把它挂在到Component原型上

import React,{ Component } from 'react'
import ReactDOM from 'react-dom'
//引入根组件
import App from './App'
//引入公用容器
import bus from './assets/js/bus'
//把公用容器挂载到Component原型上
Component.prototype.bus = bus;

数据发送端:emit

/src/components/Home.js

sendData(){
this.bus.emit('0128','不是成功来的慢,而是放弃速度快');
}

数据接收端:on

/src/components/Clock.js

constructor(){
  super()
  this.bus.on('0128',(msg)=>{
  this.setState({msg:msg})
  })
}
state = {
  nowtime : '',
  timer:null,//定时器编号
  msg:''
}

三、生命周期

只有类组件才有生命周期

1.页面渲染期

constructor 构造函数

UNSAFE_componentWillMount 组件将要挂载

render 组件渲染

componentDidMount 组件挂载完成

2.页面更新期

UNSAFE_componentWillReceiveProps 子组件将要接收父组件传递过来的最新数据

shouldComponentUpdate 组件是否要更新数据,预期得到的是一个布尔值

true表示更新数据,false表示不更新数据

UNSFAE_componentWillUpdate 组件将要更新

render 组件渲染

componentDidUpdate 组件更新完成

3.页面销毁期

componentWillUnmout 组件将要销毁(不再显示)

posted @ 2021-01-28 17:03  安亦辰00  阅读(123)  评论(0)    收藏  举报