React类组件的属性和函数组件里的hooks

PureComponent

PureComponent 提供了一个具有浅比较的 shouldComponentUpdate 方法,其他和 Component 完全一致;

import React,{PureComponent,Component} from 'react'

class App extends PureComponent{
  state={
    name:"尖叫",
    list:["运动饮料-01",["运动饮料-02"],["运动饮料-03"]]
  }
  render(){
    let {name,list}=this.state
    return (
      <div>
        <h1>{name}</h1>
        <ul>
            {
              list.map((item,index)=>{
                return <li key={index}>{item}</li>
              })
            }
        </ul>
        <button onClick={()=>{
          this.setState({name:'红牛'})
        }
          
        }>升级</button>
        <button onClick={()=>{
          list.push('新口味')
          this.setState({list:[...list, ]
          })
          // this.setState({list})   
        }}>扩大</button>
      </div>
    )
  }
}

export default App;

注意:加上PureComponent之后,他只能浅显进行比较,如果数据是对象直接赋值没有结果,如果用结构赋值,可以触发,如果是字符串,或数值可以直接输出

// this.setState({list}) 没有值

// this.setState({list:[…list, ] 可以输出值
})

PureComponent和Component的区别:

​ PureComponent每次做修改,只有发生变化后才会修改;

​ Component:每次做修改,无论和原数组是否一样都会更新

ref

获取react的DOM的节点

旧版ref

通过ref绑定一个字符串;

通过this.refs接收;

案例:利用ref做一个滚动效果

​ 1.首先: 安装better-scroll插件 npm install better-scroll

​ 2.接着引入better-scroll

​ 3.使用better-scroll 需要实例化(dom节点)

​ dom节点 通过ref设置,this.refs获取

import React,{PureComponent} from 'react';
import BScroll from 'better-scroll'
// new BScroll()
 let list=[...(".".repeat(100))];
// console.log(list)
class App extends PureComponent{
 componentDidMount(){
  new BScroll(this.refs.box)
  new BScroll(this.refs.list)
 }
  render(){
    return (
      <div
        style={{
          height:"300px",
          border:"1px solid #000",
          overflow:"hidden"
        }}
        ref="box"
      >
        <ul
        style={
          {
            margin:0,
            padding:0,
            listStyle:"none"

          }
        }
        ref='list'
        >
          {
            list.map((item,index)=>{
              return <li key={index}>这是第{index}</li>
            })
          }
        </ul>
      </div>
    )
  }
}

export default App;

注意:控制台会出现警告,想要去掉警告,去掉index.js里面的 <React.StrictMode>标签,就没有警告了

新版ref

​ 通过createRef创建一个节点,在通过ref获取

import React,{createRef, PureComponent} from 'react';
import BScroll from 'better-scroll'
// new BScroll()
 let list=[...(".".repeat(100))];

class App extends PureComponent{
  box=createRef();
  list=createRef();
//挂载完成
 componentDidMount(){
   console.log(this)
  new BScroll(this.box.current);
  new BScroll(this.list.current);
 }
  render(){
    
    return (
      <div
        style={{
          height:"300px",
          border:"1px solid #000",
          overflow:"hidden"
        }}
        ref={this.box}
      >
        <ul
        style={
          {
            margin:0,
            padding:0,
            listStyle:"none"

          }
        }
        ref={this.list}
        >
          {
            list.map((item,index)=>{
              return <li key={index}>这是第{index}</li>
            })
          }
        </ul>
      </div>
    )
  }
}

export default App;

注意:新版的ref获取的Dom节点不在refs里面,如果想获取多个DOM节点就要多创建几个节点

注意:ref是在组件挂载完成或者更新后执行;

children

组件标签里的内容可以通过props.children传入组件;

import React,{ PureComponent} from 'react';
class Child extends PureComponent{
  render(){
    console.log(this)
    let {children}=this.props;
    return (
      <div>{children}</div>
    )
  }
}
class App extends PureComponent{
 
  render(){
    
    return (
      <div>
        <Child>
          {/* <h1>今天天气真不错</h1>
          <p>明天天气也这样</p> */}
          {
            ['哈哈哈','呵呵呵']
          }
        </Child>
      </div>
    )
  }
}

export default App;

dangerouslySetInnerHTML

直接设置标签的 innerHTML,类似于vue中的v-html,可以解析标签,将内容渲染在浏览器中;

