我不确定如何不那么模糊地表述这个问题,但它是关于反应中的按值传递和按引用传递的情况。和钩子。
我正在使用 gsap 对div 滑入和滑出进行动画处理是这方面的上下文,但我猜 ref 的用途并不重要。
所以,这工作正常,即使按照我的理解,这是一种更典型的类组件传递 ref 的方式:
const RootNavigation = () => {
var navbar = useRef();
const myTween = new TimelineLite({ paused: true });
const animate = () => {
myTween.to(navbar, 0.07, { x: "100" }).play();
};
return(
<div className="nav-main" ref={div => (navbar = div)}> // <<<<<<<<<< pass as a callback
...
</div>
)}
这引发了"类型错误:无法添加属性_gsap,对象不可扩展"错误,即使这是 React Hooks 指南让我这样做的方式:
const RootNavigation = () => {
var navbar = useRef();
const myTween = new TimelineLite({ paused: true });
const animate = () => {
myTween.to(navbar, 0.07, { x: "100" }).play();
};
return(
<div className="nav-main" ref={navbar}> //<<<<<<<<<<<<< not passing a callback
...
</div>
)}
有人可以向我解释这里发生了什么,甚至扔一个男孩一个链接,指向已经解释过的地方吗?我敢肯定某种丹角色在某处写过它,我只是不确定该谷歌什么。谢谢!
在第一个示例中,您没有使用ref
,而是通过ref
回调重新分配navbar
,因此navbar
是 DOM 元素。
它与
let navbar = null;
return <div ref={node => (navbar = node)} />
在第二个示例中,您将使用ref
对象,该对象是具有保存 DOM 元素的current
属性的对象
const navbar = useRef(null)
return <div ref={navbar} />
导航栏现在是
{ current: the DOM element }
因此,您将对象传递到myTween.to()
而不是 DOM 元素中navbar.current
现在在第二个示例中,gsap
尝试扩展ref
对象本身,而不是 DOM 元素。
为什么我们得到类型错误:无法添加属性_gsap,对象不可扩展'?
如果您查看useRef
的源代码,您将在线看到891
if (__DEV__) {
Object.seal(ref);
}
React 正在密封ref
对象,当我们尝试使用Object.defineProperty()
扩展它时,JavaScript
会抛出错误,这可能是gsap
正在做的事情。
使用ref
的解决方案是将ref.current
传递到tween.to()
const RootNavigation = () => {
const navbar = useRef()
const myTween = new TimelineLite({ paused: true });
const animate = () => {
myTween.to(navbar.current, 0.07, { x: "100" }).play()
}
return (
<div className="nav-main" ref={navbar}>
...
</div>
)
}