Hyperapp에서 보기 구성 요소의 DOM 요소 작업
그러나 때때로 나는 구성 요소 정의 자체 내에서 보기 구성 요소의 요소에 액세스할 수 있기를 바라고 있습니다. 그렇게 하면 상태, 작업, 효과 및 구독이 더 복잡해져 이미 삐걱거리는 앱에 부담을 주지 않고 구성 요소의 동작을 캡슐화할 수 있습니다. React's
useRef
-hook에 해당하는 일종의 Hyperapp이 있었으면 합니다.결과적으로 Hyperapp의 지원되지 않는 구현 세부 정보(즉, 해킹)를 사용하는 것이 가능합니다. 방법은 다음과 같습니다.
마법 속성
먼저
Object.defineProperty
를 상기시켜 드리겠습니다. 다른 많은 용도 중에서 객체의 속성을 get
및 set
함수 쌍으로 정의할 수 있습니다. 이는 액세스되거나 할당될 때 일부 코드를 실행하는 속성을 정의할 수 있음을 의미합니다.
const obj = {}
let normalVal
Object.defineProperty(obj, 'normal', {
get () { return normalVal },
set (val) { normalVal = val }
})
Object.defineProperty(obj, 'wacky', {
get () { return -99 },
set (val) { console.log(val + ' ... really?!') }
})
obj.normal = 42
obj.normal // is 42
obj.wacky = 42 // logs "42 ... really?!"
obj.wacky // is always -99 regardless
나에게 당신의 비밀을 숨길 수 없습니다, Hyperapp!
이제 Hyperapp의 소스 코드를 살펴보십시오. 구체적으로 this line
return (vdom.node = node)
... 그리고 this line
return (newVNode.node = node)
패치 프로세스의 두 위치에서 하이퍼앱은
node
속성을 할당하여 vnode를 변경합니다. 편리하게 할당되는 것은 vnode에 해당하는 DOM 요소입니다.VNode 데코레이터
이는 다음과 같이 vnode에 대한 데코레이터를 만들 수 있음을 의미합니다.
const withElement = (vnode, fn) => {
let element
Object.defineProperty(vnode, 'node', {
get () { return element },
set (e) {
element = e
fn(element)
}
})
return vnode
}
그리고 입력 및 버튼이 있는 구성 요소인
useRef
에 대해 React 문서에서 사용하는 예제를 해결할 수 있습니다. 버튼을 클릭하면 관련 입력이 집중됩니다.const TextInputWithFocusButton = () => withElement(
h('span', {}, [
h('input', {type: 'text'}),
h('button', {}, text('Focus input')),
]),
span => {
let [input, button] = span.childNodes
button.addEventListener('click', () => input.focus())
}
)
우리가 실제 DOM 요소로 작업하는 함수("요소 프로세서"라고 부름)는 보기에서 구성 요소가 사용되는 각 인스턴스에 대해 자체 해당 범위 요소를 입력으로 사용하여 호출됩니다.
주기를 낭비하지 마십시오
뷰가 패치될 때마다 요소 프로세서가 호출되기 때문에 완벽하지는 않습니다. 실제로 요소가 처음 생성될 때 두 번입니다. 포커스를 입력하기 위해 버튼 클릭을 연결한 후에는 해당 범위에 대해 다시 수행할 필요가 없습니다. 그래서 한 번만 발생하도록 가드를 추가합니다.
span => {
// make sure we only do this once in the lifetime of
// each component like this:
if (span._seen) return
span._seen = true
let [input, button] = span.childNodes
button.addEventListener('click', () => input.focus())
}
주요 중요성:
이 구성 요소가 올바르게 작동하려면 Hyperapp이 동일한 요소를 계속 연결하는 것이 중요합니다. 구성 요소 루트 가상 노드에
key
property을 추가하지 않으면 보장되지 않습니다.const TextInputWithFocusButton = (key) => withElem(
h('span', {key}, [
...
Try the full example live here !
Real-DOM-land에서 액션을 보내시겠습니까?
당신은 여전히 궁금할 것입니다: DOM-랜드에서 하이퍼-랜드로 어떻게 돌아갈 수 있습니까? 요소 처리 기능에서 어떻게 작업을 발송할 수 있습니까?
첫째, 그렇게 해야 하는 경우는 매우 드뭅니다. (기술적으로는 이 중 어느 것도 필요하지 않지만 특히 저것은 필요하지 않습니다)
둘째: 무한 루프가 발생하지 않도록 주의하십시오. 디스패치 액션은 뷰가 패치되도록 하는 상태를 변경할 수 있으며, 이로 인해 요소 프로세서 함수가 다시 호출되고 액션을 다시 디스패치하는 등의 작업이 수행됩니다.
이러한 주의 사항은 다음과 같이 수행합니다. 가상 노드에서 구성된 이벤트에 작업을 바인딩하기만 하면 됩니다. 요소 프로세서에서 구성된 이벤트를 전달합니다. 케이크 한 조각 :)
const TextInputWithFocusButton = ({id, OnButtonFocus}) => withElement(
h('span', {key: id, onbuttonfocus: OnButtonFocus}, [
h('input', {type: 'text'}),
h('button', {}, text('Focus input')),
]),
span => {
if (span._seen) return
span._seen = true
let [input, button] = span.childNodes
button.addEventListener('click', () => {
span.dispatchEvent(new Event('buttonfocus'))
input.focus()
})
}
)
Here's the live example again , 이번에는 버튼 중심 입력을 맨 위로 이동하는 동작을 사용합니다. (다른 입력에 다른 텍스트를 입력하여 확인)
Note: We need to add a
requestAnimationFrame
aroundinput.focus()
now because when we dispatch theOnButtonFocus
it causes the elements to be moved in the DOM. That causes them to lose focus so we wait tofocus()
until after they have moved.
Reference
이 문제에 관하여(Hyperapp에서 보기 구성 요소의 DOM 요소 작업), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/zaceno/access-dom-elements-for-virtual-nodes-in-hyperapp-2f5k텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)