import React,{ PureComponent} from 'react';
let message=`
<h1>小天快乐</h1>
<p>真热</p>
`
class App extends PureComponent{

  render(){
   
    return ( 
      <div dangerouslySetInnerHTML={{
        __html:message
      }}>

      </div>
    )
  }
}

export default App;

注意:dangerouslySetInnerHTML返回的是以一个对象,用__html接收,后面是要显示的内容,接收的数据是后端传过来的

key

在 React ,组件每次更新时,会生成一个 虚拟DOM,和原有的虚拟DOM进行对比。
如果是批量生成的一组元素,那React就会根据 key 值去做对比

key是唯一的

列表循环也可以用index

注意:最好用id,因为index无论改变没都会更新,而且他不稳定,因为索引会发生变化,而id是唯一的

import React,{ PureComponent} from 'react';

class App extends PureComponent{

  state={
    data:[
      {
        id:0,
        content:"第1条数据"
      },
      {
        id:1,
        content:"第2条数据"
      },
      {
        id:2,
        content:"第3条数据"
      },
      {
        id:3,
        content:"第4条数据"
      },
    ]
}
  render(){
   let{data}=this.state;
    return ( 
      <div> 
        {
          data.map((item,index)=>{
             return <p key={item.id}>
              {item.content}
              <a onClick={()=>{
                data.filter(itemData=>itemData!==item)
                this.setState({
                  data:[...data]
                })
              }}>删除</a>
            </p>

          }) 
        }
      </div>
    )
  }
}

export default App;



函数式组件

主要是用来渲染内容,函数名字就是组件名

import React from 'react';
function Child(props){
  return <h1>{props.info}</h1>
}
function App(){
  console.log(this)                                                   
  return <Child  info='呵呵'/>
}

export default App;

函数组件注意事项
1.组件的第0个参数是props----接收父级传过来的信息

2.组件中的 return(必须写)----定义该组件要渲染的内容

3.没有生命周期,没有this,没有state

4.在16.7之前, 函数组件一直当做纯渲染组件来使用

hook

作用

  • 简化组件逻辑
  • 复用状态逻辑
  • 无需使用类组件编写

常用hook

useState

​ 函数组件里定义状态值

​ 先引用useState,接着定义

​ let [状态值,修改状态的方法名]=userState(状态的初始值)

​ 修改状态值方法名是自己定义的

App.js

import React,{useState} from 'react';
function App () {
    //定义  	let [状态值,修改状态的方法名]=userState(状态的初始值)
    const [ count, setCount ] = useState(0)
    return (
      <div>
        点击次数: { count } 
        <button onClick={() => { setCount(count + 1)}}>点我</button>
      </div>
      )
  }

注意:如果传的是对象不能这样用

App.js

import React,{useState} from 'react';
import Child from './Child';
// let [状态值,修改状态的方法]=userState(状态的初始值)

function App(){ 
 
  let [data,setName]=useState({
    name:"毫克",
    age:28
  })
  return<div>
      <Child  data={data}/>
      <button onClick={()=>{
        setName({
          name:"疯狂节课",
          age:data.age
        })
      }}>变身</button>
  </div>
}

export default App;



Child.js

import React from 'react';
function Child(props){
    console.log(props);
    let {data}=props;
    return <div>
            <h1>name:{data.name}</h1>
            <h1>age:{data.age}</h1>
        </div>
}
export default Child

useEffect

他是一个类组件

他在 componentDidMount、componentDidUpdate 和 componentWillUnmount

中使用(挂载,更新,卸载)

他有两个参数第一个蚕食是回调函数,第二个参数是个数组,里面放检测的参数;

useEffect 的第二个参数,有三种情况

1.什么都不传,组件每次 render 之后 useEffect 都会调用,相当于 componentDidMount 和 componentDidUpdate
2.传入一个空数组 [], 只会调用一次,相当于 componentDidMount 和 componentWillUnmount
3.传入一个数组,其中包括变量,只有这些变量变动时,useEffect 才会执行

App.js

import React,{useState} from 'react';
import Child from './Child';
// let [状态值,修改状态的方法]=userState(状态的初始值)

function App(){ 
 
  let [data,setName]=useState({
    name:"毫克",
    age:28
  })
  let [show,setShow]=useState(true)
  return<div>
     {show? <Child  data={data}/>:""}
      <button onClick={()=>{
        setName({
          name:"疯狂节课",
          age:data.age
        })
      }}>变身</button>
      <button onClick={()=>{
        setShow(false)
      }}>卸载</button>
  </div>
}

