Alpine.js는 자바스크립트 라이브러리로 HTML Driven Development 방식의 개발을 위한 인라인 개발을 지원한다. 18개의 attributes, 9개의 properties, 그리고 3개의 메소드를 가지고 있으며 매우 간단하고, 가볍다.

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.13.3/dist/cdn.min.js"></script>

Attributes(Directive)

x-data:

Alpine의 모든 시작점은 x-data이다. x-data는 HTML의 반응형 데이터를 만든다.

<div x-data="{foo: 'bar'}">
  <span x-text="foo"><!-- "bar" --></span>
  <div x-data="{foo: 'bob'}">
    <span x-text="foo"><!-- "bob" --></span>
  </div>
</div>

x-bind:

x-bind는 HTML의 속성들을 자바스크립트의 요소들로 바꾼다.

<div x-data="{ placeholder: 'Type here...' }">
  <input type="text" x-bind:placeholder="placeholder">
</div>
<div x-data="{ placeholder: 'Type here...' }">
  <input type="text" :placeholder="placeholder">
</div>

x-on:

x-on을 사용하면 전달된 DOM 이벤트에소 코드를 쉽게 실행 가능하다.

<button x-on:click="alert('Hello World!')">Say Hi</button>
<button @click="alert('Hello World!')">Say Hi</button>

x-text:

x-text는 텍스트 컨텐츠를 주어진 결과에 따라 보여준다.

<div x-data="{ username: 'calebporzio' }">
  Username: <strong x-text="username"></strong>
</div>

x-html:

x-html은 innerHTML를 주어진 결과에 따라 보여준다.

<div x-data="{ username: '<strong>calebporzio</strong>' }">
  Username: <span x-html="username"></span>
</div>

x-model:

x-model은 input에 대한 값을 x-data에 저장을 한다.

<div x-data="{ message: '' }">
  <input type="text" x-model="message">
  <span x-text="message">
</div>

x-show:

x-show는 Alpine에서 가장 유용한것 중에 하나이다. 이것은 DOM요소를 숨기고 보여주는데 매우 효과적이다.

<div x-data="{ open: false }">
  <button x-on:click="open = ! open">Toggle Dropdown</button>
  <div x-show="open">
    Dropdown Contents...
  </div>
</div>

x-transition:

x-transition을 이용하면 간단한 애니메이션을 만들수가 있다. TailwindCSS를 이용하여 조종할 수도 있다.

<div x-data="{ open: false }">
  <button @click="open = ! open">Toggle</button>
  <span x-show="open" x-transition>
    Hello 👋
  </span>
</div>
<div x-data="{ open: false }">
  <button @click="open = ! open">Toggle</button>
  <div
    x-show="open"
	x-transition:enter="transition ease-out duration-300"
	x-transition:enter-start="opacity-0 scale-90"
	x-transition:enter-end="opacity-100 scale-100"
	x-transition:leave="transition ease-in duration-300"
	x-transition:leave-start="opacity-100 scale-100"
	x-transition:leave-end="opacity-0 scale-90"
  >
    Hello 👋
  </div>
</div>

x-for:

x-for은 DOM요소가 이터럴 할 수 있게 해준다. 그리고 x-for은 무조건 template태그 안에 하나의 요소만 선언 가능하다.

<ul x-data="{ colors: ['Red', 'Orange', 'Yellow'] }">
  <template x-for="color in colors">
	<li x-text="color"></li>
  </template>
</ul>

x-if:

x-ifx-show와 비슷한 역활을 하지만 CSS를 바꾸는 것과는 다르게 요소를 제거 하거나 추가한다. 또한 template태그 안에 하나의 요소만 선언 가능하고 x-transition은 사용이 불가능하다.

<template x-if="open">
  <div>Contents...</div>
</template>

x-init:

생성자이고 다양하게 활용가능

<div x-init="console.log('I\'m being initialized!')"></div>

x-effect:

x-effect는 의존성중 하나가 바뀔때 어떻게 바뀌는지 볼 수 있다.

