ÿØÿà JFIF ÿá Exif MM * ÿÛ C
Server IP : 199.250.214.225 / Your IP : 3.145.66.126 Web Server : Apache System : Linux vps64074.inmotionhosting.com 3.10.0-1160.105.1.vz7.214.3 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : nicngo5 ( 1001) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /home/nicngo5/funds.upgrade.nicn.gov.ng/funds-upgraded/node_modules/alpinejs/ |
Upload File : |
# Alpine.js ![npm bundle size](https://img.shields.io/bundlephobia/minzip/alpinejs) ![npm version](https://img.shields.io/npm/v/alpinejs) [![Chat](https://img.shields.io/badge/chat-on%20discord-7289da.svg?sanitize=true)](https://alpinejs.codewithhugo.com/chat/) Alpine.js는 ì €ë ´í•œ 비용으로 Vue ë˜ëŠ” React와 ê°™ì€ ëŒ€ê·œëª¨ í”„ë ˆìž„ì›Œí¬ì˜ ë°˜ì‘성 ë° ì„ ì–¸ì íŠ¹ì„±ì„ ì œê³µí•©ë‹ˆë‹¤. DOMì„ ìœ ì§€í•˜ê³ ì ì ˆí•œ ë™ìž‘ì„ ì‚¬ìš©í• ìˆ˜ 있습니다. JavaScriptìš© [Tailwind](https://tailwindcss.com/)ë¼ê³ ìƒê°í•˜ì‹œë©´ ë©ë‹ˆë‹¤. > ì°¸ê³ : ì´ ë„구는 [Vue](https://vuejs.org/) (ë° [Angular](https://angularjs.org/))ì—ì„œ ì˜ê°ì„ 받았습니다. ì €ëŠ” ì´ëŸ¬í•œ ë„êµ¬ì˜ ê°œë°œìžë“¤ì´ ì›¹ì— ê¸°ì—¬í•œ ê²ƒì— ëŒ€í•´ 대단히 ê°ì‚¬í•˜ê³ 있습니다. ## 설치 **CDN 사용:** `<head>`섹션 ëì— ë‹¤ìŒ ìŠ¤í¬ë¦½íŠ¸ë¥¼ 추가합니다. ```html <script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script> ``` 그것으로 ë입니다. ìžì²´ì 으로 초기화ë©ë‹ˆë‹¤. 프로ë•ì…˜ í™˜ê²½ì˜ ê²½ìš° ìµœì‹ ë²„ì „ì˜ ì˜ˆìƒì¹˜ 못한 ë¬¸ì œë¥¼ 방지하기 위해 ë§í¬ì— íŠ¹ì • ë²„ì „ 번호를 ì„¤ì •í•˜ëŠ” ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤. 예를 들어 `2.8.2` ë²„ì „ 사용: ```html <script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.8.2/dist/alpine.min.js" defer></script> ``` **NPM 사용:** NPMì—ì„œ 패키지를 설치합니다. ```js npm i alpinejs ``` 스í¬ë¦½íŠ¸ì— ë‹¤ìŒ ë‚´ìš©ì„ ì¶”ê°€í•˜ì„¸ìš”. ```js import 'alpinejs' ``` **IE11ì„ ì§€ì›í•˜ë ¤ë©´** ë‹¤ìŒ ìŠ¤í¬ë¦½íŠ¸ë¥¼ 사용하세요. ```html <script type="module" src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js"></script> <script nomodule src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine-ie11.min.js" defer></script> ``` ìœ„ì˜ íŒ¨í„´ì€ [module/nomodule 패턴](https://philipwalton.com/articles/deploying-es2015-code-in-production-today/)으로 ìµœì‹ ë¸Œë¼ìš°ì €ì™€ IE11 ë° ê¸°íƒ€ ë ˆê±°ì‹œ 브ë¼ìš°ì €ì—ì„œ ìžë™ìœ¼ë¡œ 로드ë©ë‹ˆë‹¤. ## 사용법 *ë“œë¡ë‹¤ìš´/모달* ```html <div x-data="{ open: false }"> <button @click="open = true">Open Dropdown</button> <ul x-show="open" @click.away="open = false" > Dropdown Body </ul> </div> ``` *íƒ* ```html <div x-data="{ tab: 'foo' }"> <button :class="{ 'active': tab === 'foo' }" @click="tab = 'foo'">Foo</button> <button :class="{ 'active': tab === 'bar' }" @click="tab = 'bar'">Bar</button> <div x-show="tab === 'foo'">Tab Foo</div> <div x-show="tab === 'bar'">Tab Bar</div> </div> ``` 사소한 목ì ìœ¼ë¡œë„ ì‚¬ìš©í• ìˆ˜ 있습니다. *ë“œë¡ë‹¤ìš´ì— 마우스 오버 ì‹œ HTML ë‚´ìš©ì„ ë¯¸ë¦¬ ê°€ì ¸ì˜µë‹ˆë‹¤.* ```html <div x-data="{ open: false }"> <button @mouseenter.once=" fetch('/dropdown-partial.html') .then(response => response.text()) .then(html => { $refs.dropdown.innerHTML = html }) " @click="open = true" >Show Dropdown</button> <div x-ref="dropdown" x-show="open" @click.away="open = false"> Loading Spinner... </div> </div> ``` ## 배우기 다ìŒê³¼ ê°™ì´ ì´ 14ê°œì˜ ì§€ì¹¨ì´ ìžˆìŠµë‹ˆë‹¤: | 지침 | 설명 | | --- | --- | | [`x-data`](#x-data) | 새로운 êµ¬ì„±ìš”ì†Œì˜ ë²”ìœ„ë¥¼ ì„ ì–¸í•©ë‹ˆë‹¤. | | [`x-init`](#x-init) | 구성요소가 초기화ë ë•Œ ì œê³µëœ ì‹ì„ 실행합니다. | | [`x-show`](#x-show) | `display: none;` 부울 표현ì‹ì— ë”°ë¼ ìš”ì†Œë¥¼ í† ê¸€í•©ë‹ˆë‹¤. (true ë˜ëŠ” false). | | [`x-bind`](#x-bind) | ì „ë‹¬ ëœ JS 표현ì‹ì˜ 결과와 ë™ì¼í•œ ì†ì„± ê°’ì„ ì„¤ì •í•©ë‹ˆë‹¤. | | [`x-on`](#x-on) | ìš”ì†Œì— ì´ë²¤íŠ¸ 리스너를 설치합니다. ì´ë²¤íŠ¸ê°€ ë°œìƒí•˜ë©´ ì œê³µëœ JS 표현ì‹ì„ 실행합니다. | | [`x-model`](#x-model) | ì§€ì‹œë¬¸ì€ ìž…ë ¥ ìš”ì†Œì™€ì˜ ë°ì´í„° ë°”ì¸ë”©ì„ 보장합니다. ì´ë¥¼ 통해 양방향으로 ë°ì´í„° ë°”ì¸ë”©ì´ 가능합니다. | | [`x-text`](#x-text) | ìœ ì‚¬í•œ ë°©ì‹ìœ¼ë¡œ ìž‘ë™ `x-bind`ì˜ `innerText` 요소가 ì—…ë°ì´íŠ¸ë©ë‹ˆë‹¤. | | [`x-html`](#x-html) | ìœ ì‚¬í•œ ë°©ì‹ìœ¼ë¡œ ìž‘ë™ `x-bind`ì˜ `innerHTML` 요소가 ì—…ë°ì´íŠ¸ë©ë‹ˆë‹¤. | | [`x-ref`](#x-ref) | 구성 ìš”ì†Œì˜ DOM 요소를 ê°€ì ¸ì˜¤ëŠ” 편리한 방법입니다. | | [`x-if`](#x-if) | ì „ë‹¬ëœ ì¡°ê±´ì´ ì¶©ì¡±ë˜ì§€ 않으면 DOMì—ì„œ 요소를 ì™„ì „ížˆ ì œê±°í•©ë‹ˆë‹¤. `<template>` íƒœê·¸ì— ì‚¬ìš©ë˜ì–´ì•¼ 합니다. | [`x-for`](#x-for) | ë°°ì—´ì˜ ê° í•ëª©ì— 대해 새 DOM 노드를 만ë“니다. `<template>`íƒœê·¸ì— ì‚¬ìš©í•´ì•¼í•©ë‹ˆë‹¤. | | [`x-transition`](#x-transition) | 요소 ì „í™˜ì˜ ë‹¤ì–‘í•œ ë‹¨ê³„ì— í´ëž˜ìŠ¤ë¥¼ 추가하기 위한 지시. | | [`x-spread`](#x-spread) | Alpine ì§€ì‹œë¬¸ì´ ìžˆëŠ” 개체를 ìš”ì†Œì— ë°”ì¸ë”©í•˜ì—¬ ìž¬ì‚¬ìš©ì„±ì„ ë†’ì¼ ìˆ˜ 있습니다. | | [`x-cloak`](#x-cloak) | Alpineì´ ì´ˆê¸°í™”ë˜ë©´ í•´ì œë©ë‹ˆë‹¤. 초기화 ì „ì— DOMì„ ìˆ¨ê¸°ëŠ” ë° ìœ ìš©í•©ë‹ˆë‹¤. | ê·¸ë¦¬ê³ 6가지 마법ì†ì„±: | 마법ì†ì„± | 설명 | | --- | --- | | [`$el`](#el) | 루트 구성 ìš”ì†Œì˜ DOM 노드를 검색합니다. | | [`$refs`](#refs) | `x-ref` ì»´í¬ë„ŒíŠ¸ ë‚´ë¶€ì— í‘œì‹œëœ DOM 요소를 검색합니다. | | [`$event`](#event) | ì´ë²¤íŠ¸ 핸들러ì—ì„œ 기본 브ë¼ìš°ì € "Event" ê°ì²´ë¥¼ 검색합니다. | | [`$dispatch`](#dispatch) | `CustomEvent`를 ë§Œë“¤ê³ `.dispatchEvent()` 내부ì 으로 보냅니다. | | [`$nextTick`](#nexttick) | Alpineì´ ë°˜ì‘형 DOM ì—…ë°ì´íŠ¸ë¥¼ 수행한 후 ì œê³µëœ í‘œí˜„ì‹ì„ 실행합니다. | | [`$watch`](#watch) | "ìˆ˜ì‹ (watched)"ì¤‘ì¸ êµ¬ì„± ìš”ì†Œì˜ ì†ì„±ì´ 변경ë ë•Œ ì œê³µë˜ëŠ” ì½œë°±ì„ íŠ¸ë¦¬ê±°í•©ë‹ˆë‹¤. | ## 스í°ì„œ <img width="33%" src="https://refactoringui.nyc3.cdn.digitaloceanspaces.com/tailwind-logo.svg" alt="Tailwind CSS"> **ì—¬ê¸°ì— ë¡œê³ ë¥¼ 등ë¡í•˜ê³ ì‹¶ìœ¼ì‹ ê°€ìš”? [Twitterë¡œ DMì„ ë³´ë‚´ì£¼ì„¸ìš”](https://twitter.com/calebporzio)** ## 커뮤니티 프로ì 트 * [AlpineJS Weekly Newsletter](https://alpinejs.codewithhugo.com/newsletter/) * [Spruce (State Management)](https://github.com/ryangjchandler/spruce) * [Turbolinks Adapter](https://github.com/SimoTod/alpine-turbolinks-adapter) * [Alpine Magic Helpers](https://github.com/KevinBatdorf/alpine-magic-helpers) * [Awesome Alpine](https://github.com/ryangjchandler/awesome-alpine) ### 지시어 --- ### `x-data` **ì˜ˆì œ:** `<div x-data="{ foo: 'bar' }">...</div>` **구조:** `<div x-data="[object literal]">...</div>` `x-data` 구성 ìš”ì†Œì˜ ìƒˆ 범위를 ì„ ì–¸í•©ë‹ˆë‹¤. ë‹¤ìŒ ë°ì´í„° 개체를 사용하여 새 구성 요소를 초기화하ë„ë¡ í”„ë ˆìž„ì›Œí¬ì— 지시합니다. Vue ì»´í¬ë„ŒíŠ¸ì˜ `data` ì†ì„±ê³¼ ìœ ì‚¬í•©ë‹ˆë‹¤. **ì»´í¬ë„ŒíŠ¸ ë¡œì§ ì¶”ì¶œ** ìž¬ì‚¬ìš©ì´ ê°€ëŠ¥í•œ ë°ì´í„°(ë™ìž‘)를 ì¶”ì¶œí• ìˆ˜ 있습니다. ```html <div x-data="dropdown()"> <button x-on:click="open">Open</button> <div x-show="isOpen()" x-on:click.away="close"> // Dropdown </div> </div> <script> function dropdown() { return { show: false, open() { this.show = true }, close() { this.show = false }, isOpen() { return this.show === true }, } } </script> ``` > **번들러 사용ìžì˜ 경우**, Alpine.js는 ì „ì— ë²”ìœ„(`window`)ì˜ í•¨ìˆ˜ì—만 액세스합니다. 예를 들어 `x-data`를 ì‚¬ìš©í•˜ë ¤ë©´ 함수를 `window.dropdown = function () {}`처럼 `window`ì— ëª…ì‹œì 으로 í• ë‹¹í•´ì•¼í•©ë‹ˆë‹¤. (ì´ê²ƒì€ Webpack, Rollup, Parcel ë“±ì˜ `함수(function)`를 사용하면 기본ì 으로 `window`ê°€ ì•„ë‹Œ ëª¨ë“ˆì˜ ë²”ìœ„ë¡œ ì„¤ì •ë˜ê¸° 때문입니다.) ê°ì²´ë¥¼ 분리 사용하여 여러 ë°ì´í„° ê°ì²´ë¥¼ 혼합하여 ì‚¬ìš©í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. ```html <div x-data="{...dropdown(), ...tabs()}"> ``` --- ### `x-init` **ì˜ˆì œ:** `<div x-data="{ foo: 'bar' }" x-init="foo = 'baz'"></div>` **구조:** `<div x-data="..." x-init="[expression]"></div>` `x-init` 구성 요소가 초기화ë ë•Œ ì œê³µëœ ì‹ì„ 실행합니다. 초기 Alpine DOM ì—…ë°ì´íŠ¸ (예 : VueJSì˜ `mounted()` í›„í¬ ) í›„ì— ì½”ë“œë¥¼ ì‹¤í–‰í•˜ë ¤ë©´ `x-init` ì½œë°±ì„ ì „ë‹¬í• ìˆ˜ 있으며 초기화 í›„ì— ì‹¤í–‰í•©ë‹ˆë‹¤: `x-init="() => { // we have access to the post-dom-initialization state here // }"` --- ### `x-show` **ì˜ˆì œ:** `<div x-show="open"></div>` **구조:** `<div x-show="[expression]"></div>` `x-show` 표현ì‹ì´ true ë˜ëŠ” falseë¡œ ê²°ì •ë¨ì— ë”°ë¼ ìš”ì†Œì˜ `display: none;` ìŠ¤íƒ€ì¼ ì†ì„±ì„ ì „í™˜í•©ë‹ˆë‹¤. **x-show.transition** `x-show.transition`ì€ `x-show` 보다 ë” ë‚˜ì€ CSS transitionì„ ì œê³µí•˜ëŠ” 편리한 API입니다. ```html <div x-show.transition="open"> ì´ê³³ì˜ 컨í…ì¸ ë“¤ì€ transition in, outì´ ë™ìž‘ë¨. </div> ``` | 지침 | 설명 | | --- | --- | | `x-show.transition` | fade 와 scaleì´ ë™ì‹œì— ë™ìž‘ë¨. (opacity, scale: 0.95, timing-function: cubic-bezier(0.4, 0.0, 0.2, 1), duration-in: 150ms, duration-out: 75ms) | `x-show.transition.in` | transition in만 ë™ìž‘ë¨. | | `x-show.transition.out` | transition out만 ë™ìž‘ë¨. | | `x-show.transition.opacity` | fade만 사용ë¨. | | `x-show.transition.scale` | scale만 사용ë¨. | | `x-show.transition.scale.75` | CSS scale transform 사용ìží™” `transform: scale(.75)`. | | `x-show.transition.duration.200ms` | transition "in"ì„ 200msë¡œ ì„¤ì •. outì€ ê·¸ê²ƒì˜ ì ˆë°˜(100ms)으로 ì„¤ì •ë¨. | | `x-show.transition.origin.top.right` | CSS transform origin 사용ìží™” `transform-origin: top right`. | | `x-show.transition.in.duration.200ms.out.duration.50ms` | "in" and "out"ì— ëŒ€í•œ 서로 다른 ë™ìž‘시간. | > ì°¸ê³ : ëª¨ë“ transition ìˆ˜ì •ìžì„ 서로 결합하여 ì‚¬ìš©í• ìˆ˜ 있습니다. ì´ê²ƒì´ 가능합니다(ë§ë„ 안ë˜ì§€ë§Œ lol): `x-show.transition.in.duration.100ms.origin.top.right.opacity.scale.85.out.duration.200ms.origin.bottom.left.opacity.scale.95` > ì°¸ê³ : `x-show`는 ëª¨ë“ ìžì‹ì´ ì „í™˜ì„ ì™„ë£Œí• ë•Œ 까지 대기합니다. ì´ ë™ìž‘ì„ ìš°íšŒí•˜ë ¤ë©´ `.immediate`ìˆ˜ì •ìžë¥¼ 추가하세요: ```html <div x-show.immediate="open"> <div x-show.transition="open"> </div> ``` --- ### `x-bind` > ì°¸ê³ : 조금 ë” ê°„ë‹¨í•œ êµ¬ë¬¸ì„ ì‚¬ìš©í• ìˆ˜ 있습니다. ":" syntax: `:type="..."`. **ì˜ˆì œ:** `<input x-bind:type="inputType">` **구조:** `<input x-bind:[attribute]="[expression]">` `x-bind` JavaScript 표현ì‹ì˜ 결과를 ì†ì„±ê°’으로 ì„¤ì •í•©ë‹ˆë‹¤. 표현ì‹ì€ componentê°€ ê°€ì§€ê³ ìžˆëŠ” ë°ì´í„° ê°ì²´ì˜ ëª¨ë“ í‚¤ì— ì ‘ê·¼í• ìˆ˜ 있으며, componentì˜ ë°ì´í„°ê°€ 변경ë 때마다 ìžë™ìœ¼ë¡œ ê°±ì‹ ë©ë‹ˆë‹¤. > ì°¸ê³ : ì†ì„± ë°”ì¸ë”©ì€ 종ì†ì„±ì´ ì—…ë°ì´íŠ¸ë 때만 ì—…ë°ì´íŠ¸ë©ë‹ˆë‹¤. Framework는 ë°ì´í„° 변경 사í•ì„ ê´€ì°°í•˜ê³ ì–´ë–¤ ë°”ì¸ë”©ì´ ì´ë¥¼ 처리하는지 ê°ì§€í• 수 ìžˆì„ ë§Œí¼ ë˜‘ë˜‘í•©ë‹ˆë‹¤. **í´ëž˜ìŠ¤ ì†ì„±ì¼ 경우 `x-bind`** `x-bind` ê°€ `class` ì†ì„±ì— ë°”ì¸ë”© ë 때는 조금 다르게 ë™ìž‘합니다. í´ëž˜ìŠ¤ì˜ 경우, 키가 í´ëž˜ìŠ¤ ì´ë¦„ì´ê³ ê°’ì´ ë¶€ìš¸ 표현 ì‹ì¸ ê°ì²´ë¥¼ ì „ë‹¬í•˜ì—¬ 해당 í´ëž˜ìŠ¤ ì´ë¦„ì˜ ì 용여부를 ê²°ì •í•©ë‹ˆë‹¤. ì˜ˆì œ: `<div x-bind:class="{ 'hidden': foo }"></div>` ì´ ì˜ˆì œì—ì„œ, "hidden" í´ëž˜ìŠ¤ëŠ” `foo` ë°ì´í„° ì†ì„±ê°’ì´ `true` ì¸ ê²½ìš°ì—만 ì ìš©ë©ë‹ˆë‹¤. **부울 ì†ì„±ì¼ 경우 `x-bind`** `x-bind`는 변수를 ì¡°ê±´ì‹ìœ¼ë¡œ 사용하거나 `true` ë˜ëŠ” `false`ë¡œ 확ì¸ë˜ëŠ” JavaScript 표현ì‹ì„ 사용하여, ê°’ ì†ì„±ê³¼ ë™ì¼í•œ ë°©ì‹ìœ¼ë¡œ 부울 ì†ì„±ì„ 지ì›í•©ë‹ˆë‹¤. ì˜ˆì œ: ```html <!-- Given: --> <button x-bind:disabled="myVar">Click me</button> <!-- When myVar == true: --> <button disabled="disabled">Click me</button> <!-- When myVar == false: --> <button>Click me</button> ``` 위 ì˜ˆì œì—서는 `myVar`ì˜ ê°’ì´ ê°ê° true ë˜ëŠ” false ì¸ì§€ì— ë”°ë¼ `disabled`ì†ì„±ì´ 추가 ë˜ëŠ” ì‚ì œë©ë‹ˆë‹¤. 부울 ì†ì„±ì€ 다ìŒê³¼ ê°™ì€ ì†ì„±ì— 대해 지ì›ë©ë‹ˆë‹¤.[HTML specification](https://html.spec.whatwg.org/multipage/indices.html#attributes-3:boolean-attribute), 예 `disabled`, `readonly`, `required`, `checked`, `hidden`, `selected`, `open`, ê·¸ 외. > ì°¸ê³ : `aria-*`와 ê°™ì´ ì†ì„±ì— 대해 보여줄 거짓 ìƒíƒœê°€ 필요한 경우 ì†ì„±ì— ë°”ì¸ë”© 하는 ë™ì•ˆ `.toString()`ì„ ê°’ì— ì—°ê²°í•©ë‹ˆë‹¤. 예: `:aria-expanded="isOpen.toString()"`는 `isOpen`ê°€ `true` ë˜ëŠ” `false`ì—¬ë¶€ì— ê´€ê³„ì—†ì´ ìœ ì§€ë©ë‹ˆë‹¤. **`.camel` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<svg x-bind:view-box.camel="viewBox">` `camel`ìˆ˜ì •ìžëŠ” camel í‘œê¸°ë²•ì— í•´ë‹¹í•˜ëŠ” ì†ì„±ëª…으로 ë°”ì¸ë”© 합니다. 위 ì˜ˆì œì—ì„œ `viewBox`ì˜ ê°’ì€ `view-box`ì†ì„±ì´ ì•„ë‹Œ `viewBox` ì†ì„±ìœ¼ë¡œ ë°”ì¸ë”© ë©ë‹ˆë‹¤. --- ### `x-on` > ì°¸ê³ : 조금 ë” ê°„ë‹¨í•œ êµ¬ë¬¸ì„ ì‚¬ìš©í• ìˆ˜ 있습니다. "@" syntax: `@click="..."`. **ì˜ˆì œ:** `<button x-on:click="foo = 'bar'"></button>` **구조:** `<button x-on:[event]="[expression]"></button>` `x-on`ì€ ì„ ì–¸ ëœ ìš”ì†Œì— ì´ë²¤íŠ¸ 리스너를 연결합니다. 해당 ì´ë²¤íŠ¸ê°€ ë°œìƒí•˜ë©´ 해당 값으로 ì„¤ì •ëœ JavaScript 표현ì‹ì´ 실행ë©ë‹ˆë‹¤. ì „ì²´ ì´ë²¤íŠ¸ 목ë¡ì„ ë³´ë ¤ë©´ ì§€ì‹œë¬¸ì„ ì¶”ê°€í•˜ëŠ” ìš”ì†Œì— ì‚¬ìš©í• ìˆ˜ìžˆëŠ” ëª¨ë“ ì´ë²¤íŠ¸ì™€ 함께`x-on`ì„ ì‚¬ìš©í• ìˆ˜ 있습니다. 사용 가능한 ê°’ í•ëª©ë“¤ì€ [the Event reference on MDN](https://developer.mozilla.org/en-US/docs/Web/Events)ì—ì„œ 확ì¸í• 수 있습니다. 표현ì‹ì—ì„œ ë°ì´í„°ê°€ ìˆ˜ì •ë˜ë©´, ì´ ë°ì´í„°ì™€ ì—°ê´€ë˜ì–´ 있는 다른 ìš”ì†Œì˜ ì†ì„±ë„ ì—…ë°ì´íŠ¸ë©ë‹ˆë‹¤. > ì°¸ê³ : ìžë°”스í¬ë¦½íŠ¸ 함수 ì´ë¦„ì„ ì§€ì •í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. **ì˜ˆì œ:** `<button x-on:click="myFunction"></button>` 위 ì˜ˆì œëŠ” 다ìŒì½”드와 ë™ì¼í•©ë‹ˆë‹¤: `<button x-on:click="myFunction($event)"></button>` **`keydown` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<input type="text" x-on:keydown.escape="open = false">` `x-on:keydown` ë””ë ‰í‹°ë¸Œì— keydown ìˆ˜ì •ìžë¥¼ 사용하여 ìˆ˜ì‹ í• íŠ¹ì • 키를 ì§€ì •í• ìˆ˜ 있습니다. ìˆ˜ì •ìžëŠ” `Event.key` ê°’ì˜ ì¼€ë°¥ ì¼€ì´ìŠ¤ ë²„ì „ìž…ë‹ˆë‹¤. ì˜ˆì œ: `enter`, `escape`, `arrow-up`, `arrow-down` > ì°¸ê³ : `x-on:keydown.cmd.enter="foo"`와 ê°™ì´ ì‹œìŠ¤í…œ ìˆ˜ì •ìž í‚¤ ì¡°í•©ì„ ì‚¬ìš©í•˜ì—¬ ìˆ˜ì‹ í• ìˆ˜ 있습니다. **`.away` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<div x-on:click.away="showModal = false"></div>` `.away`ìˆ˜ì •ìžê°€ 있는 경우, ì´ë²¤íŠ¸ 핸들러는 ìžì‹ ìžì²´ê°€ ì•„ë‹Œ 다른 소스 ë˜ëŠ” 하위 소스ì—ì„œ ë°œìƒí• ë•Œ 실행ë©ë‹ˆë‹¤. ì´ê²ƒì€ ì‚¬ìš©ìž í´ë¦í• ë•Œ ë“œë¡ë‹¤ìš´ê³¼ ëª¨ë‹¬ì„ ìˆ¨ê¸°ëŠ”ë° ìœ ìš©í•©ë‹ˆë‹¤. **`.prevent` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<input type="checkbox" x-on:click.prevent>` ì´ë²¤íŠ¸ ë¦¬ìŠ¤ë„ˆì— `.prevent`를 추가하면 íŠ¸ë¦¬ê±°ëœ ì´ë²¤íŠ¸ì—ì„œ `preventDefault`ê°€ 호출ë©ë‹ˆë‹¤. 위 ì˜ˆì œì—ì„œ ì´ê²ƒì€ 사용ìžê°€ ì²´í¬ë°•ìŠ¤ë¥¼ í´ë¦í• ë•Œ, ì²´í¬ë°•ìŠ¤ê°€ ì‹¤ì œë¡œ ì„ íƒë˜ì§€ ì•ŠìŒì„ ì˜ë¯¸í•©ë‹ˆë‹¤. **`.stop` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<div x-on:click="foo = 'bar'"><button x-on:click.stop></button></div>` ì´ë²¤íŠ¸ ë¦¬ìŠ¤ë„ˆì— `.stop`를 추가하면 íŠ¸ë¦¬ê±°ëœ ì´ë²¤íŠ¸ì—ì„œ `stopPropagation`ê°€ 호출ë©ë‹ˆë‹¤. 위 ì˜ˆì œì—ì„œ ì´ê²ƒì€ "í´ë¦" ì´ë²¤íŠ¸ê°€ 외부 `<div>`ë¡œ 버블ë§ë˜ì§€ ì•ŠìŒì„ ì˜ë¯¸í•©ë‹ˆë‹¤. 즉, 사용ìžê°€ ë²„íŠ¼ì„ í´ë¦í•´ë„ `foo`는 `'bar'`ë¡œ ì„¤ì •ë˜ì§€ 않습니다. **`.self` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<div? x-on:click.self="foo = 'bar'"><button></button></div?>` ì´ë²¤íŠ¸ ë¦¬ìŠ¤ë„ˆì— `.self`를 추가하면 `$event.target`ì´ ìš”ì†Œ ìžì²´ì¸ 경우ì—만 ì´ë²¤íŠ¸ 핸들러가 트리거ë©ë‹ˆë‹¤. 위 ì˜ˆì œì—ì„œ ì´ê²ƒì€ 버튼ì—ì„œ 외부 `<div>`ë¡œ 버블ë§ëœ "í´ë¦"ì´ë²¤íŠ¸ê°€ 핸들러를 실행시키지 **ì•ŠìŒ**ì„ ì˜ë¯¸í•©ë‹ˆë‹¤. **`.window` ìˆ˜ì •ìž** **ì˜ˆì œ:** `< x-on:resize.window="isOpen = window.outerWidth > 768 ? false : open"></div>` ì´ë²¤íŠ¸ ë¦¬ìŠ¤ë„ˆì— `.window`를 추가하면 ì„ ì–¸ëœ DOM 노드 ëŒ€ì‹ ì „ì— ìœˆë„ìš° ê°ì²´ì— 리스너가 ì„¤ì •ë©ë‹ˆë‹¤. ì´ê²ƒì€ 리사ì´ì¦ˆ ì´ë²¤íŠ¸ì™€ ê°™ì´ ìœˆë„ìš°ì—ì„œ 무언가 변경ë ë•Œ ì»´í¬ë„ŒíŠ¸ì˜ ìƒíƒœë¥¼ ë³€ê²½í•˜ê³ ì‹¶ì€ ê²½ìš° ìœ ìš©í•©ë‹ˆë‹¤. ì´ ì˜ˆì œì—ì„œ 우리는 윈ë„ìš° 너비가 768 픽셀보다 커지면, 모달/ë“œë¡ë‹¤ìš´ì„ ë‹«ê³ ê·¸ë ‡ì§€ 않으면 ë™ì¼í•œ ìƒíƒœë¥¼ ìœ ì§€í•©ë‹ˆë‹¤ >ì°¸ê³ : `window` ëŒ€ì‹ `.document` ìˆ˜ì •ìžë¥¼ 사용하여 `document`ì— ë¦¬ìŠ¤ë„ˆë¥¼ 추가 í• ìˆ˜ 있습니다. **`.once` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<button x-on:mouseenter.once="fetchSomething()"></button>` ì´ë²¤íŠ¸ ë¦¬ìŠ¤ë„ˆì— `.once` ìˆ˜ì •ìžë¥¼ 추가하면, 리스너가 í•œ 번만 처리ë©ë‹ˆë‹¤. ì´ê²ƒì€ HTML부분 ê°€ì ¸ì˜¤ê¸°ì™€ ê°™ì´ í•œ 번만 ìˆ˜í–‰í•˜ë ¤ëŠ” ìž‘ì—…ì— ìœ ìš©í•©ë‹ˆë‹¤. **`.passive` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<button x-on:mousedown.passive="interactive = true"></button>` ì´ë²¤íŠ¸ ë¦¬ìŠ¤ë„ˆì— `.passive` ìˆ˜ì •ìžë¥¼ 추가하면 리스너를 수ë™ì 으로 ë™ìž‘하게 만ë“니다. 처리 ì¤‘ì¸ ì–´ë–¤ ì´ë²¤íŠ¸ì—ë„ `preventDefault()`ê°€ ë™ìž‘하지 ì•ŠìŒì„ ì˜ë¯¸í•©ë‹ˆë‹¤. 예를 들어 터치 ê¸°ê¸°ì˜ ìŠ¤í¬ë¡¤ ì„±ëŠ¥ì— ë„ì›€ì´ ë 수 있습니다. **`.debounce` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<input x-on:input.debounce="fetchSomething()">` `debounce` ìˆ˜ì •ìžë¥¼ 사용하면 ì´ë²¤íŠ¸ 핸들러를 "디바운스" í• ìˆ˜ 있습니다. 즉, ì´ë²¤íŠ¸ 핸들러는 마지막 ì´ë²¤íŠ¸ê°€ ë°œìƒí•œ ì´í›„ ì¼ì • ì‹œê°„ì´ ì§€ë‚ ë•Œê¹Œì§€ 실행ë˜ì§€ 않습니다. 핸들러가 호출ë 준비가 ë˜ë©´ 마지막 핸들러 í˜¸ì¶œì´ ì‹¤í–‰ë©ë‹ˆë‹¤. ë””ë°”ìš´ìŠ¤ì˜ ê¸°ë³¸ "대기" ì‹œê°„ì€ 250 밀리세컨드 입니다. ì´ë¥¼ 사용ìží™” í•˜ë ¤ë©´ 다ìŒê³¼ ê°™ì´ ì‚¬ìš©ìž ëŒ€ê¸° ì‹œê°„ì„ ì§€ì •í• ìˆ˜ 있습니다: ``` <input x-on:input.debounce.750="fetchSomething()"> <input x-on:input.debounce.750ms="fetchSomething()"> ``` **`.camel` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<input x-on:event-name.camel="doSomething()">` `camel` ìˆ˜ì •ìžëŠ” ì´ë²¤íŠ¸ëª…ê³¼ ë™ë“±í•œ ì¹´ë©œ 표기법으로 ì´ë²¤íŠ¸ 리스너를 연결합니다. 위 ì˜ˆì œì—ì„œ 표현ì‹ì€ 요소ì—ì„œ `eventName` ì´ë²¤íŠ¸ê°€ ë°œìƒí• ë•Œ í‰ê°€ë©ë‹ˆë‹¤. --- ### `x-model` **ì˜ˆì œ:** `<input type="text" x-model="foo">` **구조:** `<input type="text" x-model="[data item]">` `x-model`ì€ ìš”ì†Œì— "ì–‘ë°©í–¥ ë°ì´í„° ë°”ì¸ë”©"ì„ ì¶”ê°€í•©ë‹ˆë‹¤. 즉, ìž…ë ¥ ìš”ì†Œì˜ ê°’ì€ ì»´í¬ë„ŒíŠ¸ ë°ì´í„° ì•„ì´í…œì˜ ê°’ê³¼ ë™ê¸°í™”ë˜ê³ ìœ ì§€ë©ë‹ˆë‹¤. > ì°¸ê³ : `x-model`ì€ text inputs, checkboxes, radio buttons, textareas, selects, ê·¸ë¦¬ê³ multiple selects ìš”ì†Œì˜ ë³€ê²½ì„ ê°ì§€í•˜ëŠ”ë° ë›°ì–´ë‚©ë‹ˆë‹¤. ì´ëŸ¬í•œ 시나리오ì—ì„œ [how Vue would](https://vuejs.org/v2/guide/forms.html) ë™ìž‘해야 합니다. **`.number` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<input x-model.number="age">` `number`ìˆ˜ì •ìžëŠ” inputì˜ ê°’ì„ ìˆ«ìžë¡œ 변환합니다. 만약 ê°’ì´ ìœ íš¨í•œ 숫ìžë¡œ 분ì„ë˜ì§€ 않으면, ì›ë³¸ ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. **`.debounce` ìˆ˜ì •ìž** **ì˜ˆì œ:** `<input x-model.debounce="search">` `debounce` ìˆ˜ì •ìžë¥¼ 사용하면 ê°’ ì—…ë°ì´íŠ¸ì— "debounce"를 추가 í• ìˆ˜ 있습니다. 즉, ì´ë²¤íŠ¸ 핸들러는 마지막 ì´ë²¤íŠ¸ê°€ ë°œìƒí•œ ì´í›„ ì¼ì • ì‹œê°„ì´ ì§€ë‚ ë•Œê¹Œì§€ 실행ë˜ì§€ 않습니다. 핸들러가 호출ë 준비가 ë˜ë©´ 마지막 핸들러 í˜¸ì¶œì´ ì‹¤í–‰ë©ë‹ˆë‹¤. ë””ë°”ìš´ìŠ¤ì˜ ê¸°ë³¸ "대기" ì‹œê°„ì€ 250 밀리세컨드 입니다. ì´ë¥¼ 사용ìží™” í•˜ë ¤ë©´ 다ìŒê³¼ ê°™ì´ ì‚¬ìš©ìž ëŒ€ê¸° ì‹œê°„ì„ ì§€ì •í• ìˆ˜ 있습니다: ``` <input x-model.debounce.750="search"> <input x-model.debounce.750ms="search"> ``` --- ### `x-text` **ì˜ˆì œ:** `<span x-text="foo"></span>` **구조:** `<span x-text="[expression]"` `x-text`는 ì†ì„±ê°’ì„ ì—…ë°ì´íŠ¸í•˜ëŠ” ëŒ€ì‹ ìš”ì†Œì˜ `innerText`를 ì—…ë°ì´íŠ¸í•œë‹¤ëŠ” ì ì„ ì œì™¸í•˜ë©´,`x-bind`와 ìœ ì‚¬í•˜ê²Œ ë™ìž‘합니다. --- ### `x-html` **ì˜ˆì œ:** `<span x-html="foo"></span>` **구조:** `<span x-html="[expression]"` `x-html`는 ì†ì„±ê°’ì„ ì—…ë°ì´íŠ¸í•˜ëŠ” ëŒ€ì‹ ìš”ì†Œì˜ `innerHTML`ì„ ì—…ë°ì´íŠ¸í•œë‹¤ëŠ” ì ì„ ì œì™¸í•˜ë©´, `x-bind`와 ìœ ì‚¬í•˜ê²Œ ë™ìž‘합니다. > :warning: **ì‹ ë¢°ì„±ìžˆëŠ” 컨í…íŠ¸ì— ëŒ€í•´ì„œë§Œ ì‚¬ìš©í•˜ê³ ì‚¬ìš©ìž ì œê³µ 컨í…트ì—는 ì ˆëŒ€ë¡œ 사용하지 마세요** :warning: > > ì œ 3ìžë¥¼ 통한 ë™ì HTML ë Œë”ë§ì€ 쉽게 [XSS](https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting)ì— ì·¨ì•½í•´ì§ˆ 수 있습니다. --- ### `x-ref` **ì˜ˆì œ:** `<div x-ref="foo"></div><button x-on:click="$refs.foo.innerText = 'bar'"></button>` **구조:** `<div x-ref="[ref name]"></div><button x-on:click="$refs.[ref name].innerText = 'bar'"></button>` `x-ref`는 ì»´í¬ë„ŒíŠ¸ì˜ ì›ì‹œ DOM 요소를 검색하는 편리한 ë°©ë²•ì„ ì œê³µí•©ë‹ˆë‹¤. ìš”ì†Œì— `x-ref`ì†ì„±ì„ ì„¤ì •í•˜ë©´ `$refs`ë¼ëŠ” ê°ì²´ 내부ì—ì„œ ëª¨ë“ ì´ë²¤íŠ¸ 핸들러를 ì‚¬ìš©í• ìˆ˜ 있습니다. ì´ê²ƒì€ ì•„ì´ë””를 ì„¤ì •í•˜ê³ ëª¨ë“ ê³³ì—ì„œ `document.querySelector`를 사용하는 ê²ƒì— ëŒ€í•œ ìœ ìš©í•œ 대안입니다. > ì°¸ê³ : 필요하다면 x-ref: `<span :x-ref="item.id"></span>`와 ê°™ì´ ë™ì 으로 ê°’ì„ ë°”ì¸ë”© í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. --- ### `x-if` **ì˜ˆì œ:** `<template x-if="true"><div>Some Element</div></template>` **구조:** `<template x-if="[expression]"><div>Some Element</div></template>` `x-show`ë¡œ 충분하지 ì•Šì€ ê²½ìš°(`x-show`는 ê°’ì´ ê±°ì§“ì´ë©´ 요소를 `display: none`ë¡œ ì„¤ì •í•©ë‹ˆë‹¤.) , `x-if`는 DOM으로 부터 요소를 ì™„ì „ížˆ ì‚ì œí• ë•Œ ì‚¬ìš©í• ìˆ˜ 있습니다. Alpineì€ ê°€ìƒ DOMì„ ì‚¬ìš©í•˜ì§€ 않기 ë•Œë¬¸ì— `x-if`를 `<template></template>` íƒœê·¸ì— ì‚¬ìš©í•˜ëŠ”ê²Œ 중요합니다. ì´ëŸ¬í•œ êµ¬í˜„ì„ í†µí•´ Alpineì€ ê²¬ê³ í•¨ì„ ìœ ì§€í•˜ê³ ì‹¤ì œ DOMì„ ì‚¬ìš©í•˜ì—¬ ë§ˆë²•ì„ ë¶€ë¦´ 수 있습니다. > ì°¸ê³ : `x-if`는 `<template></template>`태그 ë‚´ì— ë‹¨ì¼ ë£¨íŠ¸ 요소만 ê°€ì ¸ì•¼ 합니다. > ì°¸ê³ : `svg`ì— `template`를 ì‚¬ìš©í• ë• Alpine.js ê°€ 초기화 ë˜ê¸° ì „ì— ì‹¤í–‰ë˜ë„ë¡ [í´ë¦¬í•„](https://github.com/alpinejs/alpine/issues/637#issuecomment-654856538)ì„ ì¶”ê°€í•´ì•¼ 합니다. --- ### `x-for` **ì˜ˆì œ:** ```html <template x-for="item in items" :key="item"> <div x-text="item"></div> </template> ``` > ì°¸ê³ : `:key` ë°”ì¸ë”©ì€ ì„ íƒì‚¬í•ì´ì§€ë§Œ, 사용하는 ê²ƒì„ ì 극추천합니다. `x-for`는 ë°°ì—´ì˜ ê° í•ëª©ì— 대해 새로운 DOM 노드를 ìƒì„±í•˜ë ¤ëŠ” 경우 ì‚¬ìš©í• ìˆ˜ 있습니다. ì´ê²ƒì€ ì¼ë°˜ì ì¸ DOM 요소가 ì•„ë‹Œ `template` íƒœê·¸ì— ìžˆì–´ì•¼ 한다는 ê²ƒì„ ì œì™¸í•˜ë©´ Vueì˜ `v-for`와 ìœ ì‚¬í•˜ê²Œ 나타나야 합니다. ë°˜ë³µë¬¸ì˜ í˜„ìž¬ 색ì¸ì— ì ‘ê·¼í•˜ê³ ì‹¶ë‹¤ë©´, ë‹¤ìŒ êµ¬ë¬¸ì„ ì‚¬ìš©í•˜ì„¸ìš”: ```html <template x-for="(item, index) in items" :key="index"> <!-- ì›í•œë‹¤ë©´ 반복문 ë‚´ë¶€ì˜ "색ì¸"ì„ ì°¸ì¡°í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. --> <div x-text="index"></div> </template> ``` ë°˜ë³µë¬¸ì˜ ë°°ì—´ê°ì²´(ì»¬ë ‰ì…˜)ì— ì ‘ê·¼í•˜ê³ ì‹¶ë‹¤ë©´, ë‹¤ìŒ êµ¬ë¬¸ì„ ì‚¬ìš©í•˜ì„¸ìš”: ```html <template x-for="(item, index, collection) in items" :key="index"> <!-- ì›í•œë‹¤ë©´ 반복문 ë‚´ë¶€ì˜ "ì»¬ë ‰ì…˜"ì„ ì°¸ì¡°í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. --> <!-- 현재 í•ëª©. --> <div x-text="item"></div> <!-- 위와 ë™ì¼. --> <div x-text="collection[index]"></div> <!-- ì´ì „ í•ëª©. --> <div x-text="collection[index - 1]"></div> </template> ``` > ì°¸ê³ : `x-for`는 `<template></template>`태그 ë‚´ì— ë‹¨ì¼ ë£¨íŠ¸ 요소만 ê°€ì ¸ì•¼ 합니다. > ì°¸ê³ : `svg`ì— `template`를 ì‚¬ìš©í• ë• Alpine.js ê°€ 초기화 ë˜ê¸° ì „ì— ì‹¤í–‰ë˜ë„ë¡ [í´ë¦¬í•„](https://github.com/alpinejs/alpine/issues/637#issuecomment-654856538)ì„ ì¶”ê°€í•´ì•¼ 합니다. #### `x-for`s 중첩 `x-for`루프를 ì¤‘ì²©í• ìˆ˜ëŠ” 있지만, ì´ ê²½ìš° ê° ë£¨í”„ë¥¼ 요소로 ê°ì‹¸ì•¼í•©ë‹ˆë‹¤. ì˜ˆì œ: ```html <template x-for="item in items"> <div> <template x-for="subItem in item.subItems"> <div x-text="subItem"></div> </template> </div> </template> ``` #### 범위 ë‚´ì˜ ë°˜ë³µ Alpineì€ `i in n` êµ¬ë¬¸ì„ ì§€ì›í•˜ê³ , 여기서 `n`ì€ ì •ìˆ˜ì´ë©°, ê³ ì •ëœ ë²”ìœ„ì˜ ìš”ì†Œë“¤ì„ ë°˜ë³µí• ìˆ˜ 있습니다. ```html <template x-for="i in 10"> <span x-text="i"></span> </template> ``` --- ### `x-transition` **ì˜ˆì œ:** ```html <div x-show="open" x-transition:enter="transition ease-out duration-300" x-transition:enter-start="opacity-0 transform scale-90" x-transition:enter-end="opacity-100 transform scale-100" x-transition:leave="transition ease-in duration-300" x-transition:leave-start="opacity-100 transform scale-100" x-transition:leave-end="opacity-0 transform scale-90" >...</div> ``` ```html <template x-if="open"> <div x-transition:enter="transition ease-out duration-300" x-transition:enter-start="opacity-0 transform scale-90" x-transition:enter-end="opacity-100 transform scale-100" x-transition:leave="transition ease-in duration-300" x-transition:leave-start="opacity-100 transform scale-100" x-transition:leave-end="opacity-0 transform scale-90" >...</div> </template> ``` > 위 ì˜ˆì œëŠ” [Tailwind CSS](https://tailwindcss.com)ì˜ í´ëž˜ìŠ¤ë¥¼ 사용합니다. Alpineì€ ìš”ì†Œì˜ "ìˆ¨ì ¸ì§„" ìƒíƒœì™€ "보여진" ìƒíƒœ 사ì´ì˜ 다양한 ë‹¨ê³„ì— í´ëž˜ìŠ¤ë¥¼ ì 용하기 위해 6ê°€ì§€ì˜ ì„œë¡œ 다른 ì „í™˜ 지시ìžë“¤ì„ ì œê³µí•©ë‹ˆë‹¤. ì´ ì§€ì‹œìžë“¤ì€ `x-show` ë° `x-if` 모ë‘ì—ì„œ ìž‘ë™í•©ë‹ˆë‹¤. ì´ê²ƒë“¤ì€ VueJsì˜ ì „í™˜ 지시ìžì™€ ì •í™•ížˆ ë™ì¼í•œ ë™ìž‘ì„ í•œë‹¤. 단, ê·¸ë“¤ì€ ì¡°ê¸ˆ 다른 ë” í•©ë¦¬ì ì¸ ì´ë¦„ì„ ê°€ì§€ê³ ìžˆë‹¤: | 지침 | 설명 | | --- | --- | | `:enter` | ì „ì²´ 진입 단계ì—ì„œ ì ìš©ë¨. | | `:enter-start` | 요소가 삽입ë˜ê¸° ì „ì— ì¶”ê°€ë˜ê³ , 요소가 삽입ë˜ê³ 1 í”„ë ˆìž„ ì´í›„ì— ì‚ì œë¨. | | `:enter-end` | 요소가 삽입ë˜ê³ 1 í”„ë ˆìž„ ì´í›„ì— ì¶”ê°€ë˜ê³ (ë™ì‹œì— `enter-start`는 ì‚ì œë¨) ì „í™˜/ì• ë‹ˆë©”ì´ì…˜ 종료 후 ì‚ì œë¨. | `:leave` | ì „ì²´ ì´íƒˆ 단계ì—ì„œ ì ìš©ë¨. | | `:leave-start` | ì´íƒˆ ì „í™˜ì´ ë°œìƒë ë•Œ 즉시 추가ë˜ê³ , 1 í”„ë ˆìž„ 후 ì œê±°ë¨. | | `:leave-end` | ì´íƒˆ ì „í™˜ì´ ë°œìƒëœ 후 1 í”„ë ˆìž„ 후 추가ë˜ê³ (ë™ì‹œì— `leave-start`는 ì‚ì œë¨) ì „í™˜/ì• ë‹ˆë©”ì´ì…˜ 종료 후 ì‚ì œë¨. --- ### `x-spread` **ì˜ˆì œ:** ```html <div x-data="dropdown()"> <button x-spread="trigger">Open Dropdown</button> <span x-spread="dialogue">Dropdown Contents</span> </div> <script> function dropdown() { return { open: false, trigger: { ['@click']() { this.open = true }, }, dialogue: { ['x-show']() { return this.open }, ['@click.away']() { this.open = false }, } } } </script> ``` `x-spread`를 사용하면 ìš”ì†Œì˜ Alpine ë°”ì¸ë”©ì„ 재사용 가능한 ê°ì²´ë¡œ 추출 í• ìˆ˜ 있습니다. ê°ì²´ í‚¤ë“¤ì€ ì§€ì‹œìžë“¤ì´ë©°(ìˆ˜ì •ì‚¬ë¥¼ í¬í•¨í•´ ëª¨ë“ ì§€ì‹œìžê°€ ë 수 있습니다), ê°’ë“¤ì€ Alpineì— ì˜í•´ í‰ê°€ë˜ëŠ” 콜백입니다. > ì°¸ê³ : x-spreadì—는 몇 가지 주ì˜ì‚¬í•ì´ 있습니다: > - `x-for`ê°€ "spread" ì§€ì‹œìž ì¼ ë•Œ, 콜백ì—ì„œ 반드시 ì¼ë°˜ 문ìžì—´ 표현ì‹ì„ 반환해야 합니다. ì˜ˆì œ: `['x-for']() { return 'item in items' }`. > - "spread" ê°ì²´ ë‚´ì• ì„œ `x-data` 와 `x-init`는 ì‚¬ìš©í• ìˆ˜ 없습니다. --- ### `x-cloak` **ì˜ˆì œ:** `<div x-data="{}" x-cloak></div>` `x-cloak`ì†ì„±ë“¤ì€ Alpine ì´ˆê¸°í™”í• ë•Œ 요소ì—ì„œ ì œê±°ë©ë‹ˆë‹¤. ì´ê²ƒì€ 미리 ì´ˆê¸°í™”ëœ DOMì„ ìˆ¨ê¸°ëŠ”ë° ìœ ìš©í•©ë‹ˆë‹¤. ì´ ìž‘ì—…ì„ ìˆ˜í–‰í•˜ë ¤ë©´ 다ìŒê³¼ ê°™ì´ ì „ì— ìŠ¤íƒ€ì¼ì„ 추가하는 ê²ƒì´ ì¼ë°˜ì 입니다: ```html <style> [x-cloak] { display: none; } </style> ``` ### 마법 ì†ì„±ë“¤ > `$el`ì„ ì œì™¸í•˜ê³ , ì»´í¬ë„ŒíŠ¸ê°€ ì•„ì§ ì´ˆê¸°í™” ë˜ì§€ ì•Šì€ ìƒíƒœì—ì„œ 마법 ì†ì„±ë“¤ì„ **`x-data`ë‚´ì—ì„œ ì‚¬ìš©í• ìˆ˜ 없습니다.** --- ### `$el` **ì˜ˆì œ:** ```html <div x-data> <button @click="$el.innerHTML = 'foo'">Replace me with "foo"</button> </div> ``` `$el`ì€ ë£¨íŠ¸ ì»´í¬ë„ŒíŠ¸ DOM 노드를 ê²€ìƒ‰í•˜ëŠ”ë° ì‚¬ìš©í• ìˆ˜ 있는 마법 ì†ì„±ìž…니다. ### `$refs` **ì˜ˆì œ:** ```html <span x-ref="foo"></span> <button x-on:click="$refs.foo.innerText = 'bar'"></button> ``` `$refs`는 ì»´í¬ë„ŒíŠ¸ ë‚´ì— `x-ref`ë¡œ í‘œì‹œëœ DOM 요소를 ê²€ìƒ‰í•˜ëŠ”ë° ì‚¬ìš©í• ìˆ˜ 있는 마법 ì†ì„±ìž…니다. ì´ê²ƒì€ DOM 요소를 수ë™ìœ¼ë¡œ 조작해야 í• ë•Œ ìœ ìš©í•©ë‹ˆë‹¤. --- ### `$event` **ì˜ˆì œ:** ```html <input x-on:input="alert($event.target.value)"> ``` `$event`는 ì´ë²¤íŠ¸ 리스너 ë‚´ì—ì„œ 기본 브ë¼ìš°ì € "ì´ë²¤íŠ¸" ê°ì²´ë¥¼ ê²€ìƒ‰í•˜ëŠ”ë° ì‚¬ìš©í• ìˆ˜ 있는 마법 ì†ì„±ìž…니다. > ì°¸ê³ : $event ì†ì„±ì€ DOM 표현ì‹ì—서만 ì‚¬ìš©í• ìˆ˜ 있습니다. ìžë°”스í¬ë¦½íŠ¸ 함수 ë‚´ì—ì„œ $eventì— ì ‘ê·¼í•´ì•¼ 하는 ì‹¶ì€ ê²½ìš° ì§ì ‘ ì „ë‹¬í• ìˆ˜ 있습니다: `<button x-on:click="myFunction($event)"></button>` --- ### `$dispatch` **ì˜ˆì œ:** ```html <div @custom-event="console.log($event.detail.foo)"> <button @click="$dispatch('custom-event', { foo: 'bar' })"> <!-- í´ë¦í•˜ë©´, "bar" 콘솔로그가 ì¶œë ¥ë¨ --> </div> ``` **ì´ë²¤íŠ¸ ì „íŒŒì— ëŒ€í•œ ì°¸ê³ ì‚¬í•** [ì´ë²¤íŠ¸ 버블ë§](https://en.wikipedia.org/wiki/Event_bubbling)으로 ì¸í•´ ë™ì¼í•œ 중첩 ê³„ì¸µì— ìžˆëŠ” 노드ì—ì„œ ì „ë‹¬ëœ ì´ë²¤íŠ¸ë¥¼ 캡처해야 하는 경우 [`.window`](https://github.com/alpinejs/alpine#x-on)ìˆ˜ì •ìžë¥¼ 사용해야 합니다: **ì˜ˆì œ:** ```html <div x-data> <span @custom-event="console.log($event.detail.foo)"></span> <button @click="$dispatch('custom-event', { foo: 'bar' })"> <div> ``` > ì´ê²ƒì€ `custom-event`ê°€ ì „ë‹¬ë ë•Œ, 공통 ì¡°ìƒì¸ `div`ë¡œ ì „íŒŒë˜ê¸° ë•Œë¬¸ì— ìž‘ë™í•˜ì§€ 않습니다. **ì»´í¬ë„ŒíŠ¸ë¡œ ì „ë‹¬** ë˜í•œ ì´ì „ ê¸°ìˆ ì„ í™œìš©í•˜ì—¬ ì»´í¬ë„ŒíŠ¸ê°€ 서로 í†µì‹ í•˜ë„ë¡ í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤: **ì˜ˆì œ:** ```html <div x-data @custom-event.window="console.log($event.detail)"></div> <button x-data @click="$dispatch('custom-event', 'Hello World!')"> <!-- í´ë¦í•˜ë©´ "Hello World!" 콘솔로그가 ì¶œë ¥ë¨. --> ``` `$dispatch`는 `CustomEvent`를 ìƒì„±í•˜ê³ , 내부ì 으로 `.dispatchEvent()`를 사용하여 ê·¸ê²ƒì„ ì „ë‹¬í•˜ëŠ” 간단한 방법입니다. ì‚¬ìš©ìž ì§€ì • ì´ë²¤íŠ¸ë¥¼ ì´ìš©í•˜ì—¬ ì»´í¬ë„ŒíŠ¸ê°„ì— ë°ì´í„° ì „ë‹¬í•˜ëŠ” ìœ ìš©í•œ 사용사례가 ë§Žì´ ìžˆìŠµë‹ˆë‹¤. 브ë¼ìš°ì €ì˜ `CustomEvent`ì‹œìŠ¤í…œì— ëŒ€í•œ ìžì„¸í•œ ë‚´ìš©ì€ [ì´ê³³ì„ ì½ì–´ë³´ì„¸ìš”](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events). `$dispatch('some-event', { some: 'data' })`ì— ë‘ ë²ˆì§¸ 파ë¼ë©”í„°ë¡œ ì „ë‹¬ë˜ëŠ” ë°ì´í„°ëŠ” 새로운 ì´ë²¤íŠ¸ì˜ "detail"ì†ì„±: `$event.detail.some`ì„ ì´ìš©í•´ ì‚¬ìš©í• ìˆ˜ 있습니다. 브ë¼ìš°ì €ì—ì„œ `.detail`ì†ì„±ì— 사용ìží™” ì´ë²¤íŠ¸ ë°ì´í„°ë¥¼ 연결하는 ê²ƒì€ `CustomEvent`ì— ëŒ€í•œ 표준 관행입니다. ë” ìžì„¸í•œ ë‚´ìš©ì€ [ì´ê³³ì„ ì½ì–´ë³´ì„¸ìš”](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail). `x-model`ë¡œ ë°”ì¸ë”©ëœ ë°ì´í„°ì˜ ì—…ë°ì´íŠ¸ê°€ ë°œìƒí•˜ë„ë¡ `$dispatch()`를 ì‚¬ìš©í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. ì˜ˆì œ: ```html <div x-data="{ foo: 'bar' }"> <span x-model="foo"> <button @click="$dispatch('input', 'baz')"> <!-- 버튼 í´ë¦ ì´í›„, `x-model`ì€ ë²„ë¸”ë§ëœ "input" ì´ë²¤íŠ¸ë¥¼ í¬ì°©í•˜ê³ , foo를 "baz"ë¡œ ì—…ë°ì´íŠ¸ 함. --> </span> </div> ``` > ì°¸ê³ : $dispatch ì†ì„±ì€ DOM 표현ì‹ì—서만 사용 가능합니다. ìžë°”스í¬ë¦½íŠ¸ 함수ì—ì„œ $dispatchì— ì ‘ê·¼í•˜ê³ ì‹¶ì€ ê²½ìš° ì§ì ‘ ì „ë‹¬í• ìˆ˜ 있습니다: `<button x-on:click="myFunction($dispatch)"></button>` --- ### `$nextTick` **ì˜ˆì œ:** ```html <div x-data="{ fruit: 'apple' }"> <button x-on:click=" fruit = 'pear'; $nextTick(() => { console.log($event.target.innerText) }); " x-text="fruit" ></button> </div> ``` `$nextTick`ì€ Alpineì´ ë°˜ì‘형 DOM ì—…ë°ì´íŠ¸ë¥¼ 수행한 ì´í›„ì—만 주어진 표현ì‹ì´ 실행ë˜ë„ë¡ í•˜ëŠ” 마법 ì†ì„±ìž…니다. ì´ê²ƒì€ ë‹¹ì‹ ì´ ë§Œë“ ë°ì´í„° ì—…ë°ì´íŠ¸ê°€ ë°˜ì˜ëœ DOMê³¼ ìƒí˜¸ìž‘ìš©í•˜ê³ ìž í• ë•Œ ìœ ìš©í•©ë‹ˆë‹¤. --- ### `$watch` **ì˜ˆì œ:** ```html <div x-data="{ open: false }" x-init="$watch('open', value => console.log(value))"> <button @click="open = ! open">Toggle Open</button> </div> ``` `$watch`마법 메소드를 통해 ì»´í¬ë„ŒíŠ¸ ì†ì„±ì„ "ê°ì‹œ"í• ìˆ˜ìžˆìŠµë‹ˆë‹¤. 위 ì˜ˆì œì—ì„œ, ë²„íŠ¼ì´ í´ë¦ë˜ë©´ `open`ì´ ë³€ê²½ë˜ê³ , ì œê³µëœ ì½œë°±ì´ ì‹¤í–‰ë˜ë©° `console.log`ì— ìƒˆë¡œìš´ ê°’ì´ ì¶œë ¥ë©ë‹ˆë‹¤. ## Security 보안 취약ì ì„ ë°œê²¬í•˜ë©´, [calebporzio@gmail.com]()으로 ë©”ì¼ì„ 보내주세요. Alpineì€ ì§€ì‹œìžì„ í‰ê°€í•˜ê¸° 위해 `Function` ê°ì²´ë¥¼ 사용하는 ì‚¬ìš©ìž ì •ì˜ êµ¬í˜„ì— ì˜ì¡´í•©ë‹ˆë‹¤. `eval ()`보다 ë” ì•ˆì „í•˜ì§€ë§Œ Google Chrome 앱과 ê°™ì€ ì¼ë¶€ 환경ì—서는 ì œí•œì ì¸ ì½˜í…ì¸ ë³´ì•ˆ ì •ì±…(CSP)ì„ ì‚¬ìš©í•˜ì—¬ ì‚¬ìš©ì´ ê¸ˆì§€ë©ë‹ˆë‹¤. 민ê°í•œ ë°ì´í„°ë¥¼ ë‹¤ë£¨ê³ [CSP](https://csp.withgoogle.com/docs/strict-csp.html)ê°€ 필요한 웹 사ì´íŠ¸ì—ì„œ Alpineì„ ì‚¬ìš©í•˜ëŠ” 경우, ì •ì±…ì— `unsafe-eval`ì„ í¬í•¨í•´ì•¼í•©ë‹ˆë‹¤. 올바르게 êµ¬ì„±ëœ ê°•ë ¥í•œ ì •ì±…ì€ ê°œì¸ ë˜ëŠ” 금융 ë°ì´í„°ë¥¼ ì‚¬ìš©í• ë•Œ 사용ìžë¥¼ 보호하는 ë° ë„움ì´ë©ë‹ˆë‹¤. ì •ì±…ì´ íŽ˜ì´ì§€ì˜ ëª¨ë“ ìŠ¤í¬ë¦½íŠ¸ì— ì ìš©ë˜ë¯€ë¡œ 웹 사ì´íŠ¸ì— í¬í•¨ ëœ ë‹¤ë¥¸ 외부 ë¼ì´ë¸ŒëŸ¬ë¦¬ë¥¼ ì‹ ì¤‘í•˜ê²Œ ê²€í† í•˜ì—¬ ì‹ ë¢°í• ìˆ˜ ìžˆê³ `eval()`함수를 사용하여 êµì°¨ 사ì´íŠ¸ 스í¬ë¦½íŒ… 취약ì ë˜ëŠ” DOMì„ ì¡°ìž‘í•˜ì—¬ 페ì´ì§€ì— 악성 코드를 ì‚½ìž…ì„ ìœ ë°œí•˜ì§€ 않는지 확ì¸í•˜ëŠ” ê²ƒì´ ì¤‘ìš”í•©ë‹ˆë‹¤. ## V3 Roadmap * Vue와 ë™ë“±í•˜ê²Œ `x-ref`ì—ì„œ `ref`ë¡œ 변경? * `Alpine.directive()` 추가 * `Alpine.component('foo', {...})`(ë§¤ì§ `__init()`메소드 사용) 추가 * "loaded", "transition-start", ê·¸ 외...([#299](https://github.com/alpinejs/alpine/pull/299))ì— ëŒ€í•œ Alpineì´ë²¤íŠ¸ ì „ë‹¬? * `x-bind:class="{ 'foo': true }"`ì—ì„œ "ê°ì²´"(ê·¸ë¦¬ê³ ë°°ì—´) ì œê±°([#236](https://github.com/alpinejs/alpine/pull/236) `style` ì†ì„±ì— 대한 ê°ì§€ 구문 ì§€ì› ì¶”ê°€) * `x-for`ë³€ì´ ë°˜ì‘성 ê°œì„ ([#165](https://github.com/alpinejs/alpine/pull/165)) * Add "deep watching" support in V3 ([#294](https://github.com/alpinejs/alpine/pull/294)) * V3ì— "ê¹Šì€ ê°ì‹œ" ì§€ì› ì¶”ê°€ ([#294](https://github.com/alpinejs/alpine/pull/294)) * `$el` 간편한 방법 추가 * `@click.away`를 `@click.outside`ë¡œ 변경? ## ë¼ì´ì„¼ìŠ¤ ì €ìž‘ê¶Œ © 2019-2021 Caleb Porzio 와 기여ìžë“¤ MIT ë¼ì´ì„¼ìŠ¤ì— ë”°ë¼ í—ˆê°€ë˜ë©°, ë” ìžì„¸í•œ ë‚´ìš©ì€ [LICENSE.md](LICENSE.md)를 확ì¸í•˜ì„¸ìš”.