์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

[Alpine.js] Alpine.js ์‹œ์ž‘ํ•˜๊ธฐ

developer of the night sky 2023. 12. 22. 17:38

 

Alpine.js๐Ÿ”Ž

HTML์— ์ธ๋ผ์ธ JavaScript๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•œ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

์•ŒํŒŒ์ธ.js๋Š” ๊ฐ€๋ฒผ์šฐ๋ฉด์„œ๋„ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉฐ, ๋‹ค๋ฅธ ๋ณต์žกํ•œ ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋น„ํ•ด ์ง„์ž… ์žฅ๋ฒฝ์ด ๋‚ฎ๋‹ค.

๊ณต์‹ ์‚ฌ์ดํŠธ์— ์‚ฌ์šฉ๋ฐฉ๋ฒ•์ด ๋งค์šฐ ์ž˜ ๋‚˜ํƒ€๋‚˜ ์žˆ๋‹ค.

 

๊ณต์‹ ์‚ฌ์ดํŠธ :

https://alpinejs.dev/start-here

 

Start Here — Alpine.js

Start Here Create a blank HTML file somewhere on your computer with a name like: i-love-alpine.html Using a text editor, fill the file with these contents: Open your file in a web browser, if you see I โค๏ธ Alpine, you're ready to rumble! Now that you're

alpinejs.dev

 


Alpine.js ์‹œ์ž‘ํ•˜๊ธฐ๐Ÿ”Ž

๊ฐœ๋ฐœ ํˆด์€ VS Code ๋กœ ์ž‘์—…ํ•˜์˜€๋‹ค.

 

index.html

<html>
<head>
    <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body>
    <h1 x-data="{ message: 'I Love Alpine' }" x-text="message"></h1>
</body>
</html>

 

 

 

 

- ์ฆ๊ฐ ์นด์šดํ„ฐ ๋งŒ๋“ค๊ธฐ

CMD ๊ฐ€์ ธ์˜ค๊ธฐ

์•ŒํŒŒ์ธ.js ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜ ํ•œ์ค„์„ ํ—ค๋”์— ์ถ”๊ฐ€ํ•œ๋‹ค.

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

 

    <div x-data="{count:0}">
        <button x-on:click="count--">minus(-)</button>
        <span x-text="count"></span>
        <button x-on:click="count++">plus(+)</button>
    </div>

 

๊ฐ„๋‹จํ•˜๊ฒŒ ์ˆซ์ž๋ฅผ ์นด์šดํŠธ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ„ํŠผ๊ณผ ๊ฐ’์„ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

์ด ์ฝ”๋“œ์—์„œ๋Š” 3๊ฐœ์˜ ์†์„ฑ์œผ๋กœ ์นด์šดํ„ฐ๋ฅผ ๊ตฌ์„ฑํ•˜์˜€๋‹ค.

 

1. ๋ฐ์ดํ„ฐ ์„ ์–ธ

<div x-data="{ count: 0 }">

 

Alpine์˜ ๋ชจ๋“  ๊ฒƒ์€ x-data์ง€์‹œ๋ฌธ์œผ๋กœ ์‹œ์ž‘๋œ๋‹ค. 

๋‚ด๋ถ€์—์„œ๋Š” x-data์ผ๋ฐ˜ JavaScript๋กœ Alpine์ด ์ถ”์ ํ•  ๋ฐ์ดํ„ฐ ๊ฐ์ฒด๋ฅผ ์„ ์–ธํ•œ๋‹ค.

 

 

 2. ์ด๋ฒคํŠธ ์ˆ˜์‹ 

<button x-on:click="count++">Increment</button>

 

x-on์š”์†Œ๋Š” ๋ชจ๋“  ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ง€์‹œ์–ด์ด๋‹ค.

x-on:click์€ click ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•œ๋‹ค.

mouseenter ์ด๋ฒคํŠธ๋Š” x-on:mouseenter ์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•œ๋‹ค.

 

3. ๋ณ€ํ™”์— ๋ฐ˜์‘

<h1 x-text="count"></h1>

 

x-text์š”์†Œ๋Š” ํ…์ŠคํŠธ ๋‚ด์šฉ์„ JavaScript ํ‘œํ˜„์‹์˜ ๊ฒฐ๊ณผ๋กœ ์„ค์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” Alpine ์ง€์‹œ๋ฌธ์ด๋‹ค.