<div x-data="{ label: 'Hello' }" x-effect="console.log(label)">
  <button @click="label += ' World!'">Change Message</button>
</div>

x-ref:

x-ref$ref와 같이 쓰이며 getElementById, querySelector와 같은것을 대체한다.

<button @click="$refs.text.remove()">Remove Text</button>
<span x-ref="text">Hello 👋</span>

x-cloak:

Alpine.js를 사용하다보면 페이지가 로드된 후 Alpine이 로드되기 전에 초기화되지 않은 템플릿을 볼 때 깜빡거리는 현상이 있을때 사용한다.

<style>
  [x-cloak] {
  display: none !important;
  }
</style>
 
<span x-cloak x-show="false">
  This will not 'blip' onto screen ay any point
</span>

x-ignore:

x-init, x-data를 가지고 있는 요소중 Alpine을 사용하고 싶지 않다면 사용한다.

<div x-data="{label: 'From Alpine'}">
  <div x-ignore>
    <span x-text="label"></span>
  </div>
</div>

x-id:

<div x-id="['text-input']">
    <label :for="$id('text-input')">Username</label>
    <!-- for="text-input-1" -->
    <input type="text" :id="$id('text-input')">
    <!-- id="text-input-1" -->
</div>
 
<div x-id="['text-input']">
    <label :for="$id('text-input')">Username</label>
    <!-- for="text-input-2" -->
    <input type="text" :id="$id('text-input')">
    <!-- id="text-input-2" -->
</div>

x-teleport:

x-teleport는 Alpine 템플릿을 DOM의 다른 부분으로 페이지 전체를 옮긴다.

<body>
  <div x-data="{ open: false }">
    <button @click="open = ! open">Toggle Modal</button>
      <template x-teleport="body">
        <div x-show="open">
          Modal contents...
        </div>
      </template>
    </div>
 
  <div>Some other content placed AFTER the modal markup.</div>
    ...
</body>

x-modelable:

x-modelable을 사용하면 Alpine 속성을 x-model의 대상으로 노출시킬 수 있다.

<div x-data="{ number: 5 }">
  <div x-data="{ count: 0 }" x-modelable="count" x-model="number">
    <button @click="count++">Increment</button>
  </div>
   
  Number: <span x-text="number"></span>
</div>

Properties(Magics)

$store:

$store을 사용하면 Alpine.store를 사용하여 글로벌 stores에 편리하게 접근 가능하다.

<button x-data @click="$store.darkMode.toggle()">
  Toggle Dark Mode
</button>
 
<div x-date :class="$store.darkMode.on && 'bg-black'">
  <!-- ... -->
</div>
 
<script>
  document.addEventListener('alpine:init', () => {
    Alpine.store('darkMode', {
      on: false,
      
      toogle() {
        this.on  = !this.on
      }
    }) 
  })
</script>

$el:

$el은 현재의 DOM노드를 조종할 수 있다.

<button @click="$el.innerHTML = 'Hello World!'">
  Replace me with "Hello World!"
</button>

$dispatch:

$dispatch는 브라우저의 이벤트를 전달하는 유용한 숏컷이다.

<div @notify="alert($event.detail.message)">
  <button @click="$dispatch('notify', { message: 'Hello World!' })">
    Notify
  </button>
</div>
  • $dispatchelement.dispatchEvent(new CustomEvent())의 wrapper이다.
<!-- 🚫 Won't work -->
<div x-data>
  <span @notify="..."></span>
  <button @click="$dispatch('notify')">Notify</button>
</div>
 
<!-- ✅ Will work (because of .window) -->
<div x-data>
  <span @notify.window="..."></span>
  <button @click="$dispatch('notify')">Notify</button>
</div>
  • custom-event를 사용할 경우, 형제대신 조상의 요소를 보기 때문에 .window를 추가해줘야 형제의 요소를 볼 수 있다.

  • dispatch — Alpine.js (alpinejs.dev)

$watch:

