[Elm] DOM 업데이트 후 JS 코드 실행

5333 단어 VirtualDom포트Elm
이 내용은 Elm 0.18, 0.19를 대상으로 합니다.
또한 Elm Discourse의 답변은 원래 재료입니다.

결론


update 함수로 DOM을 업데이트 한 후 JavaScript를 실행하려면,
elm.app.ports.foo.subscribe(function (id) {
  requestAnimationFrame(function () {
    /* when this callback executes, the view should have rendered. */
  })
})

처럼 포트를 등록해야 합니다.

문제 제기



Elm의 update 함수는 유형 update : Model -> Msg -> (Model, Cmd Msg)로 표시된 것처럼 이벤트 (Msg로 표시된 것)에 따라 업데이트 된 DOM 구조 (엄격히 DOM 구조 자체가 아닙니다. Model )와 부작용 ( Cmd Msg )을 동시에 지정합니다.

ports 를 사용해 JavaScript 를 실행하는 경우, Cmd Msg 부분에 그 처리를 기술합니다만,
업데이트 후 DOM에 의존하는 JavaScript 코드를 실행하려면 어떻게해야합니까?

화면 업데이트 및 Cmd 처리 타이밍


update 함수가 새 DOM 구조를 지정하면 Elm은 업데이트 프로세스를 animation-frame에 등록합니다.
그 직후에, Cmd Msg 로서 지정된 처리를 실시합니다.
animation-frame는 브라우저 화면의 새로 고침 속도에 따라 간격으로 처리를 호출하므로,
특히 궁리 없이 ports를 사용해 JavaScript의 처리를 Cmd로서 등록했을 경우, 화면의 갱신 처리보다 먼저 그 JavaScript가 실행되어 버릴 가능성이 있습니다.

해결 방법



화면의 갱신 처리를 animation-frame에 등록하고 있으므로, 실행하고 싶은 JavaScript도 마찬가지로 animation-frame에 등록하면, animation-frame가 태스크 큐로서 실행 순서를 보증해 줍니다.

구체적으로는 처음에 '결론'으로 나타낸 것처럼
elm.app.ports.foo.subscribe(function (id) {
  requestAnimationFrame(function () {
    /* when this callback executes, the view should have rendered. */
  })
})

와 같은 형식으로, 실행하고 싶은 처리를 animation-frame 에 등록하는 처리를 기술하면 됩니다.

elm-lang/dom 등은 내부적으로 animation-frame에 처리를 등록하는 구현이므로, 갱신 후에 처음 작성되는 HTML 태그에 대해서 elm-lang/dom로 정의되고 있는 스크롤이나 포커스등의 처리를 적용 하는 경우에는, 특히 신경쓰지 않고 update 의 반환값에 갱신 후의 Model 과 함께 처리를 등록하면 잘 움직입니다.

위험 🐐 스크립트 예술과의 관계



사실 위험🐐 스크립트 예술 을 사용해도 「DOM 구조에 의존하는 JavaScript를 실행한다」라고 하는 수요를 실현할 수가 있습니다.

단순히 View에 script 태그를 직접 포함하면 됩니다.

someView : Model -> Html Msg
someView { showPart } =
    div
        []
        [ if showPart then
            div
                []
                [ anotherView
                , node "script" [] [ text """ /* JavaScript code */ """ ]
                ]
          else
            text ""
        ]

다만, 이 기법은 "버그"로 애매하고 있습니다. , 다음의 버젼의 Elm 에서는 사용할 수 없게 될 가능성이 높습니다.

사용하지 않는 위험 🐐 스크립트 예술이 아닌 animation-frame 를 사용한 방법을 지금의 버전에서도 사용하는 것을 추천합니다.

좋은 웹페이지 즐겨찾기