您好,登錄后才能下訂單哦!
本篇內容主要講解“React操作DOM之forwardRef問題怎么解決”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“React操作DOM之forwardRef問題怎么解決”吧!
React操作DOM有幾種方式,傳入字符串,傳入一個對象(react推薦的方式),傳入一個函數,今天就講一下使用react封裝過的高階組件forwardRef來操作DOM
首先導入
import React, { PureComponent,createRef,forwardRef } from 'react'
然后const一個函數組件,將它作為App的子組件
const Profile = forwardRef(function (props,ref){ return <h3 ref={ref}>Profile</h3> })
定義App組件
export default class App extends PureComponent { constructor(props){ super(props); this.profileRef = createRef() } render() { return ( <div> <Profile ref={this.profileRef} name={'lsh'}/> <button onClick={e=>this.printRef()}>點擊</button> </div> ) } printRef(){ console.log(this.profileRef.current) } }
當我們點擊按鈕時候
用這個的好處是什么?因為我們之前操作dom,函數式組件是不行的,因為它沒有實例,用這個高階組件就能完美解決這個問題
傳遞ref,把自身的ref綁定到其他地方(e.g. 你把文件交給總裁秘書,總裁秘書把文件交給總裁)
ref 和 key 有點特殊,不會作為props參數向下傳遞,this.props拿不到ref對象
函數組件是沒有實例的,可以用useImperativeHandle實現部分功能
高階組件需做特殊處理
import React, { useRef } from 'react'; import Content from './content'; const Home = () => { // 創建一個Ref對象 const connectRef = useRef(null); const handleFoucus = () => { const _ref = connectRef.current; _ref.focus(); }; return ( <div> <button onClick={() => handleFoucus()}> 使用子組件中DOM元素的方法 </button> <Content ref={connectRef} /> </div> ); }; export default Home;
import React, { forwardRef } from 'react'; /** * forwardRef包裹后,ref會作為第二個參數,接收傳進來的ref屬性 * e.g. * <Content count={count} user={user} ref={connectRef}> * * @param props - {count, user} * @param ref - connectRef * */ const Content = (props, ref) => { return ( <div> {/* 把ref綁定給傳進來的ref ≈ ref={connectRef} */} <input type="password" ref={ref} /> </div> ) }; export default forwardRef(Content);
import React, { useRef } from 'react'; import Content from './content'; const Home = () => { // 創建一個Ref對象 const connectRef = useRef(null); const handleAdd = () => { const _ref = connectRef.current; const { count } = _ref.state; _ref.setState({ count: count + 1 }) }; return ( <div> <button onClick={() => handleAdd()}> 使用子組件中class組件的屬性和方法 </button> <Content ref={connectRef} /> </div> ); }; export default Home;
import React, { forwardRef } from 'react'; import Header from './header'; import Footer from './footer'; /** * forwardRef包裹后,ref會作為第二個參數,接收傳進來的ref屬性 * e.g. * <Content count={count} user={user} ref={connectRef}> * * @param props - {count, user} * @param ref - connectRef * */ const Content = (props, ref) => { return ( <div> {/* 把ref綁定給傳進來的ref ≈ ref={connectRef} */} <Header ref={ref} /> {/* class組件 */} {/* <Footer ref={ref} /> 函數組件是沒有實例的,所以connectRef.current: null */} </div> ) }; export default forwardRef(Content)
import React from 'react'; export default class Header extends React.Component { state = { count: 0 }; render() { return ( <div> {this.state.count} </div> ) } };
高階組件本質是函數,參數為組件,返回值是新組件(增強過的組件)
高階組件會把所有接收到的props,傳遞給被包裝的組件(透傳)
ref 和 key 類似,不是一個prop,所以不會透傳,ref會綁定到外層的高階組件上
高階組件可以嵌套多層,e.g. Hoc1(Hoc2(Hoc3(Content)))
所以為了把ref傳遞給最里面的組件,有兩種方法
在最外層用 forwardRef 對 ref 對象進行處理,ref -> ref -> props.key = ref
不用 ref,用自定義props承載 ref 對象,props.key = ref
/* 處理ref e.g. Hoc1(Hoc2(Content)) <Content ref={myRef} /> 給Content綁定的ref會綁定到Hoc1上,且不會繼續向下傳遞 第一種方法 React.forwardRef =============== 在 Hoc1外面 用React.forwardRef()對ref做處理,用props來傳遞ref 0. 在高階組件外面包裹forwardRef,攔截獲取ref,增加一個props(xxx={ref}),真實組件通過props.xxx獲取 1. 使用時傳 ref={XXXX} // 和第二種方法不同的地方 2. 用forwardRef的第二個參數獲取 ref 3. 增加一個新的props,用來向下轉發ref e.g. forwardedRef={ref} 4. 真實組件中綁定 ref={props.forwardedRef} const Home = (props) => { const connectRef = useRef(null); return ( <div> <Content ref={connectRef} /> </div> ); }; // 被包裝組件 const Content = (props) => { return ( <div> <input type="password" ref={props.forwardedRef} /> </div> ); }; // forwardRef的第二個入參可以接收ref,在Hoc外層對ref做處理 export default React.forwardRef((props, ref) => { const Wrapper = withRouter(Content); // Hoc // forwardRef包裹的是Wrapper // 需要在Wrapper中把ref向下傳遞給真實組件 // Wrapper中增加一個props屬性,把ref對象作為props傳給子組件 return <Wrapper {...props} forwardedRef={ref} />; }); 第二種方法 ========== 0. 使用時就用一個props來保存ref 1. 使用時傳 xxx={ref} // 和第一種方法的不同點 2. 真實組件中綁定 ref={props.xxx} const Home = (props) => { const connectRef = useRef(null); return ( <div> <Content forwardedRef={connectRef} /> </div> ); }; // 定義高階組件 export const Hoc = (WrappedComponent) => { class Wrapper extends React.Component { render() { return <WrappedComponent {...props} /> } } } // 被包裝的組件 const Content = (props) => { return ( <div> <input type="password" ref={props.forwardedRef} /> </div> ); }; // 包裝過程 export default Hoc(Content); * */
到此,相信大家對“React操作DOM之forwardRef問題怎么解決”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。