React基础知识结尾(组件通信,PureComponent,innerHTML,Hooks)

一. 组件通信:

父组件向子组件

父级向子级通信 把数据添加子组件的属性中,然后子组件中从props属性中,获取父级传递过来的数

例如:
父组件App.js:

import React,{ Component } from "react";
import Sub from "./SubComponent.js";
import "./App.css";

export default class App extends Component{

    render(){
        return(
            <div>
            	{/*传递属性*/}
                <Sub title = "今年过节不收礼" />
            </div>
        )
    }
}

子组件:

import React from "react";

const Sub = (props) => {
    return(
        <h1>
        	{/*子组件通过props接收*/}
            { props.title }
        </h1>
    )
}

export default Sub;

子组件传递给父组件:

在父级中定义相关的数据操作方法(或其他回调), 把该方法传递给子级,在子级中调用该 方法父级传递消息

例如:
父组件

import React,{ Component } from "react";
import Sub from "./SubComponent.js";
import "./App.css";

export default class App extends Component{
    callback(msg){
        console.log(msg);
    }
    render(){
        return(
            <div>
                <Sub callback = { this.callback.bind(this) } />
            </div>
        )
    }
}

子组件:

import React from "react";

const Sub = (props) => {
    const cb = (msg) => {
        return () => {
            props.callback(msg)
        }
    }
    return(
        <div>
            <button onClick = { cb("我们通信把") }>点击我</button>
        </div>
    )
}

export default Sub;

context

Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。
React.createContext() 创建一个 Context 对象

const MyContext = React.createContext(defaultValue);

Provider: 接收一个 value 属性,传递给消费组件

<MyContext.Provider value={/* 某个值 */}>

Consumer: 此组件可以让你在函数式组件中可以订阅 context,

这种方法需要一个函数作为子元素(function as a child)。
这个函数接收当前的 context 值,并返回一个 React 节点。
传递给函数的 value 值等价于组件树上方离这个 context 最近的 Provider 提供的 value 值。
如果没有对应的 Provider,value 参数等同于传递给 createContext() 的 defaultValue。
<MyContext.Consumer>
  {value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>

contextType: 挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。此属性能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中
注意:此方法只适用于类式组件

class MyClass extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* 在组件挂载完成后,使用 MyContext 组件的值来执行一些有副作用的操作 */
  }
  componentDidUpdate() {
    let value = this.context;  
  }
  componentWillUnmount() {
    let value = this.context;
  }
  render() {
    let value = this.context;
    /* 基于 MyContext 组件的值进行渲染 */
  }
}
MyClass.contextType = MyContext;

react项目封装context方法:
1.新建 context.js 文件:

import {createContext} from 'react'
let context = createContext()
let {Provider,Consumer} = context
// export default context
export  {Provider,Consumer}

2.父组件内引入Provider:

import './App.css';
import React from 'react'
import ReactDOM from 'react-dom';
import { Provider} from "./context";
import Children from "./children"
function App() {
  const [chuan] = React.useState('传值') //定义传的值
  return (
    <div className="App">
      <Provider value={chuan}> //传递
        <Children></Children> 
      </Provider>
    </div>
  );
}
export default App;

3.子组件内引入Consumer

import React from "react"
import {Consumer} from './context'
function Children (){
    return <div>
        <h3>我是子元素</h3>      
        <Consumer>
	    {
	      value => ( // value就是context中的value数据
	       value
	      )
	    }
	  </Consumer>
    </div>   
}
export default Children

二. React.PureComponent 与 React.Component

通常情况下,我们会使用ES6的class关键字来创建React组件

class MyComponent extends React.Component {
    // some codes here ...
}

但是,你也可以创建一个继承React.PureComponent的React组件,就像这样

class MyComponent extends React.PureComponent {
    // some codes here
}

1.区别:
React.PureComponentReact.Component 几乎完全相同,但 React.PureComponent 通过props和state的浅对比来实现 shouldComponentUpate()

2.PureComponent缺点:
可能会因深层的数据不一致而产生错误的否定判断,从而shouldComponentUpdate结果返回false,界面得不到更新。

3.PureComponent优势:
不需要开发者自己实现shouldComponentUpdate,就可以进行简单的判断来提升性能。

三. children

向组件内部动态传入带内容的结构(标签)
组件标签对之间的内容会被当做一个特殊的属性 props.children 传入组件内

如下例,一个 span 标签在 Parent 中作为Child的子节点传入,可在 Child 中通过 this.props.children 取到:

