React操作DOM之forwardRef问题

这篇文章主要介绍了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 

Profile

})

定义App组件

export default class App extends PureComponent { constructor(props){ super(props); this.profileRef = createRef() } render() { return ( 
) } printRef(){ console.log(this.profileRef.current) } }

当我们点击按钮时候

用这个的好处是什么?因为我们之前操作dom,函数式组件是不行的,因为它没有实例,用这个高阶组件就能完美解决这个问题

React forwardRef使用方法

作用与注意点

  • 传递ref,把自身的ref绑定到其他地方(e.g. 你把文件交给总裁秘书,总裁秘书把文件交给总裁)
  • ref 和 key 有点特殊,不会作为props参数向下传递,this.props拿不到ref对象
  • 函数组件是没有实例的,可以用useImperativeHandle实现部分功能
  • 高阶组件需做特殊处理

父 -> 子 -> 子(Dom)

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 ( 
); }; export default Home;
import React, { forwardRef } from 'react'; /** * forwardRef包裹后,ref会作为第二个参数,接收传进来的ref属性 * e.g. *  * * @param props - {count, user} * @param ref   - connectRef * */ const Content = (props, ref) => { return ( 
{/* 把ref绑定给传进来的ref ≈ ref={connectRef} */}
) }; export default forwardRef(Content);

父 -> 子 -> 子(class)

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 ( 
); }; export default Home;
import React, { forwardRef } from 'react'; import Header from './header'; import Footer from './footer'; /** * forwardRef包裹后,ref会作为第二个参数,接收传进来的ref属性 * e.g. *  * * @param props - {count, user} * @param ref   - connectRef * */ const Content = (props, ref) => { return ( 
{/* 把ref绑定给传进来的ref ≈ ref={connectRef} */}
{/* class组件 */} {/*
函数组件是没有实例的,所以connectRef.current: null */}
) }; export default forwardRef(Content)
import React from 'react'; export default class Header extends React.Component { state = { count: 0 }; render() { return ( 
{this.state.count}
) } };

高阶组件中的特殊情况

  • 高阶组件本质是函数,参数为组件,返回值是新组件(增强过的组件)
  • 高阶组件会把所有接收到的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会绑定到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 ( 
); }; // 被包装组件 const Content = (props) => { return (
); }; // forwardRef的第二个入参可以接收ref,在Hoc外层对ref做处理 export default React.forwardRef((props, ref) => { const Wrapper = withRouter(Content); // Hoc // forwardRef包裹的是Wrapper // 需要在Wrapper中把ref向下传递给真实组件 // Wrapper中增加一个props属性,把ref对象作为props传给子组件 return ; }); 第二种方法 ========== 0. 使用时就用一个props来保存ref 1. 使用时传 xxx={ref} // 和第一种方法的不同点 2. 真实组件中绑定 ref={props.xxx} const Home = (props) => { const connectRef = useRef(null); return (
); }; // 定义高阶组件 export const Hoc = (WrappedComponent) => { class Wrapper extends React.Component { render() { return } } } // 被包装的组件 const Content = (props) => { return (
); }; // 包装过程 export default Hoc(Content); * */

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持0133技术站。

以上就是React操作DOM之forwardRef问题的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » JavaScript 教程