Svelte

[Svelte]Action과 use 지시자

DevStory 2022. 8. 5.

Action과 use 지시자

Svlete에서 DOM 요소가 DOM에 추가될 때 실행되는 함수를 액션(Action)이라고 합니다. 주로 DOM 요소의 속성을 변경하는 경우 사용됩니다.

 

예를 들어, 특정 DOM 요소를 포커싱 처리하거나 style을 적용하는 작업에서 액션을 사용할 수 있습니다.

 

DOM 요소에 액션을 적용하기 위해서는 use 지시자를 사용합니다.

<script>
  const inputElementOnFocus = (element) => {
    element.focus();
  }
</script>

<input type="text" use:inputElementOnFocus />

use 지시자에는 DOM에 추가될 때 실행되는 함수를 지정하고 함수의 인자로 DOM 노드가 전달됩니다.


예제 1. input 태그 포커싱 및 placeholder

다음 예제는 "input 태그 활성화" 버튼을 클릭하면, input 태그가 DOM에 그려지면서 포커싱 및 placeholder가 설정되어야 합니다. "input 태그 비활성화" 버튼을 클릭하면 input 태그가 DOM에서 사라집니다.

<script>
  let strValue = '';    
  let isInputElementView = false;

  const handleClick = (param) => {
    isInputElementView = param;
  }

  const inputElementOnFocus = (element) => {
    element.setAttribute("placeholder", "값을 입력하세요.");
    element.focus();
  }
</script>

<button on:click={() => handleClick(true)}>
  input 태그 활성화
</button>

<button on:click={() => handleClick(false)}>
  input 태그 비활성화
</button>

{#if isInputElementView}
<div>
  <input type="text" bind:value={strValue} use:inputElementOnFocus/>
</div>
{/if}

[실행 결과]

input 태그의 use 지시자로 inputElementOnFocus() 함수를 액션 함수로 등록합니다. inputElementOnFocus() 함수에는 DOM 노드가 전달되고 DOM 노드의 속성을 설정하는 setAttribute() 함수와 포커싱 처리하는 focus() 함수를 호출합니다.


매개변수 추가

액션으로 등록된 함수에는 DOM 노드 이외에도 두 번째 매개변수를 사용할 수 있습니다. 즉, 개발자가 액션에 원하는 값을 전달할 수 있습니다.

 

다음 예제는 input 태그의 placeholder 문구를 매개변수로 전달합니다.

<script>
  let strValue = '';    
  let isInputElementView = false;

  const handleClick = (param) => {
    isInputElementView = param;
  }

  const inputElementOnFocus = (element, param) => {
    element.setAttribute("placeholder", param.placeholderValue);
    element.focus();
  }
</script>

<button on:click={() => handleClick(true)}>
  input 태그 활성화
</button>

<button on:click={() => handleClick(false)}>
  input 태그 비활성화
</button>

{#if isInputElementView}
<div>
  <input type="text" 
         bind:value={strValue} 
         use:inputElementOnFocus={{placeholderValue: "값을 입력하세요."}}/>
</div>
{/if}

만약, 객체가 아닌 단일 값을 전달하는 경우에는 다음 소스 코드처럼 중괄호를 한 번만 사용합니다.

<input type="text" 
       bind:value={strValue} 
       use:inputElementOnFocus={"값을 입력하세요."}/>

매개변수의 값이 변경

액션 함수에 매개변수를 전달하는 경우 몇 가지 문제점이 존재합니다.

1. 매개변수의 값이 변경된 경우 변경된 값이 적용되지 않습니다.

2. 해당 요소가 DOM에서 제거될 때, style이 제거되지 않을 수 있습니다.

 

다음 예제를 통해 문제점을 알아봅시다. 다음 예제는 textarea에 입력한 값을 input 태그의 placeholder로 설정합니다.

<script>
  let strValue = '';  
  let txtValue = '';  
  let isInputElementView = false;

  const handleClick = (param) => {
    isInputElementView = param;
  }

  const inputElementOnFocus = (element, param) => {
    element.setAttribute("placeholder", param);
    element.focus();
  }
</script>

<button on:click={() => handleClick(true)}>
  input 태그 활성화
</button>

<button on:click={() => handleClick(false)}>
  input 태그 비활성화
</button>

{#if isInputElementView}
<div>
  <input type="text" bind:value={strValue} use:inputElementOnFocus={txtValue}/>
</div>
{/if}
<div>
  <p>▼ placeholder 값 입력</p>
  <textarea type="text" bind:value={txtValue}/>
</div>

[실행 결과]

textarea에서 입력한 값이 input 태그의 placeholder에 적용되지 않고 input 태그를 비활성화 후 다시 활성화하면 적용됩니다. 즉, input 태그가 활성화된 상태에서는 placeholder가 변경되지 않습니다.

 

Svelte에서는 고맙게도 이러한 작업을 처리할 수 있는 두 가지 함수를 제공합니다. 이 두 가지 함수는 액션 함수에서 사용할 수 있으며, update() 함수는 매개변수의 값이 변경되면 호출되고 destroy() 함수는 해당 요소가 DOM에서 제거될 때, 호출됩니다.

 

update() 함수와 destroy() 함수는 액션 함수의 return문에 적용합니다.

 

다음 예제는 input 태그가 활성화된 상태에서 textarea에 입력된 값이 input 태그의 placeholder에 적용되고 input 태그가 비활성화되면, 변수 txtValue의 값을 빈 값으로 할당합니다.

<script>
  let strValue = '';  
  let txtValue = '';  
  let isInputElementView = false;

  const handleClick = (param) => {
    isInputElementView = param;
  }

  const inputElementOnFocus = (element, param) => {
    element.focus();
    element.setAttribute("placeholder", param);
    return {
      update: (newParam) => {
        element.setAttribute("placeholder", newParam);
      },
      destroy: () => {
        txtValue = '';
      }
    }
  }
</script>

<button on:click={() => handleClick(true)}>
  input 태그 활성화
</button>

<button on:click={() => handleClick(false)}>
  input 태그 비활성화
</button>

{#if isInputElementView}
<div>
  <input type="text" bind:value={strValue} use:inputElementOnFocus={txtValue}/>
</div>
{/if}
<div>
  <p>▼ placeholder 값 입력</p>
  <textarea type="text" bind:value={txtValue}/>
</div>

[실행 결과]

반응형

댓글