어떻게 Vue 에서 Svelte 의 Defer Transition 을 실현 합 니까?

최근 Rich Harris 의'Rethinking Reactivity'영상 을 보고 Svelte 프레임 워 크 의 효율 성에 감탄 하면 서 Vue 가 갖 추 지 못 한 애니메이션 에 대한 원생 지원 인 defer transitions 도 발견 했다.
스 벨 트 의 이른바 defer transition 효 과 를 살 펴 보 자.

Svelte 로 만 든 Todo Demo 애플 리 케 이 션 입 니 다.전체 todo 는 세 부분 으로 나 뉜 다.입력 부분,todo 목록,done 목록.todo 목록 의 항목 을 클릭 하면 해당 항목 은 done 목록 으로 이동 되 며 반대로 도 마찬가지 입 니 다.
여기 서 항목 이 한 목록 에서 다른 목록 으로 이동 합 니 다.갑 작 스 럽 게 반 짝 이 는 것 이 아니 라 클릭 한 곳 에서 목적지 로 이동 합 니 다.또한 목록 에 있 는 항목 이 떠 날 때 나머지 항목 은 빈 자 리 를 메 우기 위해 미끄러져 위로 이동한다.Svelte 에 서 는 코드 를 몇 줄 만 더 하면 개발 자 에 게 매우 우호 적 이 고 효율 적 입 니 다.다음 코드 참조 또는Svelte 튜 토리 얼