์œ„์—์„œ x-data๋กœ ์„ ์–ธํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค.

 

 

- ๋“œ๋กญ๋‹ค์šด ๋งŒ๋“ค๊ธฐ

     <div x-data="{open: false}">
        <button @click="open =! open">Toggle</button>
        
        <div x-show="open" @click.outside="open = false">about dropdown</div>
     </div>

๊ฐ„๋‹จํ•˜๊ฒŒ ํ† ๊ธ€ ๋ฒ„ํŠผ์„ ์ƒ์„ฑํ•˜์˜€๋‹ค.

 

1. ์š”์†Œ ์ „ํ™˜

<div x-show="open" ...>Contents...</div>

 

x-show ๋Š” ํŽ˜์ด์ง€์—์„œ HTML ๋ธ”๋ก์„ ํ‘œ์‹œํ•˜๊ณ  ์ˆจ๊ธฐ๋Š”๋ฐ ์‚ฌ์šฉํ•˜๋Š” ์ง€์‹œ์–ด์ด๋‹ค.

 

2. ์™ธ๋ถ€์—์„œ๋„ ํด๋ฆญ ์ˆ˜์‹ ํ•˜๊ธฐ

<div ... @click.outside="open = false">Contents...</div>

 

@click.outside ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋“œ๋กญ๋‹ค์šด ์™ธ๋ถ€๋ฅผ ํด๋ฆญํ•  ๋•Œ open ๋ณ€์ˆ˜๋ฅผ false๋กœ ์„ค์ •ํ•˜์—ฌ ๋“œ๋กญ๋‹ค์šด์„ ๋‹ซ๋Š”๋‹ค. ์ด ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋“œ๋กญ๋‹ค์šด์ด ์—ด๋ฆฐ ์ƒํƒœ์—์„œ ๋‹ค๋ฅธ ๊ณณ์„ ํด๋ฆญํ•ด๋„ ๋“œ๋กญ๋‹ค์šด์ด ๋‹ซํžŒ๋‹ค.

 

 

- ๊ฒ€์ƒ‰ํ•˜๊ธฐ

     <div
        x-data="{
            search: '',

            items: ['susu', 'kkang', 'Heo'],

            get filteredItems() {
                return this.items.filter (
                    i => i.startsWith(this.search)
                )
            }
        }">

        <input x-model="search" placeholder="Search...">

        <ul>
            <template x-for="item in filteredItems" :key="item">
                <li x-text="item"></li>
            </template> 
        </ul>
     </div>

 

๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ํ•ญ๋ชฉ์ด ํŽ˜์ด์ง€์— ํ‘œ์‹œ๋˜๊ณ  ํ…์ŠคํŠธ ์ž…๋ ฅ์„ ํ•˜๋ฉด ํ•„ํ„ฐ๋ง์„ ํ•œ๋‹ค.

์ž…๋ ฅํ•˜๋Š” ๋™์•ˆ ๋ชฉ๋ก์€ ๊ฒ€์ƒ‰์ค‘์ธ ๋‚ด์šฉ์„ ๋ฐ˜์˜ํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ๋‹ค.

 

1. ๊ฒŒํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ„์‚ฐ๋œ ์†์„ฑ

<div
    x-data="{
        search: '',
 
        items: ['foo', 'bar', 'baz'],
 
        get filteredItems() {
            return this.items.filter(
                i => i.startsWith(this.search)
            )
        }
    }"
>

 

items ์œผ๋กœ JavaScript ๋ฐฐ์—ด์— ๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค.

 

get filteredItems()

x-data ๋””๋ ‰ํ‹ฐ๋ธŒ ๋‚ด์—์„œ ์„ ์–ธ๋˜์–ด JavaScript์˜ ๊ฒŒํ„ฐ(getter) ๋ฉ”์„œ๋“œ๋กœ ์ž‘๋™ํ•œ๋‹ค.

๊ฐ์ฒด์˜ ์†์„ฑ์ฒ˜๋Ÿผ ์ ‘๊ทผ๋˜์ง€๋งŒ ํ•จ์ˆ˜์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

get ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, filteredItems๋ฅผ ๋งˆ์น˜ ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ํ•จ์ˆ˜๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์•ŒํŒŒ์ธ์€ filteredItems๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•จ์œผ๋กœ์จ ์ฝ”๋“œ๊ฐ€ ๋” ๊ฐ„๊ฒฐํ•˜๊ณ  ์ฝ๊ธฐ ์‰ฌ์›Œ์ง€๋ฉฐ, ๊ณ„์‚ฐ๋œ ์†์„ฑ์ด ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ๊ฐฑ์‹ ๋  ์ˆ˜ ์žˆ๋‹ค.

 

filteredItems ํ•จ์ˆ˜๋Š” ํ˜„์žฌ ๊ฒ€์ƒ‰์–ด์— ๋”ฐ๋ผ ํ•„ํ„ฐ๋ง๋œ ํ•ญ๋ชฉ๋“ค์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋กœ ์ •์˜ํ•˜์˜€๋‹ค.

 

this

์œ„์—์„œ๋Š” ์†์„ฑ์„ ์ฐธ์กฐํ•˜๋Š”๋ฐ just ์†์„ฑ๋ช…๋งŒ ์‚ฌ์šฉํ•˜์˜€๋‹ค. ํ•˜์ง€๋งŒ  x-data ๊ฐ์ฒด ๋‚ด์—์„œ ์ง์ ‘ ์ž‘์—…ํ•˜๊ณ  ์žˆ์„ ๋•Œ๋Š” ๋‹ค๋ฅด๋‹ค.

x-data ๊ฐ์ฒด ๋‚ด์—์„œ ์†์„ฑ์„ ์ฐธ์กฐํ•  ๋•Œ๋Š” [property] ๋Œ€์‹ ์— this.[property]๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

 

2. ์ž…๋ ฅ์— ๋ฐ”์ธ๋”ฉ

<input x-model="search" placeholder="Search...">

 

x-model ์€ ์ž…๋ ฅ ์š”์†Œ์˜ ๊ฐ’์„ ๋ฐ์ดํ„ฐ ์†์„ฑ๊ณผ "๋ฐ”์ธ๋”ฉ"ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

์ฆ‰, ์ž…๋ ฅ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค "search" ์˜ ๊ฐ’๋„ ์ด๋ฅผ ๋ฐ˜์˜ํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ๋‹ค.

 

3. ๋ฐ˜๋ณต ์š”์†Œ

    <ul>
        <template x-for="item in filteredItems" :key="item">
            <li x-text="item"></li>
        </template>
    </ul>

 

x-for

x-forํ‘œํ˜„์‹์€ [item] in [items]  ํ˜•์‹์œผ๋กœ ์ทจํ•œ๋‹ค. 

์—ฌ๊ธฐ์„œ [items]๋Š” ๋ฐ์ดํ„ฐ ๋ฐฐ์—ด์ด๊ณ  [item]์€ ๋ฃจํ”„ ๋‚ด๋ถ€ ๋ฐ˜๋ณต์— ํ• ๋‹น๋  ๋ณ€์ˆ˜์˜ ์ด๋ฆ„์ด๋‹ค.

x-for ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ filteredItems ๋ฐฐ์—ด์„ ์ˆœํšŒํ•˜๋ฉด์„œ ๊ฐ ํ•ญ๋ชฉ์— ๋Œ€ํ•œ <li>(๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ)๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

 

:key 

:key ๋ฐ”์ธ๋”ฉ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ํ•ญ๋ชฉ์— ๊ณ ์œ ํ•œ ํ‚ค๋ฅผ ๋ถ€์—ฌํ•œ๋‹ค. x-text ๋””๋ ‰ํ‹ฐ๋ธŒ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ์— ํ•ด๋‹น ํ•ญ๋ชฉ์˜ ํ…์ŠคํŠธ๋ฅผ ํ‘œ์‹œํ•œ๋‹ค.

๋˜ํ•œ, ๊ฐ ์š”์†Œ์— ๋Œ€ํ•ด ํŠน์ •ํ•œ ๊ฐ’์„ ์ง€์ •ํ•˜๋ฉฐ, ์ด ๊ฐ’์€ ํ•ด๋‹น ์š”์†Œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ ํ”„๋ ˆ์ž„์›Œํฌ์—๊ฒŒ ์–ด๋–ค ์š”์†Œ๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋Š”์ง€ ์•Œ๋ ค์ค€๋‹ค.