在父组件中的子组件标签上将父组件的变量,方法经过属性的形式让子组件能够访问vue
在子组件中经过this.props.属性名访问对应变量或方法react
方法应定义为箭头函数,避免不一样组件调用方法致使this指向混乱api
// 以todos功能为例
// 父组件
import React, { Component } from 'react'
import AddItem from './AddItem'
import Todolist from './Todolist'
class Content extends Component {
constructor(props) {
super(props)
this.state = {//父组件中的变量
value: '',
arrList: []
}
}
// 定义方法
// 用setState函数修改state中变量,避免直接对state中的变量进行操做
// 为了子组件调用父组件方法时不改变this指向,应将方法定义为箭头函数
handleChange = (value) => {
this.setState({//异步操做,但若在定时器中使用就是同步操做
value
})
}
handleClick = () => {
this.setState({
arrList: [...this.state.arrList, this.state.value],
value: ''
})
}
deleteClick = (id) => {
let temparr = this.state.arrList
temparr.splice(id,1)
this.setState({
arrList: temparr
})
}
render() {
return (
<div>
<AddItem
value = {this.state.value}
handleChange = {this.handleChange}
handleClick = {this.handleClick}
/>
<Todolist
arrList = {this.state.arrList}
deleteClick = {this.deleteClick}
/>
</div>
)
}
}
export default Content
// 子组件 AddItem
import React, { Component, Fragment } from 'react'
class AddItem extends Component {
getInpValue = (e) => {
this.props.handleChange(e.target.value)
}
render() {
return (
<Fragment>
<input type = "text" value = {this.props.value} onChange = {this.getInpValue} />
<button onClick = {this.props.handleClick}>添加任务</button>
</Fragment>
)
}
}
export default AddItem
// 子组件 Todolist
import React, { Component } from 'react'
class Todolist extends Component {
// 使用父组件方法须要传参,应在子组件方法中调用,经过bind绑定参数给子组件方法传参
// 虽然父组件定义方法时箭头函数时,子组件给该方法bind绑定参数也能够,但以上方法更可靠
deleteItem (i) {
this.props.deleteClick(i)
}
render() {
return (
<ul>
{
this.props.arrList.map((item,index) => {
return (
<li key = {index}>
{item}
<span onClick = {this.props.deleteClick.bind(this,index)}>X</span>
</li>
)
})
}
</ul>
)
}
}
export default Todolist
复制代码
context的功能数组
使用方法dom
React.createContext() 咱们须要用到createContext建立上下文异步
返回的是一个对象 对象内有2个组件ide
示例:按钮实现加/减函数
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import CountProvider from './context'
// 组件标签内就算有内容也不会自动去解析,需在组件内部经过this.props.children获取使用
ReactDOM.render(
(
<CountProvider> <App /> </CountProvider>
),
document.getElementById('root'));
复制代码
context.jspost
import React, { createContext, Component, Fragment } from 'react'
// Fragment不会生成DOM标签,通常用来作根标签,也能够用<></>代替
const {Consumer, Provider} = createContext()
class CountProvider extends Component {
constructor(props) {
super(props)
this.state = {
num: 10
}
}
addNum = () => {
this.setState({
num: this.state.num + 1
})
}
minusNum = () => {
this.setState({
num: this.state.num - 1
})
}
// 此处this.props.children获取到的是APP组件,故在App组件中使用的组件均可以能够经过Consumer接收
render() {
return (
<Fragment> <Provider value = {{ num: this.state.num, addNum: this.addNum, minusNum: this.minusNum }}> {this.props.children} </Provider> </Fragment>
)
}
}
// export 导出语法有
// export let/const 变量名
// 或export function 函数名 () {}
// 或export {变量名}
// export default 可直接导出 变量,但只能使用一次
export default CountProvider
export {Consumer, Provider}
复制代码
App.js动画
import React, { Component } from 'react'
import CountButton from './components/button'
import Count from './components/count'
class App extends Component {
render () {
return (
<div> <CountButton type='add'>+</CountButton> <Count /> <CountButton type='minus'>-</CountButton> </div>
)
}
}
export default App;
复制代码
/count/index.js
import React, { Component } from "react";
import {Consumer} from '../../context'
class Count extends Component {
render() {
return (
<Consumer> { ({num}) => { return ( <span>{num}</span> ) } } </Consumer>
)
}
}
export default Count
复制代码
/button/index.js
import React, { Component } from 'react'
import { Consumer } from '../../context'
class CountButton extends Component {
render() {
return (
<Consumer> { ({addNum, minusNum})=>{ const setFunc = this.props.type === 'add' ? addNum : minusNum return ( <button onClick={setFunc}> {this.props.children} </button> ) } } </Consumer>
)
}
}
export default CountButton
复制代码
适用场景
避免使用
使用限制
ref
属性,由于函数组件没有实例在元素或组件标签上设置ref属性
<button ref = 'btnRef' onClick = {this.handleClick}>dianwo</button>
<Son ref = 'sonRef' />
复制代码
经过this.refs获得全部设置了ref属性的元素或组件实例
过期的API,官方建议使用 回调函数 或者 createRef API的方式来替换
函数组件内部不支持使用
在React16.3 版本中引入的
使用 React.createRef()
建立 Refs
,并经过 ref
属性附加至 React
元素上。一般在构造函数中,将 Refs
分配给实例属性,以便在整个组件中引用。
当 ref
被传递给 render
中的元素时,对该节点的引用能够在 ref
的 current
属性中访问
ref
的值根据节点的类型而有所不一样
当 ref
属性用于 HTML
元素时,构造函数中使用 React.createRef()
建立的 ref
接收底层 DOM
元素做为其 current
属性
当 ref
属性用于自定义的 class 组件时, ref
对象接收组件的挂载实例做为其 current
属性
不能在函数组件上使用 ref
属性,由于函数组件没有实例
this.sonRef = createRef()
<Son ref = {this.sonRef} />
this.sonRef.current
复制代码
useRef
是 React16.8 中引入的,只能在函数组件中使用
使用 React.useRef()
建立 Refs
,并经过 ref
属性附加至 React
元素上
返回的 ref 对象在组件的整个生命周期内保持不变
当 ref
被传递给 React 元素时,对该节点的引用能够在 ref
的 current
属性中访问
import React from 'react';
export default function MyInput(props) {
const inputRef = React.useRef(null);
React.useEffect(() => {
inputRef.current.focus();
});
return (
<input type="text" ref={inputRef} /> ) } 复制代码
在react较早的版本中,咱们推荐使用 回调形式的refs
这种方式能够帮助咱们更精细的控制什么时候 Refs 被设置和解除
将回调函数传递给 React元素
的 ref
属性。这个函数接受 React 组件实例 或 HTML DOM 元素做为参数,将其挂载到实例属性上
React 会在组件挂载时,调用 ref
回调函数并传入 DOM元素(或React实例),当卸载时调用它并传入 null
。在 componentDidMount
或 componentDidUpdate
触发前,React 会保证 Refs 必定是最新的
import React from 'react';
export default class MyInput extends React.Component {
constructor(props) {
super(props);
this.inputRef = null;
this.setTextInputRef = (ele) => {
this.inputRef = ele;
}
}
componentDidMount() {
this.inputRef && this.inputRef.focus();
}
render() {
return (
<input type="text" ref={this.setTextInputRef}/> ) } } 复制代码
参考: 你想知道的关于 Refs 的知识都在这了 ---刘小夕
基础决定将来,一步一个脚印