{#each todos.filter(t => !t.done) as todo (todo.id)}
    <label
	in:receive="{{key: todo.id}}"
        out:send="{{key: todo.id}}"
        animate:flip>
        <input type=checkbox on:change={() => mark(todo, true)}>
            {todo.description}
            <button on:click="{() => remove(todo)}">remove</button>
    </label>
{/each}
element 에 만 in,out,animate 속성 을 추가 합 니 다.여기 서 in 과 out 은 각각 프레임 워 크 가 제공 하 는 함수 receive 와 send 를 받 아들 여 선별 조건 을 제공 합 니 다.animate 속성 은 내 장 된 flip 방법 을 받 습 니 다.이곳 의 flip 는 반전 이 아니 라FLIP 기술기술 입 니 다.vue 는에서 도 유용 합 니 다.전체 이동 목록 의 나머지 항목 으로 잃 어 버 린 요소 의 위 치 를 메 우 는 데 사 용 됩 니 다.
그래서 나 는 Vue 라면 어떻게 그 에 상응하는 효 과 를 거 둘 수 있 을 까 생각 했다.자세 한 설명 을 보고 싶 지 않 으 면code pen의 코드 를 직접 볼 수 있 습 니 다)
Vue 네 이 티 브 는 애니메이션 을 지원 하 는 두 개의 구성 요 소 를 제공 합 니 다.transition 과 transition-group.list 의 이동 이기 때문에 transition-group 을 사용 합 니 다.구체 적 인 사용법 은 Vue 튜 토리 얼Transitions & Animation을 참고 하면 된다.
같은 효 과 를 얻 으 려 면 두 가지 UI 애니메이션 효과 가 있어 야 한다.
목록 에 있 는 항목 이 사라 지면 남 은 항목 이 이동 하여 빈 자 리 를 보충 합 니 다.
항목 이 사라 지 는 동시에 다른 목록 에 삽 입 될 때 항목 이 이동 합 니 다.
첫 번 째 수요 의 실현 은 비교적 간단 합 니 다.vue 원생 은 좋 은 지원 을 제 공 했 습 니 다.Vue 문서 의List-Move-Transitions를 참고 하면 됩 니 다.
두 번 째 수 요 를 실현 하기 위해 몇 가지 문 제 를 해결 해 야 한다.
  • 사라 진 항목 의 위치 정보
  • 항목 의 위치 정보 삽입
  • 효과 시작 과 종료 시기
  • 우 리 는 먼저 앞의 두 문제 가 어떻게 해결 되 는 지 보 자.문서 에 따 르 면 transition-group 은 자바 script hook 을 제공 합 니 다.각각:
    
     v-on:before-enter
     v-on:enter
     v-on:after-enter
     v-on:enter-cancelled
    
     v-on:before-leave
     v-on:leave
     v-on:after-leave
     v-on:leave-cancelled
    
    시각 적 으로 표시 하면 다음 그림 과 같 습 니 다.

    before-enter:삽입 항목 의 transition 의 초기 값 을 설정 하 는 데 사용 합 니 다.이 때 BoundingClient Rect.enter:동 효 기 를 가 져 올 수 없습니다.이때 enter 갈고리 함수 의 입 참 엘 은 boundingClient Rect after-enter 를 가 져 올 수 있 습 니 다.
    leave 도 비슷 해.
    그래서 우리 가 항목 요소 인 DOMRect 정 보 를 얻 을 수 있 는 시 기 는 enter 와 leave 일 때 뿐이다.
    이렇게 하면 우 리 는 leave 때 leave 항목 의 DOMRect 데 이 터 를 받 아 저장 할 수 있다.enter 에 있 을 때,우 리 는 leave 항목 과 enter 항목 의 위치 정 보 를 동시에 가 질 수 있 습 니 다.
    위치 정 보 를 얻 었 는데 어떻게 하면 항목 이 들 어 갈 때 사라 진 항목 에서 이동 하 는 효과 가 있 을 수 있 습 니까?먼저 생각해 보고 뒤의 해석 을 볼 수 있다.
    그래서 우 리 는 이동 효 과 를 얻 으 려 면 먼저 leave 항목 요 소 를 숨 겨 야 합 니 다.
    
    leave(el, done) {
          console.log("before leave");
          const rect = el.getBoundingClientRect();
          sendRectMap.set(el.dataset.key, rect);
          el.style.display = "none";
    },
    
    그 다음 에 enter 항목 요소 에 위치 초기 상 태 를 설정 합 니 다.초기 화 된 위 치 는 leave 항목 요소 의 위 치 를 설정 한 다음 에 transition 이 효력 을 발생 하기 시 작 했 을 때 그 위 치 를 삽입(enter)의 위치 로 복원 합 니 다.
    이런 방법 은 사실 이른바 FLIP 기술 이다.transition-group 구성 요소 에서 도 이 기술 을 사용 하여 나머지 목록 을 이동 하여 이동 항목 의 공백 을 채 웁 니 다.
    
    var first = el.getBoundingClientRect();
    
    // Now set the element to the last position.
    el.classList.add('totes-at-the-end');
    
    // Read again. This forces a sync
    // layout, so be careful.
    var last = el.getBoundingClientRect();
    
    // You can do this for other computed
    // styles as well, if needed. Just be
    // sure to stick to compositor-only
    // props like transform and opacity
    // where possible.
    var invert = first.top - last.top;
    
    // Invert.
    el.style.transform =
        `translateY(${invert}px)`;
    
    // Wait for the next frame so we
    // know all the style changes have
    // taken hold.
    requestAnimationFrame(function() {
    
      // Switch on animations.
      el.classList.add('animate-on-transforms');
    
      // GO GO GOOOOOO!
      el.style.transform = '';
    });
    
    다음 문 제 는 enter 항목 요소 transition 의 초기 상 태 를 언제 설정 하 느 냐 하 는 것 입 니 다.enter 항목 요소 transition 의 끝 상 태 를 언제 설정 하 느 냐 하 는 것 입 니 다.
    위 에서 언급 한 javascript hook 에 따 르 면,우 리 는 before-enter 갈고리 함수 에서 초기 상 태 를 설정 하고,이어서 enter 갈고리 함수 에서 transition 종료 상 태 를 설정 할 수 있 습 니 다.그렇다면 우리 의 초기 상 태 는 무엇 일 까?저 희 는 getBoundingClient Rect 를 통 해 enter 요소(후 to 로 표시)의 DOMRect 데 이 터 를 얻 을 수 있 습 니 다.top,left,bottom,right,width,height,x,y 를 포함 합 니 다.또한 저 희 는 이전에 저 장 된 leave 위치 맵 을 통 해 leave 항목 의 위치 정 보 를 얻 을 수 있 습 니 다(from 이 라 고 함).그래서 before-enter 에서 우 리 는 계 산 된 오프셋 을 통 해 translate 를 통 해 to 요소 의 위 치 를 초기 화 합 니 다.그리고 enter 단계 에서 translate 값 을 from 까지 하고 transition 을 css 에 추가 하면 됩 니 다.
    before-enter 갈고리 에서:
    
            //         
            const key = el.dataset.key;
            // enter   map,    , before-enter   ,
            // receiveRectMap get  to 。      。     
            const to = receiveRectMap.get(key);
            // leave   map
            const from = sendRectMap.get(key);
    
            //      
            const dx = from.left - to.left;
            const dy = from.top - to.top;
            
            //    to     
            el.style.transform = `translate(${dx}px, ${dy}px)`;
            el.style.opacity = 0;
    
    enter 갈고리 에서:
    
            el.style.transition = "all 800ms";
            el.style.transform = "";
            el.style.opacity = 1;
            el.style.display = "block";
    
    위의 코드 에 서 는 before-enter 에서 to 는 receiveRectMap.get(key)을 통 해 얻 을 수 있 습 니 다.그러나 이때 receiveRectMap 에는 키 에 대응 하 는 DOMRect 값 이 없습니다.비록 before-enter 의 입 참 은 el(HTML Element)이지 만 이 엘 요소 의 DOMRect 의 모든 값 은 0 이기 때문에 enter 방법 에서 el 을 receiveRectMap 에 넣 어야 합 니 다.그러면 하나의 모순 이 생 길 것 이다.그것 은 before-enter 에서 translate 를 통 해 to 요소 의 위 치 를 초기 화 할 수 없다 는 것 이다.그래서 우 리 는 defer transition 기술 을 사용 하여 transition 의 발생 을 지연 시 킵 니 다.
    enter 에서 setTimeout 이나 request Animation Frame 을 사용 하여 defer transition 을 실현 할 수 있 습 니 다.
    
    requestAnimationFrame(() => {
            const key = el.dataset.key;
    		  //   ,receiveRectMap    key   。
            const to = receiveRectMap.get(key);
            const from = sendRectMap.get(key);
    
            const dx = from.left - to.left;
            const dy = from.top - to.top;
    
            //        transition   ,
            //   to                 ,
            //         transition        from  ,      
            el.style.transition = "all 0ms";
            el.style.transform = `translate(${dx}px, ${dy}px)`;
            
            //       ,    animation frame ,  FLIP  ,      。
    	requestAnimationFrame(() => {
              el.style.transition = "all 800ms";
              el.style.transform = "";
              el.style.opacity = 1;
              el.style.display = "block";
            });
          });
    
    전체 코드 참고 가능codepen
    마지막 효과:

    이상 은 Vue 에서 Svelte 의 Defer Transition 을 어떻게 실현 하 는 지 에 대한 상세 한 내용 입 니 다.Vue 가 Svelte 의 Defer Transition 을 실현 하 는 지 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 해 주 십시오!

    좋은 웹페이지 즐겨찾기