Open utterances-bot opened 4 months ago
所以还有机会看到博主大佬整理的后续那篇文章吗?关于 Rxjs 这块,看了几篇文章,还是博主的印象较为深入浅出🥹
正在看博主关于 hooks 结合 Rxjs 这块的那篇,发现居然是 Observable Hooks 的作者,膜拜
哈哈感谢回复,第一个之前有搜到过,但感觉没有那么直观,第二个正在看,再次感谢
CRIMX @.***> 於 2024年6月28日週五 上午10:22寫道:
所以还有机会看到博主大佬整理的后续那篇文章吗?关于 Rxjs 这块,看了几篇文章,还是博主的印象较为深入浅出🥹
抱歉草稿好像已经丢了哈哈,当时写到一半的时候 RxJS7 刚出来,operators 改了挺多的,概念倒是没什么变化。
你可以看看 rxmarbles https://rxmarbles.com/ 或者 rxtutor https://rxtutor.org/ 。
— Reply to this email directly, view it on GitHub https://github.com/crimx/blog-comments/issues/23#issuecomment-2195989639, or unsubscribe https://github.com/notifications/unsubscribe-auth/AG7BM5H6TUQTWGF7OFBHEFTZJTCH5AVCNFSM6AAAAABJ7ITCWKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCOJVHE4DSNRTHE . You are receiving this because you commented.Message ID: @.***>
大佬打扰了,在写个人项目练习 observable-hooks 过程中,有个问题想请假下,假如对一个 textarea 组件进行封装,现在想实现检测该组件的多个状态(高度变化, 是否有输入内容等),那么我应该拆成多个 useObservableState ,还是在一个 useObservableState 里面处理所有状态的逻辑?
以下为当前代码:
function AskQuestionArea({ className, placeholder = 'Ask me anthing...', ...props }: { className?: string, placeholder?: string }) {
const textareaRef = useRef<HTMLTextAreaElement>(null)
const textareaWrappRef = useRef<HTMLDivElement>(null)
const [height] = useObservableState(() => {
return defer(() => {
const textareaEl = textareaRef.current
if (!textareaEl) {
console.error('no textareaEl and return')
return of('20px')
}
// 获取初始高度作为最小高度
const minHeight = textareaEl.clientHeight
const updateHeight$ = (): Observable<string> => {
return new Observable<string>((observer) => {
requestAnimationFrame(() => {
const scrollPos = textareaEl.scrollTop
const currHeight = textareaEl.style.height
textareaEl.style.height = '20px'
const newHeight = Math.max(textareaEl.scrollHeight, minHeight)
textareaEl.style.height = currHeight // 使用保存的高度
textareaEl.scrollTop = scrollPos
requestAnimationFrame(() => {
textareaEl.style.height = `${newHeight}px`
observer.next(`${newHeight}px`)
observer.complete()
})
})
})
}
return merge(
of(`${minHeight}px`),
fromEvent<React.ChangeEvent<HTMLTextAreaElement>>(textareaEl, 'input').pipe(
startWith(null), // 确保初始化也会计算高度
switchMap(() => updateHeight$()),
),
)
})
}, '20px') // 默认值
const handleFocus = () => {
if (textareaRef.current && textareaWrappRef.current) {
textareaWrappRef.current?.setAttribute('data-focus', 'true')
}
}
const handleBlur = () => {
if (textareaRef.current && textareaWrappRef.current) {
textareaWrappRef.current?.removeAttribute('data-focus')
}
}
return (
<div className="group flex w-full flex-col" ref={textareaWrappRef}>
<div
className={
cn([
'relative',
'inline-flex',
'!h-auto',
'min-h-8',
'cursor-text',
'flex-row',
'items-center',
'rounded-xl',
'border-2',
'bg-[hsl(var(--background))]',
'p-2',
'gap-1',
'shadow-sm',
'transition-colors',
'!duration-150',
'hover:border-indigo-200',
'group-data-[focus=true]:border-[hsl(var(--ring))]',
'motion-reduce:transition-none',
])
}
>
<Textarea
ref={textareaRef}
className={
cn([
'bg-[hsl(var(--background))]',
'text-[hsl(var(--foreground))]',
'pe-2',
'focus-visible:ring-0',
'border-0',
'max-h-80',
], className)
}
style={{ height }}
onFocus={handleFocus}
onBlur={handleBlur}
placeholder={placeholder}
{...props}
/>
<Button
size="icon"
className="size-8 self-end rounded-lg"
>
<Icon icon="majesticons:arrow-right-line" />
</Button>
</div>
</div>
)
}
export default AskQuestionArea
@Zeno2019 我一般是倾向写纯的 operator ,避免在其中做副作用。这样可以独立测试 Observerable 链。比如这里的 textarea 高度,我会算出一个 height$
,再用 const height = useObservableState(height$)
走正常的 React 组件设 props 。
(P.S. 现在可以用新的 field-sizing: content
感谢大佬回复,我研究看看🙏
理解 RxJS :四次元编程 | CRIMX BLOG
学习 RxJS 最大的问题是官方造了很多概念,但文档又解释得不太全面和易懂,需要结合阅读各种文章(特别是 Ben Lesh 的,包括视频)。本文试图整体梳理一遍再用另外的角度来介绍,希望能帮助初学者或者对 RxJS 的一些概念比较含糊的使用者。 为什么需要 RxJS RxJS
https://blog.crimx.com/2018/02/16/understanding-rxjs/