在父組件中的子組件標籤上將父組件的變量,方法經過屬性的形式讓子組件能夠訪問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 的知識都在這了 ---劉小夕
基礎決定將來,一步一個腳印