당신의 머릿속에서 날씬하게 컴파일하기 ({# 만약})
우리의 관점이 일치하는지 확인하기 위해서, 우선ifblock이 어떻게 일을 하는지 설명해 봅시다.
{#if}
블록컨텐트를 조건부로 표시하려면
{#if}
블록을 사용하여 포장할 수 있습니다.{#if condition}
<div>Conditionally rendered content</div>
{/if}
만약 condition
가 진실이라면, 너는 볼 수 있을 것이다 <div>Conditionally rendered content</div>
. 그렇지 않으면 너는 아무것도 볼 수 없을 것이다.JavaScript와 마찬가지로 Svelte에서
else
및 else if
를 사용하여 여러 조건을 테스트할 수도 있습니다.{#if condition_a}
<div>Rendered due to condition_a</div>
{:else if condition_b}
<div>Rendered due to condition_b</div>
{:else}
<div>Otherwise</div>
{/if}
Svelte의 상호작용 강좌를 방문하여 {#if}
logic block에 대한 더 많은 정보를 얻을 수 있습니다.바닐라 JS
그렇다면 우리는 어떻게 아무런 틀도 없는 상황에서
{#if}
논리를 실현할 수 있을까?앞에서 말한 바와 같이, 우리는 프레임 도움말 없이 요소를 만드는 방법을 보았다.
구현 if 블록
구현
{#if}
논리 블록은 다음과 같습니다.function createElementsIfConditionA() {
// code to create `<div>Rendered due to condition_a</div>`
}
function createElementsIfConditionB() {
// code to create `<div>Rendered due to condition_b</div>`
}
function createElementsElse() {
// code to create `<div>Otherwise</div>`
}
function createIfBlock() {
if (condition_a) {
createElementsIfConditionA();
} else if (condition_b) {
createElementsIfConditionB();
} else {
createElementsElse();
}
}
condition_a
와 condition_b
는 동적일 수 있다. 이것은 조건에 변화가 발생하면 우리는 다시 호출해야 한다는 것을 의미한다createIfBlock
.그 전에 만들어진 요소를 삭제해야 합니다.이것은 이전에 어떤 조건을 만족시켰는지, 그리고 이전에 어떤 요소를 만들었는지에 달려 있다.
그러면 이러한 정보를 변수에 저장합니다.
function destroyElementsIfConditionA() {
// code to destroy `<div>Rendered due to condition_a</div>`
}
function destroyElementsIfConditionB() {
// code to destroy `<div>Rendered due to condition_b</div>`
}
function destroyElementsElse() {
// code to destroy `<div>Otherwise</div>`
}
let previousDestroy;
function getPreviousDestroy() {
if (condition_a) {
previousDestroy = destroyElementsIfConditionA;
} else if (condition_b) {
previousDestroy = destroyElementsIfConditionB;
} else {
previousDestroy = destroyElementsElse;
}
}
function createIfBlock() {
// ...
getPreviousDestroy();
}
따라서 조건이 변경되면 이전에 생성한 요소를 제거하고 새 요소를 생성합니다.function updateIfBlock() {
// if `condition_a` or `condition_b` changed
if (conditionChanged) {
previousDestroy();
createIfBlock();
}
}
단, 조건이 바뀌지 않았더라면if 블록의 내용에 변화가 생겼습니다. 예를 들어 value_a
, value_b
또는 value_else
다음 코드에 변화가 생겼습니다.{#if condition_a}
<div>{ value_a }</div>
{:else if condition_b}
<div>{ value_b }</div>
{:else}
<div>{ value_else }</div>
{/if}
그런 다음 요소를 업데이트하는 방법을 알아야 합니다.function updateElementsIfConditionA() {
// code to update `<div>{ value_a }</div>`
}
function updateElementsIfConditionB() {
// code to update `<div>{ value_b }</div>`
}
function updateElementsElse() {
// code to update `<div>{ value_else }</div>`
}
function updateIfBlock() {
// if `condition_a` or `condition_b` changed
if (conditionChanged) {
previousDestroy();
createIfBlock();
} else {
if (condition_a) {
updateElementsIfConditionA();
} else if (condition_b) {
updateElementsIfConditionB();
} else {
updateElementsElse();
}
}
}
마지막으로 요소를 제거하려면 전체 블록{#if}
을 제거할 때 사용할 수 있습니다previousDestroy
. 요소를 작성하는 기준에 기반하기 때문입니다.function destroyIfBlock() {
previousDestroy();
}
여기createIfBlock
,updateIfBlock
와destroyIfBlock
가 있습니다.if (condition)
논리가 createIfBlock
, getPreviousDestroy
와 updateIfBlock
사이에 분산되어 있기 때문에 매우 서투르게 보인다.그래서 이걸 재구성해 봅시다.코드를 바꿔서 더 깨끗하게 합시다.✨
코드 재구성
각 논리적 분기마다 요소를 생성, 업데이트 및 제거할 수 있습니다.첫 번째 조건의 구분에 대해 우리는 다음과 같은 것을 가지고 있다.
createElementsIfConditionA
updateElementsIfConditionA
destroyElementsIfConditionA
각 조건부 분기의 작업을 그룹화할 수 있으며 각 작업마다 인터페이스가 동일합니다
{ create(){}, update(){}, destroy(){} }
.const operationConditionA = {
create: createElementsIfConditionA,
update: updateElementsIfConditionA,
destroy: destroyElementsIfConditionA,
};
const operationConditionB = {
create: createElementsIfConditionB,
update: updateElementsIfConditionB,
destroy: destroyElementsIfConditionB,
};
const operationConditionElse = {
create: createElementsElse,
update: updateElementsElse,
destroy: destroyElementsElse,
};
이제 동일한 인터페이스가 있기 때문에 다음과 같은 조건으로 작업을 선택할 수 있습니다.function getOperation() {
if (condition_a) {
return operationConditionA;
} else if (condition_b) {
return operationConditionB;
} else {
return operationConditionElse;
}
}
여기서 우리는 우리의 createIfBlock
, updateIfBlock
와 destroyIfBlock
를 다시 쓸 수 있다.let currentOperation = getOperation();
function createIfBlock() {
currentOperation.create();
}
function updateIfBlock() {
const previousOperation = currentOperation;
currentOperation = getOperation();
// if (conditionChanged)
if (currentOperation !== previousOperation) {
previousOperation.destroy();
currentOperation.create();
} else {
currentOperation.update();
}
}
function destroyIfBlock() {
currentOperation.destroy();
}
조건이 변경되었는지 확인하기 위해서 우리는 이 조작을 계산하고 이전의 조작과 비교하여 그것이 변경되었는지 확인할 수 있다.컴파일된 JS
Svelte가 출력 자바스크립트로
{#if}
를 어떻게 컴파일했는지 보여 줍니다.<script>
let loggedIn = false;
function toggle() {
loggedIn = !loggedIn;
}
</script>
{#if loggedIn}
<button on:click={toggle}>
Log out
</button>
{:else}
<button on:click={toggle}>
Log in
</button>
{/if}
Svelte REPL 출력 코드:
/* App.svelte generated by Svelte v3.25.1 */
// ...
function create_else_block(ctx) {
// ...
return {
c() { /* ... */ },
m(target, anchor) { /* ... */ },
p: noop,
d(detaching) { /* ... */ },
};
}
// (9:0) {#if loggedIn}
function create_if_block(ctx) {
// ...
return {
c() { /* ... */ },
m(target, anchor) { /* ... */ },
p: noop,
d(detaching) { /* ... */ },
};
}
function create_fragment(ctx) {
// ...
function select_block_type(ctx, dirty) {
if (/*loggedIn*/ ctx[0]) return create_if_block;
return create_else_block;
}
let current_block_type = select_block_type(ctx, -1);
let if_block = current_block_type(ctx);
return {
c() {
if_block.c();
if_block_anchor = empty();
},
m(target, anchor) {
if_block.m(target, anchor);
insert(target, if_block_anchor, anchor);
},
p(ctx, [dirty]) {
if (current_block_type === (current_block_type = select_block_type(ctx, dirty)) && if_block) {
if_block.p(ctx, dirty);
} else {
if_block.d(1);
if_block = current_block_type(ctx);
if (if_block) {
if_block.c();
if_block.m(if_block_anchor.parentNode, if_block_anchor);
}
}
},
i: noop,
o: noop,
d(detaching) {
if_block.d(detaching);
if (detaching) detach(if_block_anchor);
},
};
}
몇 가지 관찰 결과:관찰1: 만약에 Svelte의 컴파일 출력과 우리가 전에 발표한 JS 코드를 비교한다면 비슷한 점을 볼 수 있습니다.
create_else_block
와 create_if_block
이다.앞에서 설명한 바와 같이, 이 함수들은 모든 논리 지점에 DOM 세션을 구축하는 방법에 대한 설명 매뉴얼을 되돌려줍니다.operationConditionA
, operationConditionB
와 operationConditionElse
이다.create_fragment
함수를 사용하는지 확인하기 위해 우리는 select_block_type
함수를 가지고 있다.getOperation
과 유사하다.let current_block_type = select_block_type(ctx, -1);
let if_block = current_block_type(ctx);
if_block.c()
if_block.m(target, anchor)
if_block.p(ctx, dirty)
if_block.d(detaching)
{#if}
블록의 원소.p
(u p 날짜) 방법에서 current_block_type
가 변경되었는지 확인하고 변경되지 않으면 필요에 따라 호출if_block.p(ctx, dirty)
하여 업데이트합니다.if_block.d(1)
이전의 요소를 없애고 current_block_type
를 바탕으로 새로운 세션을 만들고 if_block.c()
와 if_block.m(...)
를 통해 요소를 만들고 불러옵니다.이것은 우리가 말한
previousOperation.destroy()
와 currentOperation.create()
또는 currentOperation.update()
와 유사하다.관찰2:
if_block_anchor
이후 삽입if_block
if_block_anchor = empty()
empty()
빈 텍스트 노드를 만듭니다.// https://github.com/sveltejs/svelte/blob/v3.25.1/src/runtime/internal/dom.ts#L56-L58
export function empty() {
return text('');
}
그리고 u p date 방법if_block_anchor
을 설치할 때if_block
를 사용합니다.if_block.m(if_block_anchor.parentNode, if_block_anchor)
그러면 이 추가 빈 텍스트 노드는 무엇을 합니까?추가 텍스트 노드
블록
{#if}
을 업데이트하고 세그먼트 블록 유형을 변경해야 한다는 것을 알았을 때 이전에 만든 요소를 제거하고 새로 만든 요소를 삽입해야 합니다.우리가 새로운 요소를 삽입할 때, 우리는 어디에 그것들을 삽입하는지 알아야 한다.
insertBefore
API를 사용하면 요소를 삽입할 노드를 지정할 수 있습니다.그래서 지금 질문을 회피하고 있습니다. 어느 노드입니까?정답은 구성 요소에 기록된 위치에 따라 달라집니다
{#if}
.가능한 경우는 4가지입니다.1.
{#if}
블록 뒤에 원소가 있다{#if condition}
<div />
{/if}
<span />
Svelte REPL 보실 거예요.
<span />
노드if_block.m(span.parentNode, span)
When the
{#if}
condition changes,{#if}
block will replace and insert new elements before the<span />
element.
2.
{#if}
블록은 마지막 하위 블록이고 {#if}
블록에는 상위 블록이 있음<div>
{#if condition}
<div />
{/if}
</div>
Svelte REPL 보실 거예요.
{#if}
블록을 부 노드<div />
에 삽입하고 null
이전에 삽입한다.null
를 insertBefore
에 전달하면 부가 원소를 마지막 하위 원소로 한다)if_block.m(div, null);
When the
{#if}
condition changes,{#if}
block will replace and insert new elements as the last children of the parent<div />
element.
3.
{#if}
블록은 마지막 하위 항목이고 {#if}
블록은 상위 항목이 없습니다.{#if condition}
<div />
{/if}
Svelte REPL 보실 거예요.
anchor
요소 만들기 anchor
요소를 삽입한다.{#if}
요소 앞에 {#if}
블록을 삽입합니다.if_block.m(if_block_anchor.parentNode, if_block_anchor);
When the
{#if}
condition changes,{#if}
block will replace and insert new elements before theanchor
element.
그런데 왜요?
섬세한 조립품은 어디서나 사용할 수 있기 때문이다.
다음 장면을 살펴보겠습니다.
<!-- A.svelte -->
{#if condition}
<div id="a" />
{/if}
<!-- B.svelte -->
<div id="b" />
<!-- App.svelte -->
<script>
import A from './A.svelte';
import B from './B.svelte';
</script>
<div id="parent">
<A />
<B />
</div>
anchor
에서 A.svelte
블록은 마지막 하위 블록이고 그 뒤에는 동급 원소가 없다.우선 우리
{#if}
원소가 없다고 가정하자.anchor
가 condition
에서 false
로 바뀌었을 때 Svelte는 새 요소true
를 부모 요소에 삽입해야 합니다.<div id="a">
블록 뒤에 다음 원소도 없고 {#if}
원소도 없기 때문에 우리는 anchor
블록 앞에 삽입해야 한다.여기서 null
는 부모 요소<div id="a" />
의 마지막 하위 요소로 삽입됩니다.야, 우리가 벌레 한 마리를 발견했어!내부 원소<div id="parent">
가 <A />
뒤에 나타납니다!<div id="parent">
<div id="b"></div>
<div id="a"></div> <!-- newly inserted element -->
</div>
우리는 <B />
원소를 첨가함으로써 이런 상황이 발생하는 것을 방지할 수 있다.anchor
가 condition
인 경우 DOM은 다음과 같습니다.<div id="parent">
<#text /> <!-- an empty text node, not visible to the user -->
<div id="b"></div>
</div>
false
회전condition
할 때 우리는 true
원소 앞에 <div id="a" />
:<div id="parent">
<div id="a"></div> <!-- newly inserted element -->
<#text /> <!-- an empty text node, not visible to the user -->
<div id="b"></div>
</div>
네, 저희는 anchor
와 <A />
의 질서를 유지하고 있습니다.🎉 !<B />
블록의 anchor
원소는 an anchor to a ship와 유사하다. "이곳은 {#if}
블록이 마땅히 {#if}
해야 할 곳!"4.
insertBefore()
블록 뒤에 다른 논리 블록 연결마지막 장면.
{#if}
블록 뒤에 다른 논리 블록 연결:{#if condition}
<div id="a" />
{/if}
{#if condition2}
<div id="b" />
{/if}
두 번째{#if}
의 막힘 조건은 {#if}
또는true
일 수 있다.이것은 false
거기에 있을 수도 있고 없을 수도 있다는 것을 의미한다.따라서 변경
<div id="b" />
할 때 어디에 삽입해야 하는지<div id="a" />
를 알아야 한다. 우리는 첫 번째condition
블록 다음, 두 번째anchor
블록 앞에 {#if}
요소를 삽입해야 한다.폐막사
우리는 Svelte가
{#if}
블록을 어떻게 컴파일하는지, 그리고 {#if}
블록이 필요로 하는 anchor
요소의 방식과 원인을 소개했다.날씬함에 대해 더 알고 싶다면.
다음 부분을 준비한 후에 다음 글은
{#if}
논리 블록에 관한 것이다.
Reference
이 문제에 관하여(당신의 머릿속에서 날씬하게 컴파일하기 ({# 만약})), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/tanhauhau/compile-svelte-in-your-head-if-1g6b텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)