父子组件传值,非父子组件传值 实例方法/事件封装(2018/12/11)

.一、父组件给子组件传值 (当子组件在父组件中当做标签使用的时候 通过自定义属性进行传值,接受的时候通过this.props进行接受)
思路:
父组件引入子组件,在子组件的标签中添加自定义属性  然后将this.state中的属性传给子组件的标签
子组件通过this.props 接收父组件传过来的属性,添加到虚拟dom中,再通过对虚拟dom的渲染在页面上显示出来
 
this.props是用来接受外部属性
one.js(这是子组件)
 
import React,{Component} from "react"
class one extends Component{
     render(){
            console.log(this.props)  //{info:“1111”}
          let {info} = this.props; //this.props是接收外部属性 如父组件的属性
          return(
              <div>
                   <h2>接收到父组件的值为{info}</h2>
              </div>
          )
     }
}
export default one
 
App.js(这是父组件)
 
import React,{Component} from "react"
import One from './one'  //1) 引入子组件
class App extends Component{
     constructor(){
          super();
          this.state={
              message:'1111'
          }
     }
     render(){
          let {message} = this.state
          return(
              <div>
                   <One  info={message}></One> {/*这是子组件   用自定义属性给子组件传值  info是自定义属性*/}
              </div>
          )
     }
}
export default App
 
 
二、子组件给父组件传值 (当子组件在父组件中当做标签使用的时候  调用父组件的方法进行传值)
 
one.js
 
import React,{Component} from "react"
class one extends Component{
render(){
     console.log(this.props)   //show fn()
     let {info} = this.props
     return(
          <div>
              
              <button   onClick={this.handleClick.bind(this)}>点击</button>  
          </div>
          
     )
}
handleClick(){
     this.props.show("子组件传过来的值") //子组件通过触发点击事件 给绑定在子组件标签上的父组件的show方法中 传递一个值
}
}
export default one
 
App.js
 
import React,{Component} from "react"
import One from './one'  //1) 引入子组件
class App extends Component{
     constructor(){
          super();
          this.state={
              message:'aaaa',
              oneVal:''
          }
     }
     render(){
          let {message,oneVal} = this.state
          return(
              <div>
              <One  show={this.handleShow.bind(this)}></One> //show是绑定在子组件标签上的父组件的方法,用它来接收子组件传过来的值
              <h2>接受到子组件的值为{oneVal}</h2>
              </div>
          )
     }
     handleShow(val){
                console.log(val) //将子组件传过来的值赋给父组件
          this.setState({
              oneVal:val
          })
     }
     
}
export default App
 
 
三、父组件给子组件传值中的-----------默认值的使用 (外部属性的使用)
            有时候父组件给子组件传值会因为父组件中在子组件上设置的自定义属性名称与子组件中接收的自定义属性名称不符而传值失败,所以就需要设定一个默认值,如果两个名称不符的话就用默认值,名称相符就用父传给子的值
            
                组件名称.defaultProps = {   //这个写在子组件中
                            key : val
                            info : “这是一个默认值”
                }
 
 
四、实例方法/事件的封装
 
$on  绑定事件,可以绑定很多函数
 
$on(事件名称,function(){ } )
 
例: $on("abc" , fn1)
        $on("abc" , fn2) 
    一个事件上可以绑定多个函数,当$emit执行的时候可以将这些函数都触发
 
 
$emit   触发事件
$emit("事件名称",需要传递的参数params)
 
例:$emit("abc",1)
 
$off  解绑事件
$off(" 事件名" ,fn)  //如果只写事件名称的话就是解绑这个事件上所有的函数
 
$on  先绑定事件 然后等待 $emit触发这个事件  等到被触发的时候就执行$on中的函数
observe.js
const eventList={
    //click=[] //这里存放的是一个事件名对应多个函数
    
}
const $on = function(eventName,cb){
    //判断当前事件名称是否存在
    if(!eventList[eventName]){ //如果eventList中不存在这个时间
         eventList[eventName]=[]  //则事件对应的函数也为空
    }
    eventList[eventName].push(cb) //如果存在这个事件,就将函数添加进对应的数组中
}
const $emit = function(eventName,params){
    //判断当前事件名称是否存在
    if(eventList[eventName]){ //如果事件存在
         eventList[eventName].map((cb)=>{  //遍历这个事件中所有的函数,然后给对应的函数传参
             cb(params)
         })
    }else{
         return //不存在就不需要触发事件
    }
}
const $off = function(eventName,params){
    if(eventList[eventName]){
         if(params){ //如果存在参数,就解绑含这个参数的函数
             eventList[eventName]=eventList[eventName].filter((cb)=>{
                 return params !=cb //返回参数不等于cb的函数
             })
         }else{
             eventList[eventName] = [] //如果不存在参数 就直接解绑这个事件
         }
    }
}
function fn1(val){
    console.log("事件一",val)
}
function fn2(val){
    console.log("事件二",val)
}
$on("handle",fn1)
$on("handle",fn2)
$off("handle",fn2)
$emit("handle",123)
 
 
 
 
五、非父子组件传值
 
