目录
一. 组件通信:
父组件向子组件
父级向子级通信 把数据添加子组件的属性中,然后子组件中从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.PureComponent
与 React.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标签的一个属性,类似于angular
的ng-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>
);
}
总结:
在实际应用中,按照实际要解决的需求选择解决办法.不同的传值方式适用于不同的情况.不同的需求所用的最佳方法也不同.