父组件:

class Parent extends React.Component {
  render() {
    return (
    <Child>
        <span>{'child node'}</span>
      </Child>
    );
  }

子组件:


class Child extends React.Component {
  render() {
    return (
      <div>
        {this.props.children}
      </div>
    );
  }
}

四.dangerouslySetInnerHTML

dangerouslySetInnerHTML 是 React 为浏览器 DOM 提供 innerHTML 的替换方案

<div dangerouslySetInnerHTML = {{ __html: checkMessages.details }} />

原理:

1.dangerouslySetInnerHTMl 是React标签的一个属性,类似于angularng-bind
2.有2个{{}},第一{}代表jsx语法开始,第二个是代表dangerouslySetInnerHTML接收的是一个对象键值对;
3.既可以插入DOM,又可以插入字符串;
4.不合时宜的使用 innerHTML 可能会导致 cross-site scripting (XSS) 攻击。 净化用户的输入来显示的时候,经常会出现错误,不合适的净化也是导致网页攻击的原因之一.dangerouslySetInnerHTML 这个 prop 的命名是故意这么设计的,以此来警告,它的 prop 值( 一个对象而不是字符串 )应该被用来表明净化后的数据。

五. Hooks

1.React Hook/Hooks是什么:

(1). Hook是React 16.8.0版本增加的新特性/新语法
(2). 可以让你在函数组件中使用 state 以及其他的 React 特性

2.三个常用的Hook:
(1). State Hook: React.useState()

①. State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作
②.语法: const [xxx, setXxx] = React.useState(initValue)  
③.useState()说明:
    参数: 第一次初始化指定的值在内部作缓存
    返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数
④.setXxx()2种写法:
    setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
    setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值

示例:

function App() {
  const [count,setCount] = React.useState(0)
  React.useEffect(()=>{
   let timer = setInterval(()=>{
    setCount(count=>count+1)
   },1000)
   return ()=>{
    clearInterval(timer)
  }
 },[])
 function start(){
   setCount(count+1)
 }
 return (
    <div className="App">
      <h1>计时器开启:{count}</h1>
      <button onClick={start}>开始计时</button>  
    </div>
 );
}

(2). Effect Hook: React.useEffect()

①. Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
②. React中的副作用操作:
    发ajax请求数据获取
    设置订阅 / 启动定时器
    手动更改真实DOM
③. 可以把 useEffect Hook 看做如下三个函数的组合
    componentDidMount()
    componentDidUpdate()
	componentWillUnmount() 

语法和说明:

useEffect(() => { 
    // 在此可以执行任何带副作用操作,如定时器
     return () => { // return是在组件卸载前执行
         // 在此做一些收尾工作, 比如清除定时器/取消订阅等
      }
}, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行  

示例:
(一).

function App() {
  const [count,setCount] = React.useState(0)
  React.useEffect(()=>{
  	//组件挂载之后执行操作改变count值
   	let timer = setInterval(()=>{
    	setCount(count=>count+1)
   	},1000)
  },[])
  return (
    <div className="App">
      <h1>计时器开启:{count}</h1>
      <button onClick={start}>开始计时</button>
    </div>
  );
}

(二).

function App() {
  	const [count,setCount] = React.useState(0)
  	React.useEffect(()=>{
    	console.log(222)
   		let timer = setInterval(()=>{
     		console.log(111)
    		setCount(count=>count+1)
   		},1000)
   		//return在卸载组件之前清除定时器.
	   	return ()=>{
    		clearInterval(timer)
  		}
 	},[])
  	function delet(){ 
  		ReactDOM.unmountComponentAtNode(document.getElementById('root'))
  	}
 	 return (
    	<div className="App">
      		<h1>计时器开启:{count}</h1>
      		<button onClick={start}>开始计时</button>
      		<button onClick={delet}>卸载组件</button>
    	</div>
  	);
}

(3). Ref Hook: React.useRef()

①. Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
②. 语法: const refContainer = useRef()
③. 作用:保存标签对象,功能与React.createRef()一样

示例:

function App() {
  const refContainer = React.useRef()
  function get(){
    alert(refContainer.current.value)
  }
  return (
    <div className="App">
      <input type="text" ref={refContainer}></input>
      <button onClick={get}>拿值</button>
    </div>
  );
}

总结:

在实际应用中,按照实际要解决的需求选择解决办法.不同的传值方式适用于不同的情况.不同的需求所用的最佳方法也不同.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值