$watch를 사용하면 컴포넌트의 속성을 볼 수 있다.

<div x-data="{ foo: { bar: 'baz' }}" 
	 x-init="$watch('foo.bar', value => console.log(value))">
    <button @click="foo.bar = 'bob'">Toggle Open</button>
</div>
  • button를 누르면 foo.bar은 “bob”으로 바뀌고 콘솔에 “bob”이 출력된다.
<div x-data="{ open: false }" 
	 x-init="$watch('open', (value, oldValue) => 
	 console.log(value, oldValue))">
    <button @click="open = ! open">Toggle Open</button>
</div>

$refs:

$refsx-ref으로 연결된 컴포넌트를 검색해 조작할 수 있다. document.querySelector보다 간결하고 범위가 지정된 대안으로 사용된다.

<button @click="$refs.text.remove()">Remove Text</button>
<span x-ref="text">Hello 👋</span>

$nextTick:

$nextTick은 DOM이 업데이트된 후에 어떠한 작업을 수행하고 싶을때 사용한다.

<div x-data="{ title: 'Hello' }">
  <button
	@click="
	  title = 'Hello World!';
	  $nextTick(() => { console.log($el.innerText) });
	"
	x-text="title"
  ></button>
</div>
  • $nextTick은 프로미스를 반환함으로 $nextTick를 사용하여 비동기 함수를 DOM이 업데이트 될때까지 정지 시킬수 있다. ( await )

  • nextTick — Alpine.js (alpinejs.dev)

$root:

$root은 DOM 트리에서 x-data를 포함한 가장 가까운 루트요소를 찾는다.

<div x-data data-message="Hello World!">
  <button @click="alert($root.dataset.message)">Say Hi</button>
</div>

$data:

$data는 현재 Alpine 데이터의 범위에 접근을 위해 사용된다. 대부분의 경우 x-data="{message: 'Hello World!}"x-text="message"와 같은 방법을 사용하지만 다른 함수에 모든 범위를 캡슐화하는 객체를 전달할때가 필요할 수도 있다.

<div x-data="{ greeting: 'Hello' }">
  <div x-data="{ name: 'Caleb' }">
    <button @click="sayHello($data)">Say Hello</button>
  </div>
</div>
 
<script>
  function sayHello({ greeting, name }) {
    alert(greeting + ' ' + name + '!')
  }
</script>

$id:

$id는 요소의 ID를 생성한다.

<input type="text" :id="$id('text-input')">
<!-- id="text-input-1" -->
<input type="text" :id="$id('text-input')">
<!-- id="text-input-2" -->
  • x-id를 사용해여 더 유연하게 사용가능하다.
<div x-id="['text-input']">
  <label :for="$id('text-input')"> <!-- "text-input-1" -->
  <input type="text" :id="$id('text-input')"> <!-- "text-input-1" -->
</div>
 
<div x-id="['text-input']">
  <label :for="$id('text-input')"> <!-- "text-input-2" -->
  <input type="text" :id="$id('text-input')"> <!-- "text-input-2" -->
</div>

Methods(Globals)

Alpine.data:

<div x-data="dropdown">
  <!-- ... -->
</div>
 
 
<script>
  document.addEventListener('alpine:init', () => {
    Alpine.data('dropdown', () => ({
      open: false,
 
      toggle() {
        this.open = ! this.open
      }
    }))
  })
</script>

Alpine.store:

<script>
  document.addEventListener('alpine:init', () => {
    Alpine.store('darkMode', {
      on: false,
      
      toggel() {
        this.on = ! this.on
      }
    })
  })
</script>

Alpine.bind:

Apline.bind()를 사용하면 x-bind 객체를 재사용가능하게 할 수 있다.

<button x-bind="SomeButton"></button>
 
<script>
  document.addEventListener('alpine:init', () => {
    Alpine.bind('SomeButton', () => ({
      type: 'button',
      
      '@click'() {
        this.doSomething()
      },
      
      ':disabled'() {
        return this.shouldDisable
      },
    }))
  })
</script>