React 서스펜스가있는 사전 캐싱 이미지
React의 서스펜스 기능은 흥미 진진하고 있으며, 개발자가 "준비"될 때까지 구성 요소의 렌더링을 쉽게 지연 시켜서 더 부드러운 사용자 경험을 초래할 수 있습니다. "준비"는 여기에서 여러 측면을 참조 할 수 있습니다. 예를 들어, 데이터로드 유틸리티는 서스펜스와 함께 사용하여 각 쿼리의로드 상태를 수동으로 추적하지 않고 모든 데이터가 전송되는 동안 일관된로드 상태를 표시 할 수 있습니다. 그런 다음 데이터를 사용할 수 있고 구성 요소가 "준비"되면 렌더링됩니다. 이것은 서스펜스와 가장 자주 논의되는 주제이며, 나는 이전에 그것에 대해 썼습니다. 그러나 데이터 로딩은 서스펜스가 사용자 경험을 향상시킬 수있는 많은 사용 사례 중 하나 일뿐입니다. 오늘 이야기하고 싶은 또 다른 사용 사례는 이미지 사전 로딩입니다.
화면에 도달 할 때 이미지가 다운로드되어 렌더링 될 때 위치 지터와 점프가있는 웹 앱을 만들거나 사용한 적이 있습니까? 우리는 그것을 컨텐츠 재 배열이라고 부르며 충격적이고 불쾌합니다. 서스펜스는이 문제를 해결하는 데 도움이 될 수 있습니다. 서스펜스의 요점은 준비가 될 때까지 구성 요소 렌더링을 방지하는 것임을 알고 있습니까? 다행스럽게도 "Ready"는 여기에서 매우 개방되어 있습니다. 목적을 위해 "필요한 사전로드 된 이미지"가 포함될 수 있습니다. 어떻게하는지 보자!
서스펜스 빠른 시작
세부 사항을 파헤 치기 전에 서스펜스가 어떻게 작동하는지 빨리 이해해 봅시다. 두 가지 주요 부분이 있습니다. 우선, 구성 요소 개념이 있습니다. 이것은 React가 우리의 구성 요소를 렌더링하려고한다는 것을 의미하지만 "준비된"것은 아닙니다. 이런 일이 발생하면 구성 요소 트리에서 가장 가까운 "폴백"이 렌더링됩니다. 우리는 곧 폴백을 만드는 방법을 볼 수 있지만 (상당히 간단한) 구성 요소는 반응이 아직 준비되지 않았다고 약속을 지킬 것이라고 말합니다. React는 약속을 포착하고 구성 요소가 아직 준비되지 않았다는 것을 깨닫고 폴백을 렌더링합니다. 약속이 구문 분석되면 React는 다시 렌더링을 시도 할 것입니다. 이 과정을 반복하십시오. 그렇습니다. 나는 약간 지나치게 단순화되었지만 서스펜스가 어떻게 작동하는지의 요점이며, 우리는 우리가 갈 때 이러한 개념 중 일부를 확장 할 것입니다.
서스펜스의 두 번째 부분은 "전환"상태 업데이트의 도입입니다. 이것은 우리가 상태를 설정한다는 것을 의미하지만, 반응은 상태 변화로 구성 요소가 매달릴 수 있다고 말하며, 이런 일이 발생하면 폴백이 렌더링 되지 않습니다 . 대신 상태 업데이트가 준비 될 때까지 현재 화면을 계속 보려고합니다. 물론 React는 개발자 에게이 프로세스가 진행 중임을 알 수 있도록 "보류중인"부울 지표를 제공하여 인라인로드 피드백을 제공 할 수 있습니다.
이미지를 사전로드합시다!
먼저,이 기사의 끝에 우리가 만들고있는 데모가 완전한 데모가 있음을 지적하고 싶습니다. 코드에 뛰어 들고 싶다면 지금 데모를 자유롭게 열어주십시오. 전환 상태 업데이트와 함께 서스펜스가 어떻게 사용되는지 보여줍니다. 이 게시물의 나머지 부분은 코드를 단계별로 구축하고 그 길을 어떻게 그리고 이유를 설명합니다.
좋아, 시작하자!
우리는 모든 이미지가 사전로드 될 때까지 구성 요소가 매달리기를 원합니다. 가능한 한 많은 작업을 단순화하려면<suspenseimage></suspenseimage>
SRC 속성을 수신하는 구성 요소, 이미지를 사전로드하고 예외 던지기를 처리 한 다음 <img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174358885649082.png" class="lazy" alt="React 서스펜스가있는 사전 캐싱 이미지">
HTML에서 이미지를 사용하지만 javaScript의 Image()
객체를 사용하여 명령적인 방식으로 이미지를 만들 수도 있습니다. 또한, 우리 가이 방식으로 생성하는 이미지에는 이미지가로드 될 때 발사되는 onload
콜백이 있습니다. 다음과 같이 보입니다.
const img = new image (); img.onload = () => { // 이미지가로드 됨};
그러나 우리는 그것을 어떻게 제외하고 던지는 것과 결합합니까? 당신이 나와 같은 경우, 먼저 다음과 같은 것을 생각할 수 있습니다.
const sustenseimg = ({src, ... rest}) => { 새로운 약속을 던지십시오 ((Resolve) => { const img = new image (); img.onload = () => { 해결하다(); }; img.src = src; }); 반품<img alt="" src="%7Bsrc%7D"> ; };
물론 문제는 이것이 항상 약속을 던질 것이라는 것입니다. 반응 할 때마다 렌더링을 시도합니다<suspenseimg></suspenseimg>
사례가 진행되면 새로운 약속이 만들어지고 즉시 발생합니다. 대신, 우리는 단지 이미지로드 전에 약속을 던지고 싶습니다. 컴퓨터 과학의 모든 문제는 간접 계층을 추가하여 해결할 수 있다는 오래된 말이 있습니다 (너무 많은 간접 계층의 문제를 제외하고). SRC를 읽으면 캐시가 이미지를로드했는지 확인하고 그렇지 않은 경우 사전로드가 시작되어 예외가 발생합니다. 그리고 이미지가 사전로드되면 true를 반환하고 React가 계속 우리의 이미지를 렌더링하게합니다.
이것은 우리의 것입니다<suspenseimage></suspenseimage>
구성 요소의 모습 :
내보내기 const spessenseimg = ({src, ... rest}) => { imgcache.read (SRC); 반품<img src="%7Bsrc%7D" alt="React 서스펜스가있는 사전 캐싱 이미지" > ; };
우리가 캐시한 최소 버전은 다음과 같습니다.
const imgcache = { __cache : {}, 읽기 (src) { if (! this .__ 캐시 [src]) { 이 .__ 캐시 [SRC] = 새로운 약속 ((resolve) => { const img = new image (); img.onload = () => { 이 .__ 캐시 [src] = true; Resolve (this .__ 캐시 [SRC]); }; img.src = src; }); } if (this .__ cache [src] instanceof promise) { this .__ 캐시 [SRC]; } 이 .__ 캐시 [SRC]; } };
완벽하지는 않지만 지금은 충분합니다. 계속 사용합시다.
성취하다
아래는 전체 작업 데모에 대한 링크이므로 특정 단계에서 너무 빨리 움직이면 절망하지 마십시오. 우리는 갈 때 설명 할 것입니다.
우리의 폴백을 정의하는 것으로 시작합시다. 컴포넌트 트리에 서스펜스 태그를 배치하여 폴백을 정의하고 폴백 속성을 전달합니다. 보류중인 모든 구성 요소는 가장 최근의 서스펜스 태그를 검색하고 폴백을 렌더링합니다 (그러나 서스펜스 태그를 찾을 수없는 경우 오류가 발생합니다). 실제 애플리케이션에는 프로세스 전반에 걸쳐 많은 서스펜스 태그가있을 수 있으며 개별 모듈에 대한 특정 폴백을 정의하지만이 데모에는 루트 응용 프로그램을 감싸는 태그 만 필요합니다.
기능 앱 () { 반품 ( <suspense fallback="{<Loading"></suspense> }> <showimages></showimages> ); }
<loading></loading>
구성 요소는 기본 스피너이지만 실제 응용 분야에서는보다 원활한 경험을 제공하기 위해 실제로 렌더링하려는 구성 요소의 빈 껍질을 렌더링 할 수 있습니다.
이것으로 우리는<showimages></showimages>
구성 요소는 결국 다음을 사용하여 이미지를 렌더링합니다.
<div> {images.map ((img) => ( <div key="{img}"> <suspenseimg alt="" src="%7Bimg%7D"></suspenseimg> </div> ))} </div>
초기 로딩시 로딩 스피너는 초기 이미지가 준비 될 때까지 표시되며,이 시점에서 인터레이스 재 배열 지연없이 동시에 표시됩니다.
전환 상태 업데이트
이미지가 제자리에 있으면 다음 이미지의 배치를로드 할 때로드 후에 표시되기를 원합니다. 물론 기존 이미지를 화면에로드 할 때 유지합니다. 우리는 useTransition
후크를 사용하여이를 수행합니다. 이것은 우리의 상태 업데이트가 진행 중이지만 중단되었음을 나타내는 startTransition
기능과 isPending
부울을 반환합니다 (또는 중단되지 않더라도 상태 업데이트가 너무 오래 걸리면 여전히 사실 일 수 있음). 마지막으로, useTransition
호출되면, timeoutMs
값을 전달해야합니다.이 값은 최대 시간의 최대 시간입니다. isPending
플래그는 사실 일 수 있습니다. 그 후 RECT는 낙하를 포기하고 렌더링 할 수 있습니다 (가까운 시일 내에 timeoutMs
매개 변수가 삭제 될 수 있으며 기존 콘텐츠가 업데이트 될 때 전이 상태 업데이트는 가능한 한 오래 기다릴 수 있습니다).
이것이 내가 모양입니다.
const [startTransition, Ispending] = Usetransition ({timeoutms : 100000});
우리는 폴백 디스플레이 전에 10 초를 통과 할 수 있습니다.이 시연에는 특히 실험을 위해 DevTools의 네트워크를 느리게 할 수 있다면이 데모에 적합합니다.
사용 방법은 다음과 같습니다. 더 많은 이미지를로드하는 버튼을 클릭하면 코드가 다음과 같습니다.
startTransition (() => { setPage ((p) => p 1); });
이 상태 업데이트는 내 GraphQL 클라이언트 Micro-GraphQL-React를 사용하여 새로운 데이터로드를 트리거합니다. 이는 서스펜스와 호환되며 쿼리가 진행 중일 때 우리에게 약속을합니다. 데이터가 반환되면 이미지가 사전로드되면 구성 요소가 렌더링하고 다시 매달려고합니다. 이 모든 일이 발생하지만 isPending
값은 사실이므로 기존 컨텐츠 상단에 로딩 스피너를 표시 할 수 있습니다.
인터넷 폭포를 피하십시오
이미지 사전 로딩이 진행되는 동안 React가 어떻게 렌더링을 차단할 수 있는지 궁금 할 것입니다. 위의 코드를 사용하여 다음을 수행 할 때 :
{images.map ((img) => (
... 그리고 그것에 렌더링되는 것<suspenseimage></suspenseimage>
, 첫 번째 이미지를 렌더링하고, 목록을 걸고, 첫 번째 이미지를 초과 한 다음 (현재 캐시에), 두 번째 이미지, 세 번째, 4 번째 등을 걸었습니다. 이전에 서스펜스에 대해 읽은 경우,이 모든 렌더링이 발생하기 전에 목록의 모든 이미지를 수동으로 사전로드 해야하는지 궁금 할 수 있습니다.
React는 서스펜스 세상에서 상황을 어떻게 밝히는 지에 대해 상당히 영리하기 때문에 걱정하거나 어색한 사전로드 할 필요가 없습니다. 반응이 우리의 구성 요소 트리를 가로 지르면 보류 중일 때 멈추지 않습니다. 대신, 그것은 우리의 구성 요소 트리의 다른 모든 경로를 계속 렌더링하려고합니다. 그렇습니다. 이미지 0을 렌더링하려고 할 때, 교수형이 발생하지만, React는 매달리기 전에 이미지 1을 n으로 렌더링하려고합니다.
새 이미지 세트가로드되면 전체 데모에서 네트워크 탭을 볼 수 있도록이를 볼 수 있습니다. 전체 이미지 버킷이 네트워크 목록에 즉시 표시되어 하나씩 구문 분석되며, 완료되면 결과를 화면에 표시해야합니다. 이 효과를 실제로 증폭 시키려면 네트워크 속도를 "빠른 3G"로 줄일 수 있습니다.
재미를 위해, 우리는 반응이 우리의 구성 요소를 렌더링하고 구성 요소 트리의 모든 경로를 가로지 않기 전에 캐시에서 각 이미지를 수동으로 읽음으로써 서스펜스가 이미지를 가로 지르도록 강요 할 수 있습니다.
images.foreach ((img) => imgcache.read (img));
나는 이것을 설명하기 위해 데모를 만들었습니다. 새 이미지 세트를로드 할 때 네트워크 탭을 보면 네트워크 목록에 순서대로 추가 된 것을 볼 수 있습니다 (그러나 네트워크 속도를 늦추면이를 실행 하지 마십시오 ).
지연된 교수형
서스펜스를 사용할 때는 하나의 추론을 기억해야합니다. 렌더링과 구성 요소 트리의 하위 레벨에서 가능한 한 늦게 매달아야합니다. 일부 렌더링 된 이미지를 렌더링하는 경우<imagelist></imagelist>
, 각 이미지가 자체 구성 요소에 매달려 있으므로 React가 다른 이미지를 차단하지 않도록 React가 별도로 액세스 할 수 있으므로 폭포가 발생합니다.
이 규칙의 데이터로드 버전은 실제로 필요한 구성 요소에 의해 데이터를 가능한 한 많이로드해야한다는 것입니다. 즉, 구성 요소에서 다음을 피해야합니다.
const {data1} = useuspensequery (query1, vars1); const {data2} = useuspensequery (query2, vars2);
우리가 이것을 피하고 싶은 이유는 쿼리 하나가 매달려 두 개를 쿼리하여 폭포를 일으키기 때문입니다. 이것이 피할 수없는 경우, 매달리기 전에 두 쿼리를 수동으로 예압해야합니다.
데모
다음은 저의 헌신에 대한 시연입니다. 위에서 연결 한 데모와 동일합니다.
데모를 열고 개발 도구를 열면 DevTools 네트워크 탭에 표시된 비활성화 된 캐시 상자를 선택 취소하지 마십시오. 그렇지 않으면 전체 데모를 중단합니다.
코드는 이전에 보여준 코드와 거의 동일합니다. 데모의 한 가지 개선은 캐시 읽기 메소드에 다음 줄이 있다는 것입니다.
settimeout (() => resolve ({}), 7000);
모든 이미지를 잘로드하지만 실제 생활에서는 이미지 뒤에 이미지 뒤에 한두 가지가 천천히로드되기 때문에 렌더링을 무기한으로 차단하고 싶지 않을 수도 있습니다. 그래서 잠시 후 우리는 이미지가 준비되지 않았더라도 녹색 불을냅니다. 사용자는 이미지 또는 두 번의 플래시를 볼 수 있지만 소프트웨어 동결의 좌절을 견뎌내는 것보다 낫습니다. 또한 7 초가 너무 길지만이 데모의 경우 사용자가 DevTools의 네트워크를 늦추어 서스펜스 기능을보다 명확하고 희망적으로 지원할 수 있다고 가정합니다.
데모에는 Precache 이미지 확인란도 있습니다. 기본적으로 선택되지만 정상 사용을 선택 취소 할 수 있습니다.<img alt="React 서스펜스가있는 사전 캐싱 이미지" >
태그 교체<suspenseimage></suspenseimage>
구성 요소, 서스펜스 버전을 "정상 반응"과 비교하려면 (결과가 나타날 때 확인하지 마십시오. 그렇지 않으면 전체 UI가 매달려 폴백을 렌더링 할 수 있습니다).
마지막으로 Codesandbox와 마찬가지로 일부 상태는 때때로 동기화되지 않을 수 있으므로 상황이 이상하거나 손상되기 시작하면 새로 고침 버튼을 클릭하십시오.
여러 가지 잡다한
이 데모를 정리할 때 실수로 큰 실수를했습니다. 브라우저가 다운로드 한 이미지를 캐시하기 때문에 데모가 효과를 잃는 것을 원하지 않습니다. 따라서 캐시 차단기를 사용하여 모든 URL을 수동으로 수정합니다.
const [cachebuster, setcachebuster] = usestate (initial_time); const {data} = useuspensequery (get_images_query, {page}); const images = data.allbooks.books.map ( (b) => b.smallimage`? cachebust = $ {cachebuster}` );
Initial_Time은 모듈 레벨 (즉, 전 세계)에서 정의됩니다.
const initial_time = 새 날짜 ();
내가 왜 이것을하지 않았는지 궁금하다면 :
const [cachebuster, setcachebuster] = usestate (new date ());
... 이것은 끔찍하고 끔찍한 결과를 초래할 수 있기 때문입니다. 첫 번째 렌더링에서 이미지는 렌더링을 시도합니다. 캐시는 교수형을 일으키고 반응을 취소하고 렌더링을 취소하고 우리의 폴백을 표시합니다. 모든 약속이 구문 분석되면 RECT는 렌더링을 다시 시작하려고 시도하고 초기 소송 호출은 재현됩니다 . 즉, 다음을 의미합니다.
const [cachebuster, setcachebuster] = usestate (new date ());
... 새로운 초기 값으로 다시 실행하여 새로운 이미지 URL 세트가 발생하여 다시 무기한으로 매달릴 것입니다. 구성 요소는 실행되지 않으며 Codesandbox 데모는 실행을 중단합니다 (디버깅을 실망시킵니다).
이것은이 특정 데모의 고유 한 요구 사항으로 인한 이상한 특별한 문제인 것처럼 보이지만 더 큰 교훈이 있습니다. 렌더링은 순수해야하며 부작용이 없습니다. RECT는 구성 요소를 여러 번 다시 렌더링하려고 시도 할 수 있어야하며 (동일한 초기 소품이 주어진) 다른 쪽 끝에서 동일한 정확한 상태를 얻어야합니다.
위 내용은 React 서스펜스가있는 사전 캐싱 이미지의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

Google Fonts가 새로운 디자인 (트윗)을 출시 한 것을 볼 수 있습니다. 마지막 큰 재 설계와 비교할 때 이것은 훨씬 더 반복적 인 느낌이 듭니다. 차이를 간신히 말할 수 있습니다

프로젝트에 카운트 다운 타이머가 필요한 적이 있습니까? 그런 것은 플러그인에 도달하는 것이 당연하지만 실제로는 훨씬 더 많습니다.

새로운 프로젝트가 시작될 때, Sass 컴파일은 눈을 깜박이게합니다. 특히 BrowserSync와 짝을 이루는 경우 기분이 좋습니다.

타탄은 일반적으로 스코틀랜드, 특히 세련된 킬트와 관련된 패턴의 천입니다. tartanify.com에서 우리는 5,000 개가 넘는 타탄을 모았습니다

Inline-Template 지시문을 사용하면 기존 WordPress 마크 업에 대한 진보적 인 향상으로 풍부한 VUE 구성 요소를 구축 할 수 있습니다.

Lea Verou의 기능 목록을 주시 한 한 가지는 Conic-Gradient () Polyfill이 마지막 항목이었습니다.