export default App;



Child.js

import React,{useState,useEffect} from 'react';
function Child(props){
    console.log(props);
    let {data}=props;
    let [age,setAge]=useState(8)
    useEffect(()=>{
        console.log('挂载了');
        // return ()=> {
        //     // console.log("卸载时触发")
        // }
    },[])
    useEffect(()=>{
        return ()=>{
            console.log('卸载了')
        }
    })
    //检测参数值发生变化才触发此方法 ,如果不写参数,怎样都不会触发这些方法
    return <div>
            <h1>name:{data.name}</h1>
            <h1>age:{age}</h1>
            <button onClick={()=>[
                setAge(++age)
            ]}>长一岁</button>
        </div>
}
export default Child

注意1:挂载和更新在useEffect里面写,而卸载在return里面写

注意2:检测参数值发生变化才触发此方法 ,如果不写参数,怎样都不会触发这些方法

useRef

​ 作用:在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的 this.xxx;

使用:

先引入useRef,然后创建一个空的useRef(),在通过ref来接收创建的那个空的useRef

App.js

import React,{useState} from 'react';
import Child from './Child';
// let [状态值,修改状态的方法]=userState(状态的初始值)

function App(){ 
 
  let [data,setName]=useState({
    name:"毫克",
    age:28
  })
  let [show,setShow]=useState(true)
  return<div>
     {show? <Child  data={data}/>:""}
      <button onClick={()=>{
        setName({
          name:"疯狂节课",
          age:data.age
        })
      }}>变身</button>
      <button onClick={()=>{
        setShow(false)
      }}>卸载</button>
  </div>
}

export default App;



Child.js

import React,{useState,useEffect,useRef} from 'react';

function Child(props){

    let {data}=props;
    let [age,setAge]=useState(8);
    let ageP=useRef();
    let [txt,setTxt]=useState('文字')

    useEffect(()=>{
        console.log(ageP.current);
        
    },[])
    //检测参数值发生变化才触发此方法 ,如果不写参数,怎样都不会触发这些方法
    return <div>
            <h1>name:{data.name}</h1>
            <h1 ref={ageP}>age:{age}</h1>
            <button onClick={()=>[
                setAge(++age)
            ]}>长一岁</button>

            <p>{txt}</p>
            <input  type='text' value={txt} onChange={({target})=>{
                setTxt(target.value)
            }}/>
          
        </div>
}
export default Child

Hook 使用规则

  • 只在最顶层使用 Hook
  • 只在 React 函数中调用 Hook
    • React 函数组件中
    • React Hook 中 - 我自己定义 hook 时,可以调用别的hook
  • 所有的 hook 必须 以 use

自定义组件

首先引入react,定义函数组件 开头必须是use,retuen里面写内容,在哪用就把组件引在哪;

利用hooks里的ref和useEffect写了一个滚动案例

hooks.js

import React,{useState} from 'react';
function useSize(){
    return {
        w:window.innerWidth,
        h:window.innerHeight
    }
}
//获取滚动条
function useScrollY(){
    let [scrollY,setY]=useState(window.scrollY)
    return [
        scrollY,
        (newScrollY)=>{
            window.scrollTo(0,newScrollY);
            setY(newScrollY)
        }
    ]
}
export  {useSize,useScrollY};

app.js

import React ,{useEffect}from 'react';
import {useSize,useScrollY} from './hooks'
// let [状态值,修改状态的方法]=userState(状态的初始值)

function App(){ 
let [scrollY,setY]=useScrollY();

useEffect(()=>{
  window.onscroll=()=>{
    setY(window.scrollY)
  }
  return()=>   {
    window.oncroll=null
  }
},[])

  return<div>
        <ul>
          {
            [...(".".repeat(100))].map((item,index)=>{
              return <li key={index}>这是第{index}个li</li>
            })
          }
        </ul>
        <a onClick={()=>{
          setY(100)
        }}
        style={{
          position:"fixed",
          top:"50px",
          left:"200px"
        }}
        >{scrollY}</a>
  </div>
}

export default App;

 

总结
学习了react的类组件里的属性和函数组件hooks,受益匪浅,我这是个人了解,详细内容可以查看官网;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值