one.js
 
import React,{Component} from "react"
import observe from './observe'  //引入封装的方法
class one extends Component{
    
    constructor(){
         super();
         this.state={
             message:"我是one组件"
         }
    }
render(){
    console.log(this.props)
    
    return(
         <div  class='one'>
         <h1>one组件</h1>
             <button  onClick={this.handleClick.bind(this)}>发送给two组件</button>  //在one组件中绑定一个事件
         </div>
         
    )
}
handleClick(){
    observe.$emit("handle",this.state.message) /*通过$emit将事件中绑定的值传递出去*/
}
}
export default one
 
two.js
 
import React,{Component} from "react"
import observe from './observe'
class two extends Component{
    constructor(){
         super();
         this.state={  //先定义一个空的属性用于接收  one.js组件传过来的值
             val:""
         }
         observe.$on("handle",(params)=>{  //调用事件绑定的方法 获取handle中传过来的参数params
             this.setState({
                 val:params  //给val赋值
             })
         })
    }
    render(){
         let {val} = this.state
         return(
             <div class='two'>
                      <h1>two组件</h1>
                 <h2>接受到one组件的值为:{val}</h2>   
             </div>
             
         )
    }
 
 
六、数据类型的校验
     
        1、安装
            cnpm install prop-types --save-dev
 
        2、引入(在组件中引入)
            import PropTypes from "prop-types";
 
        3、校验
            组件名称.propTypes = {
                key:PropTypes.类型
            }
 
 
         optionalArray: PropTypes.array,
        optionalBool: PropTypes.bool,
        optionalFunc: PropTypes.func,
        optionalNumber: PropTypes.number,
        optionalObject: PropTypes.object,
        optionalString: PropTypes.string,
        optionalSymbol: PropTypes.symbol,
        optionalNode: PropTypes.node,
 
        // 一个 React 元素
        optionalElement: PropTypes.element,
 
        // 你也可以声明属性为某个类的实例,这里使用 JS 的
        // instanceof 操作符实现。
        optionalMessage: PropTypes.instanceOf(Message),
 
        // 你也可以限制你的属性值是某个特定值之一
        optionalEnum: PropTypes.oneOf(['News', 'Photos']),
 
        // 限制它为列举类型之一的对象
        optionalUnion: PropTypes.oneOfType([
            PropTypes.string,
            PropTypes.number,
            PropTypes.instanceOf(Message)
        ]),
 
        // 一个指定元素类型的数组
        optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
 
        // 一个指定类型的对象
        optionalObjectOf: PropTypes.objectOf(PropTypes.number),
App.js
 
import React,{Component} from "react"
import One from './one'  //1) 引入子组件
class App extends Component{
    constructor(){
         super();
         this.state={
             apple:'zsr'
         }
    }
    render(){
         let {apple} = this.state
         return(
             <div>
             <One name={apple}></One>
             </div>
         )
    }
  
}
export default App
 
one.js
 
import React,{Component} from "react"
import observe from './observe'  //引入封装的方法
import PropTypes from 'prop-types'
class one extends Component{
    
    constructor(){
         super();
         this.state={
           
         }
    }
render(){
    console.log(this.props)
    let {name} = this.props //接收父组件传过来的值
    return(
         <div  class='one'>
             <h3>{name}</h3>
         </div>
    )
}
}
one.propTypes={  //这里的propTypes是组件身上的属性
    name:PropTypes.number  //这里的PropTypes是引入的   数据类型小写
}
export default one
 
七、获取组件标签内部包裹的元素
 
this.props.children
App.js
 
render(){
         let {apple} = this.state
         return(
             <div>
             <One name={apple}>
                 <p>111</p>
                 <p>222</p>
             </One>
             </div>
         )
    }
 
one.js
 
return(
         <div  class='one'>
         <h1>one组件</h1>
             {this.props.children}
         </div>
         
    )
 
八、强制更新 (外部属性的使用)
因为数据没有放在this.state中,所以不会自动更新,在this.state中的数据只要数据改变就会自动更新
this.forceUpdate()
one.js
import React,{Component} from "react"
class one extends Component{
    
    constructor(){
         super();
         this.state={
         }
         this.age = 18
    }
render(){
   
    return(
         <div  class='one'>
         <button  onClick={this.handleAge.bind(this)}>改变年龄</button>
         <p>我的年龄是{this.age}</p>
         </div>
    )
}
    handleAge(){
         this.age = 20
         this.forceUpdate()  //强制更新,相当于手动执行了一次render
    }
export default one
 
 
九、render函数什么时候会执行?
        当this.state、this.porps发生改变的时候render函数就会执行
原文地址:https://www.cnblogs.com/zsrTaki/p/11510741.html