如何将超过 1 个 ref 传递给 SolidJS 中的子组件?
How to pass more than 1 ref to a child component in SolidJS?
父组件:
function ParentComponent() {
return (
<section>
<ChildComponent ref={sectionRef} ref1={headerRef} />
</section>
);
}
子组件:
function ChildComponent(props) {
return (
<section ref={props.ref}>
<article>
<h2 ref={props.ref1}>Lorem Ipsum</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Maxime mollitia,
molestiae quas vel sint commodi repudiandae consequuntur voluptatum laborum
numquam blanditiis harum quisquam eius sed odit fugiat iusto fuga praesentium optio, eaque rerum!</p>
</article>
</section>
);
}
我的目标是能够从父组件定位子组件中的不同 DOM 元素,以便我可以根据父组件的滚动事件为它们设置动画。
我尝试将引用作为不同的数据结构传递:
<ChildComponent ref={{sectionRef, headerRef}} />
和:
<ChildComponent ref={[sectionRef, headerRef]} />
和:
<ChildComponent section={sectionRef} header={headerRef} />
但不断出现第二个引用未定义的错误。如果我为每个子组件传递一个引用,我只能让它工作。有什么想法吗?
参考链接 material 我查看了:
https://www.solidjs.com/tutorial/bindings_forward_refs
https://www.solidjs.com/docs/latest/api#ref
在组件中设置 Refs 时
有 3 种方法可以在组件中引用 DOM 元素。
- 传递常规变量
function Component() {
let buttonEl;
onMount(() => {
console.log(buttonEl) // logs button element
})
return (
<button ref={buttonEl}>Click</button>
);
}
- 通过信号setter
function Component() {
const [buttonEl, setButtonEl] = createSignal(null);
onMount(() => {
console.log(buttonEl()) // logs button element
})
return <button ref={setButtonEl}>Click</button>;
}
- 通过回调
function Component() {
let buttonEl;
const refCallback = (el) => {
buttonEl = el;
};
onMount(() => {
console.log(buttonEl); // logs button element
});
return <button ref={refCallback}>Click</button>;
}
在子组件中设置 Refs 时
然而,当引用在子组件中设置的 DOM 元素时,情况就不同了。为了演示,我们不会对子组件使用 ref
prop,而是使用 PASSREF
prop.
- 将常规变量传递给
PASSREF
。变量不更新并且是 undefined
.
function Component() {
let buttonEl;
onMount(() => {
console.log(buttonEl); // logs `undefined`
});
return <Child PASSREF={buttonEl} />;
}
function Child(props) {
return <button ref={props.PASSREF}>Click</button>;
}
- 将信号 setter 传递给
PASSREF
,有效。
function Component() {
const [buttonEl, setButtonEl] = createSignal(null)
onMount(() => {
console.log(buttonEl()); // logs button element
});
return <Child PASSREF={setButtonEl} />;
}
function Child(props) {
return <button ref={props.PASSREF}>Click</button>;
}
- 将与
buttonEl
在相同范围内声明的回调传递给 PASSREF
,有效。
function Component() {
let buttonEl;
const refCallback = (el) => {
buttonEl = el;
};
onMount(() => {
console.log(buttonEl); // logs button element
});
return <Child PASSREF={refCallback} />;
}
function Child(props) {
return <button ref={props.PASSREF}>Click</button>;
}
要修复使用常规变量 let buttonEl;
的 #1 解决方案,请使用正确的组件属性 ref
以便将元素设置为变量。
function Component() {
let buttonEl;
onMount(() => {
console.log(buttonEl); // logs button element
});
return <Child ref={buttonEl} />;
}
function Child(props) {
return <button ref={props.ref}>Click</button>;
}
那么为什么这样做有效呢?好吧,因为在编译输出中,使用 ref 的 Child prop 参数实际上被内联回调替换,这样它就位于声明 buttonEl
的相同范围内并且可以更新。
// This is NOT how the Compiled Output actually looks,
// but ref argument is replaced by an inline callback
function Component() {
let buttonEl;
onMount(() => {
console.log(buttonEl); // logs button element
});
return <Child ref={(el) => buttonEl = el} />;
}
function Child(props) {
return <button ref={props.ref}>Click</button>;
}
是不是很眼熟?这几乎完全符合 #3 解决方案的结构,您可以在其中传递回调函数来更新 buttonEl
.
解决方案
老实说,这取决于您的用例,要么使用来自 createSignal
的信号 setters 来传递引用,要么使用在父级中声明的回调函数来设置您的普通变量。
在这个解决方案示例中,sectionRef
和 headerRef
都是未分配的变量。 sectionRef
被传递给 ref
道具,在幕后,它被包裹在回调中。回调函数 refCallback
被传递给 ref1
属性,它设置 headerRef
为传递的元素值。
function ParentComponent() {
let sectionRef;
let headerRef;
const refCallback = (el) => {
headerRef = el
}
onMount(() => {
console.log(sectionRef); // logs section el
console.log(headerRef); // logs header el
});
return (
<section>
<Overview ref={sectionRef} ref1={refCallback} />
</section>
);
}
function Overview(props) {
return (
<section ref={props.ref}>
<article>
<h2 ref={props.ref1}>Lorem Ipsum</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Maxime
mollitia, molestiae quas vel sint commodi repudiandae consequuntur
voluptatum laborum numquam blanditiis harum quisquam eius sed odit
fugiat iusto fuga praesentium optio, eaque rerum!
</p>
</article>
</section>
);
}
如何
再次重申。 Solid 使其工作的方式是在编译输出中,如果一个组件 属性 被命名为 ref
,它被一个对象方法替换(在这种情况下具有与回调函数相同的策略)它位于创建“ref”变量(例如sectionRef
)的同一位置,这样就可以将“ref”变量分配给它。
如果你很好奇,这里是解决方案的实际编译输出,你可以在其中看到 ref
的实际情况。
// Compiled Output
function ParentComponent() {
let sectionRef;
let headerRef;
const refCallback = el => {
headerRef = el;
};
// ...
return (() => {
const _el$ = _tmpl$.cloneNode(true);
insert(_el$, createComponent(Overview, {
ref(r$) {
const _ref$ = sectionRef;
typeof _ref$ === "function" ? _ref$(r$) : sectionRef = r$;
},
ref1: refCallback
}));
// ...
})();
}
父组件:
function ParentComponent() {
return (
<section>
<ChildComponent ref={sectionRef} ref1={headerRef} />
</section>
);
}
子组件:
function ChildComponent(props) {
return (
<section ref={props.ref}>
<article>
<h2 ref={props.ref1}>Lorem Ipsum</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Maxime mollitia,
molestiae quas vel sint commodi repudiandae consequuntur voluptatum laborum
numquam blanditiis harum quisquam eius sed odit fugiat iusto fuga praesentium optio, eaque rerum!</p>
</article>
</section>
);
}
我的目标是能够从父组件定位子组件中的不同 DOM 元素,以便我可以根据父组件的滚动事件为它们设置动画。
我尝试将引用作为不同的数据结构传递:
<ChildComponent ref={{sectionRef, headerRef}} />
和:
<ChildComponent ref={[sectionRef, headerRef]} />
和:
<ChildComponent section={sectionRef} header={headerRef} />
但不断出现第二个引用未定义的错误。如果我为每个子组件传递一个引用,我只能让它工作。有什么想法吗?
参考链接 material 我查看了: https://www.solidjs.com/tutorial/bindings_forward_refs https://www.solidjs.com/docs/latest/api#ref
在组件中设置 Refs 时
有 3 种方法可以在组件中引用 DOM 元素。
- 传递常规变量
function Component() {
let buttonEl;
onMount(() => {
console.log(buttonEl) // logs button element
})
return (
<button ref={buttonEl}>Click</button>
);
}
- 通过信号setter
function Component() {
const [buttonEl, setButtonEl] = createSignal(null);
onMount(() => {
console.log(buttonEl()) // logs button element
})
return <button ref={setButtonEl}>Click</button>;
}
- 通过回调
function Component() {
let buttonEl;
const refCallback = (el) => {
buttonEl = el;
};
onMount(() => {
console.log(buttonEl); // logs button element
});
return <button ref={refCallback}>Click</button>;
}
在子组件中设置 Refs 时
然而,当引用在子组件中设置的 DOM 元素时,情况就不同了。为了演示,我们不会对子组件使用 ref
prop,而是使用 PASSREF
prop.
- 将常规变量传递给
PASSREF
。变量不更新并且是undefined
.
function Component() {
let buttonEl;
onMount(() => {
console.log(buttonEl); // logs `undefined`
});
return <Child PASSREF={buttonEl} />;
}
function Child(props) {
return <button ref={props.PASSREF}>Click</button>;
}
- 将信号 setter 传递给
PASSREF
,有效。
function Component() {
const [buttonEl, setButtonEl] = createSignal(null)
onMount(() => {
console.log(buttonEl()); // logs button element
});
return <Child PASSREF={setButtonEl} />;
}
function Child(props) {
return <button ref={props.PASSREF}>Click</button>;
}
- 将与
buttonEl
在相同范围内声明的回调传递给PASSREF
,有效。
function Component() {
let buttonEl;
const refCallback = (el) => {
buttonEl = el;
};
onMount(() => {
console.log(buttonEl); // logs button element
});
return <Child PASSREF={refCallback} />;
}
function Child(props) {
return <button ref={props.PASSREF}>Click</button>;
}
要修复使用常规变量 let buttonEl;
的 #1 解决方案,请使用正确的组件属性 ref
以便将元素设置为变量。
function Component() {
let buttonEl;
onMount(() => {
console.log(buttonEl); // logs button element
});
return <Child ref={buttonEl} />;
}
function Child(props) {
return <button ref={props.ref}>Click</button>;
}
那么为什么这样做有效呢?好吧,因为在编译输出中,使用 ref 的 Child prop 参数实际上被内联回调替换,这样它就位于声明 buttonEl
的相同范围内并且可以更新。
// This is NOT how the Compiled Output actually looks,
// but ref argument is replaced by an inline callback
function Component() {
let buttonEl;
onMount(() => {
console.log(buttonEl); // logs button element
});
return <Child ref={(el) => buttonEl = el} />;
}
function Child(props) {
return <button ref={props.ref}>Click</button>;
}
是不是很眼熟?这几乎完全符合 #3 解决方案的结构,您可以在其中传递回调函数来更新 buttonEl
.
解决方案
老实说,这取决于您的用例,要么使用来自 createSignal
的信号 setters 来传递引用,要么使用在父级中声明的回调函数来设置您的普通变量。
在这个解决方案示例中,sectionRef
和 headerRef
都是未分配的变量。 sectionRef
被传递给 ref
道具,在幕后,它被包裹在回调中。回调函数 refCallback
被传递给 ref1
属性,它设置 headerRef
为传递的元素值。
function ParentComponent() {
let sectionRef;
let headerRef;
const refCallback = (el) => {
headerRef = el
}
onMount(() => {
console.log(sectionRef); // logs section el
console.log(headerRef); // logs header el
});
return (
<section>
<Overview ref={sectionRef} ref1={refCallback} />
</section>
);
}
function Overview(props) {
return (
<section ref={props.ref}>
<article>
<h2 ref={props.ref1}>Lorem Ipsum</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Maxime
mollitia, molestiae quas vel sint commodi repudiandae consequuntur
voluptatum laborum numquam blanditiis harum quisquam eius sed odit
fugiat iusto fuga praesentium optio, eaque rerum!
</p>
</article>
</section>
);
}
如何
再次重申。 Solid 使其工作的方式是在编译输出中,如果一个组件 属性 被命名为 ref
,它被一个对象方法替换(在这种情况下具有与回调函数相同的策略)它位于创建“ref”变量(例如sectionRef
)的同一位置,这样就可以将“ref”变量分配给它。
如果你很好奇,这里是解决方案的实际编译输出,你可以在其中看到 ref
的实际情况。
// Compiled Output
function ParentComponent() {
let sectionRef;
let headerRef;
const refCallback = el => {
headerRef = el;
};
// ...
return (() => {
const _el$ = _tmpl$.cloneNode(true);
insert(_el$, createComponent(Overview, {
ref(r$) {
const _ref$ = sectionRef;
typeof _ref$ === "function" ? _ref$(r$) : sectionRef = r$;
},
ref1: refCallback
}));
// ...
})();
}