어떻게 Vue 에서 Svelte 의 Defer Transition 을 실현 합 니까?
8421 단어 VueSvelteDeferTransition
스 벨 트 의 이른바 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를 참고 하면 됩 니 다.
두 번 째 수 요 를 실현 하기 위해 몇 가지 문 제 를 해결 해 야 한다.
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 을 실현 하 는 지 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 해 주 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Vue Render 함수로 DOM 노드 코드 인스턴스 만들기render에서createElement 함수를 사용하여 DOM 노드를 만드는 것은 직관적이지 않지만 일부 독립 구성 요소의 디자인에서 특수한 수요를 충족시킬 수 있습니다.간단한 렌더링 예는 다음과 같습니다. 또한 v...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.