3. Vue Router ๐Ÿ‘ฉโ€๐Ÿ’ป

1. Installation

vue create๋ฅผ ํ†ตํ•ด ํ”„๋กœ์ ํŠธ ์ƒ์„ฑํ•  ๋•Œ Router๋ฅผ ํ”„๋กœ์ ํŠธ์— ์„ค์ •ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ์„ค์น˜ํ•œ๋‹ค.

vue add router

@vue/cli-plugin-router๊ฐ€ ์„ค์น˜๋˜๋ฉฐ, src ์•„๋ž˜ router, view ๋””๋ ‰ํ† ๋ฆฌ ๋ฐ ํŒŒ์ผ์ด ์ƒ์„ฑ๋œ๋‹ค.

2. Run App with Vue Router

1 ) main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App).use(router).mount('#app')

  • node_modules์—์„œ vue ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ๋ถ€ํ„ฐ createApp์„ ๊ฐ€์ ธ์˜จ๋‹ค.
  • ./App.vue๋ฅผ App์œผ๋กœ ๊ฐ€์ ธ์˜จ๋‹ค(์ž๋™์œผ๋กœ default export ๊ฐ€ ์ ์šฉ๋œ๋‹ค).
  • ./router/index.js๋ฅผ router๋กœ ๊ฐ€์ ธ์˜จ๋‹ค.
    (ํŒŒ์ผ๋ช…์ด index ์ผ ๊ฒฝ์šฐ๋Š” ์ƒ๋žต ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ โ€˜./routerโ€™ ๋กœ ์ ์„ ์ˆ˜ ์žˆ๋‹ค.
    index.js ํŒŒ์ผ์„ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด export default router ๋ฅผ ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— import { router }๋กœ ์ ์ง€ ์•Š๊ณ  { }๋กœ ์ ๋Š”๋‹ค).

index.html document ๋ฅผ ๋ฐ›์€ ํ›„ ์•ฑ์ด Vue๋ฅผ ํ†ตํ•ด ์‹œ์ž‘๋˜๋Š” Entry Point๋‹ค.


2 ) App.vue

<template>
  <nav>
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link>
  </nav>
  <router-view/>
</template>
  • โ€ : Vue์— ์˜ํ•ด <a href=""></a> HTML ์ด ์ž๋™ ์ƒ์„ฑ๋œ๋‹ค.

  • : ๋ผ์šฐํ„ฐ์— ์˜ํ•ด ๋งค์นญ๋œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ด ๊ณณ์— ๋ Œ๋”๋ง ๋œ๋‹ค.


3 ) index.js

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

  • node_modules์—์„œ vue-router ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ๋ถ€ํ„ฐ createRouter๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค(createWebHistory๋Š” optional).
  • ๋ผ์šฐํ„ฐ๋ฅผ ์ƒ์„ฑํ•œ๊ณ , ์ด ๋ผ์šฐํ„ฐ๋ฅผ default๋กœ exportํ•œ๋‹ค.


routes Object ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑ๋œ๋‹ค.

  • path : ๋ผ์šฐํ„ฐ์˜ endopoint
  • name : ๋ผ์šฐํ„ฐ์˜ ์ด๋ฆ„
  • component : Vue ์ปดํฌ๋„ŒํŠธ
    (component: HomeView์ฒ˜๋Ÿผ import HomeView from '../views/HomeView.vue'๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜๋„ ์žˆ๊ณ ,
    component: () => import('../views/AboutView.vue')์™€ ๊ฐ™์ด ํด๋กœ์ €๋ฅผ ์ด์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.)

3. Lazy Load

Vue CLI 3๋ถ€ํ„ฐ prefetch ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜์–ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฏธ๋ฆฌ ๋กœ๋”ฉํ• ์ง€, Lazy ๋กœ๋”ฉํ• ์ง€๋ฅผ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ true๋กœ ๋ณ„๋„๋กœ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด prefetch๋กœ ์ž‘๋™๋œ๋‹ค.

prefetch๋ฅผ ์ ์šฉํ•˜๋ฉด, ์ตœ์ดˆ ์•ฑ ๋กœ๋”ฉ ํ›„ ๋น ๋ฅธ ์†๋„๋ฅผ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ˜๋ฉด ์ดˆ๊ธฐ ๋กœ๋”ฉ์ด ๋Š๋ ค์ง„๋‹ค. ๋”ฐ๋ผ์„œ prefetch๋ฅผ ์ ์šฉํ•  ๊ณณ๊ณผ ์ ์šฉํ•˜์ง€ ์•Š์„ ๊ณณ์„ ๊ตฌ๋ณ„ํ•ด ์ดˆ๊ธฐ ๋กœ๋”ฉ ์†๋„๋ฅผ ๋น ๋ฅด๊ฒŒ ํ•˜๋ฉด์„œ, ์ผ๋ถ€ ๋ฌด๊ฑฐ์šด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ ์ ˆํžˆ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ํ•„์š”ํ•˜๋‹ค.

๋‹ค์Œ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

1 ) prefetch true

prefetch๋Š” ๋ณ„๋„๋กœ ๋„์ง€ ์•Š์œผ๋ฉด Vue CLI 3์—์„œ๋Š” ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ true๋ฅผ ๊ฐ–๋Š”๋‹ค.
๋”ฐ๋ผ์„œ, Lazy ๋กœ๋”ฉ์ด ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ import์— /* webpackChunkName: "about" */ ์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ด ๋ณ„๋„์˜ ํŒŒ์ผ๋กœ ๋นŒ๋“œํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ์„ chunk๋ฅผ ๋งŒ๋“ ๋‹ค๊ณ  ํ•˜๋ฉฐ, ์ด ๊ฒฝ์šฐ about.js๋ผ๋Š” ํŒŒ์ผ์„ ๋ถ„๋ฆฌ ๋นŒ๋“œํ•œ๋‹ค.

const Home = () => import(/* webpackChunkName: "home" */ './Home.vue');
const About = () => import(/* webpackChunkName: "about" */ './About.vue');
const Contact = () => import(/* webpackChunkName: "contact" */ './Contact.vue');


2 ) prefetch false

๊ธฐ๋ณธ์ ์œผ๋กœ prefetch๋ฅผ ๊บผ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ธฐ๋ณธ์ ์œผ๋กœ Lazy ๋กœ๋”ฉ๋˜๋„๋ก ํ•œ ํ›„, prefetch๊ฐ€ ํ•„์š”ํ•œ ๊ณณ์„ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ๋‹ค. ์œ„ ๋ฐฉ๋ฒ•๊ณผ ์ • ๋ฐ˜๋Œ€ ๋˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์šฐ์„  vue.config.js์—์„œ prefetch๋ฅผ ๋„๋„๋ก ํ•œ๋‹ค.

module.exports = {
  chainWebpack: config => {
    config.plugin.delete('prefetch');
  }
}

๊ทธ๋ฆฌ๊ณ  prefetch๊ฐ€ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ import์— /* webpackPrefetch: true */ ์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

{
  path: '/about',
  name: 'about',
  component: () => import(/* webpackPrefetch: true */ '../views/AboutView.vue')
}

4. Vue Component ๐Ÿ‘ฉโ€๐Ÿ’ป

Component Structures

<template>
  <div></div>
</template>

<script>
export default {
  name: "",         // ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„(ํ•„์ˆ˜๊ฐ’์€ ์•„๋‹˜)
  components: {},   // ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ๋ฅผ import
  data() {          // html ๊ณผ javascript ์—์„œ ์‚ฌ์šฉํ•  ๋ฐ์ดํ„ฐ ๋ณ€์ˆ˜๋กœ `Vue`์— ์˜ํ•ด ์ปจํŠธ๋กค
    return {}
  },
  setup() {         // (Lifecycle Hooks) Composition API
  },
  created() {       // (Lifecycle Hooks) ์ปดํฌ๋„ŒํŠธ init ํ›„
  },
  mounted() {       // (Lifecycle Hooks) ์ปดํฌ๋„ŒํŠธ initial render ํ›„
  },
  unmounted() {     // (Lifecycle Hooks) ์ปดํฌ๋„ŒํŠธ ์–ธ๋งˆ์šดํŠธ ์‹œ
  },
  methods: {},      // ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ๋ฉ”์„œ๋“œ
}
</script>

<style scoped>

</style>

Vue Lifecycle Hookds


5. Data Binding โ€˜v-modelโ€™ ๐Ÿ‘ฉโ€๐Ÿ’ป

Vue๋Š” Anlgular์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Two-way data binding์„ ์ง€์›ํ•œ๋‹ค.

1. Text Data Binding

{{ someData }} ๋กœ ๋ฐ”์ธ๋”ฉ ํ•œ๋‹ค.

<template>
  <div>{{ someData }}</div>
</template>

<script>
export default {
  data() {
    return {
      someData: `Some Text`
    }
  },
}
</script>

2. Raw HTML Data Binding

{{ someData }} ๋กœ ์ž‘์„ฑํ•  ๊ฒฝ์šฐ ๋‹จ์ˆœ ํ…์ŠคํŠธ๋กœ ์ธ์‹๋˜๊ธฐ ๋•Œ๋ฌธ์— v-html directive ๋ฅผ ์ด์šฉํ•ด

<div v-html="someData"></div> ๋กœ ๋ฐ”์ธ๋”ฉ ํ•œ๋‹ค.

<template>
  <div v-html="someData"></div>
</template>

<script>
export default {
  data() {
    return {
      someData: `<Some HTML></Some HTML>`
    }
  },
}
</script>
  • <div v-html="someData"></div> ๋˜๋Š” <span v-html="someData"></span> ์™€ ๊ฐ™์ด children์ด ์—†๋Š” ๋นˆ element๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • <div v-html="someData"></div>์˜ children์ด export ๋˜๋Š” element ๋กœ override ๋œ๋‹ค.


Raw HTML Data Binding Examples

<template>
  <div v-html="someHtml"></div>
</template>

<script>
export default {
  data() {
    return {
      someHtml: `<p style="color: red;">This is red.</p>`
    }
  },
}
</script>

Raw HTML Data Binding

3. Form input type="text"

v-model directive ๋ฅผ ์ด์šฉํ•ด

<input type=โ€textโ€ v-model=โ€someValueโ€> ๋กœ ๋ฐ”์ธ๋”ฉ ํ•œ๋‹ค.

<template>
  <input type="text" v-model="someValue">
</template>

<script>
export default {
  data() {
    return {
      someValue: `Some Text`
    }
  },
}
</script>

4. Form input type="number"

v-model.number directive ๋ฅผ ์ด์šฉํ•ด

<input type=โ€tnumberโ€ v-model=โ€someNumberโ€> ๋กœ ๋ฐ”์ธ๋”ฉ ํ•œ๋‹ค.

<template>
  <input type="number" v-model.number="someNumber">
</template>

<script>
export default {
  data() {
    return {
      someNumber: 0
    }
  },
}
</script>

5. Form textarea

<textarea>{{ someText }}</textarea>์ผ ๊ฒƒ ๊ฐ™์ง€๋งŒ JavaScript๊ฐ€ .innerText๊ฐ€ ์•„๋‹Œ .value๋กœ ์ ‘๊ทผํ•˜๊ธฐ ๋Œ€๋ฌธ์— ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ v-model directive ๋ฅผ ์ด์šฉํ•ด

<textarea v-model=โ€someValueโ€></textarea> ๋กœ ๋ฐ”์ธ๋”ฉ ํ•œ๋‹ค.

<template>
  <textarea v-model="someValue"></textarea>
</template>

<script>
export default {
  data() {
    return {
      someValue: `Some Text`
    }
  },
}
</script>

6. Form select

v-model directive ๋ฅผ ์ด์šฉํ•ด

<select v-model=โ€someValueโ€></select> ๋กœ ๋ฐ”์ธ๋”ฉ ํ•œ๋‹ค.

<template>
  <select v-model="someValue">
    <option value="value01">Value 01</option>
    <option value="value02">Value 02</option>
    <option value="value03">Value 03</option>
  </select>
</template>

<script>
export default {
  data() {
    return {
      someValue: `value01`
    }
  },
}
</script>


๋˜ํ•œ ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ฐ’์ด ์•„๋‹Œ ๊ณ ์ •๊ฐ’์ด ์ง€์ •๋˜๋Š” select box ๋˜๋Š” radio button์˜ ๊ฒฝ์šฐ value๋ฅผ HTML ์— ๊ฐ’์„ ๊ณ ์ •ํ•˜์ง€ ์•Š๊ณ  v-bind:value directive ๋ฅผ ์ด์šฉํ•ด ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ๋‹ค.

<option v-bind:value=โ€value01โ€></option> ๋กœ ๋ฐ”์ธ๋”ฉ ํ•œ๋‹ค.

<template>
  <select v-model="someValue">
    <option v-bind:value="value01">Value 01</option>
    <option v-bind:value="value02">Value 02</option>
    <option v-bind:value="value03">Value 03</option>
  </select>
</template>

<script>
export default {
  data() {
    return {
      someValue: `value01`,
      value01: `value01`,
      value02: `value02`,
      value03: `value03`,
    }
  },
}
</script>

7. Form input type="checkbox"

JavaScript๊ฐ€ .value๊ฐ€ ์•„๋‹Œ .checked๋กœ ์ ‘๊ทผํ•˜์ง€๋งŒ value ์ ‘๊ทผ์œผ๋กœ ์ทจ๊ธ‰ํ•ด v-model directive ๋ฅผ ์ด์šฉํ•ด

<input type=โ€checkboxโ€ v-model=โ€someBooleanโ€> ๋กœ ๋ฐ”์ธ๋”ฉ ํ•œ๋‹ค.

<template>
  <input type="checkbox" v-model="someBoolean">
</template>

<script>
export default {
  data() {
    return {
      someBoolean: true
    }
  },
}
</script>

8. Form input type="radio"

6. select box ์™€ ๋™์ผํ•˜๊ฒŒ v-model๊ณผ v-bind:value๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

์›๋ž˜ radio button์€ name์„ ๋™์ผํ•˜๊ฒŒ ํ•ด์ค˜์•ผํ•˜์ง€๋งŒ, ๋ณ„๋„๋กœ name์„ ์„ค์ •ํ•˜์ง€ ์•Š์•„๋„ v-model ๋ฐ”์ธ๋”ฉ์— ์˜ํ•ด ํ•˜๋‚˜์˜ ๊ฐ’๋งŒ ์„ ํƒ๋œ๋‹ค.

<template>
  <select v-model="someValue">
    <option value="value01">Value 01</option>
    <option value="value02">Value 02</option>
    <option value="value03">Value 03</option>
  </select>
  <div>
    <label for="radio01"><input type="radio" v-bind:value="value01" id="radio01" v-model="someChecked">์„œ์šธ</label>
    <label for="radio02"><input type="radio" v-bind:value="value02" id="radio02" v-model="someChecked">๋ถ€์‚ฐ</label>
    <label for="radio03"><input type="radio" v-bind:value="value03" id="radio03" v-model="someChecked">์ œ์ฃผ</label>
  </div>
</template>

<script>
export default {
  data() {
    return {
      someChecked: `value01`
    }
  },
}
</script>


<template>
  <select v-model="someValue">
    <option v-bind:value="value01">Value 01</option>
    <option v-bind:value="value02">Value 02</option>
    <option v-bind:value="value03">Value 03</option>
  </select>
  <div>
    <label for="radio01"><input type="radio" v-bind:value="value01" id="radio01" v-model="someChecked">์„œ์šธ</label>
    <label for="radio02"><input type="radio" v-bind:value="value02" id="radio02" v-model="someChecked">๋ถ€์‚ฐ</label>
    <label for="radio03"><input type="radio" v-bind:value="value03" id="radio03" v-model="someChecked">์ œ์ฃผ</label>
  </div>
</template>

<script>
export default {
  data() {
    return {
      someChecked: `value01`,
      value01: `value01`,
      value02: `value02`,
      value03: `value03`,
    }
  },
}
</script>

6. Data Binding โ€˜v-bind:xโ€™ for Attributes ๐Ÿ‘ฉโ€๐Ÿ’ป

HTML ์˜ attributes ๋ฅผ ๋ฐ”์ธ๋”ฉ ํ•  ๋•Œ value ๋ฅผ ์ œ์™ธํ•œ attributes ๋Š” v-bind:x๋ฅผ ์ด์šฉํ•ด ๋ฐ”์ธ๋”ฉ ํ•˜๋ฉฐ, v-bind๋ฅผ ์ƒ๋žตํ•ด :x๋กœ ๋ฐ”์ธ๋”ฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.

1. img > src

v-bind:scr directive ๋ฅผ ์ด์šฉํ•œ๋‹ค.

<template>
  <img :src="myBlogFavicon">
</template>

<script>
export default {
  data() {
    return {
      myBlogFavicon: `https://sbpark88.github.io/assets/images/favicon/greendreamtree.png`
    }
  },
}
</script>

2. button > disabled

v-bind:diabled directive ๋ฅผ ์ด์šฉํ•œ๋‹ค.

<template>
  <input type="text" v-model="textValue">
  <button type="button" :disabled="!textValue">Click</button>
</template>

<script>
export default {
  data() {
    return {
      textValue: ``
    }
  },
}
</script>

3. class

.classList.add('someClass') ๋˜๋Š” .classList.remove('someClass')๋ฅผ ํ•  ํ•„์š” ์—†์ด,

๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•  class๋Š” class attribute ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , Vue๋ฅผ ์ด์šฉํ•ด ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•  ๋ณ€๋™์„ฑ ์žˆ๋Š” class๋Š” v-bind:class directive ๋ฅผ ์ด์šฉํ•˜๋ฉฐ, Object ํƒ€์ž… ๋งคํ•‘๊ณผ, Array ํƒ€์ž… ๋งคํ•‘ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

1 ) v-bind:class by Object Mapping

<template>
  <div class="fixed-class" :class="{ 'some-class-1': class1, 'some-class-2': class2 }"></div>
</template>

<script>
export default {
  data() {
    return {
      class1: true,
      class2: false
    }
  },
}
</script>

<style scoped>
.fixed-class { }
.some-class-1 { }
.some-class-2 { }
</style>

class-name: boolean ์Œ์œผ๋กœ ์ž‘์„ฑํ•ด ์ ์šฉํ•  ํด๋ž˜์Šค๋ฅผ On/Off ํ•  ์ˆ˜ ์žˆ๋‹ค.


2 ) v-bind:class by Array Mapping

<template>
  <div class="fixed-class" :class="[class1, class2]"></div>
</template>

<script>
export default {
  data() {
    return {
      class1: 'some-class-1',
      class2: 'some-class-2'
    }
  },
}
</script>

<style scoped>
.fixed-class { }
.some-class-1 { }
.some-class-2 { }
</style>

ํด๋ž˜์Šค ์ด๋ฆ„์„ Array๋กœ ๋‚˜์—ดํ•  ๋ฟ ์ ์šฉํ•  ํด๋ž˜์Šค๋ฅผ On/Off ํ•  ์ˆ˜ ์—†๋‹ค.
๋Œ€์‹  Array๋ฅผ ์ด์šฉํ•˜๋ฉด ์œ„ ์ผ€์ด์Šค๋ฅผ ๊ธฐ์ค€์œผ๋กœ class1 ๋ณ€์ˆ˜ ํ•˜๋‚˜์— some-class-1 some-class-2์™€ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

4. Inline Style

v-bind:style directive ๋ฅผ ์ด์šฉํ•˜๋ฉฐ, Object ํƒ€์ž… ๋งคํ•‘๊ณผ, Array ํƒ€์ž… ๋งคํ•‘ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.
๋‹จ, v-bind:class์™€ ๋‹ฌ๋ฆฌ Object Mapping์ด template ์ชฝ์ด ์•„๋‹Œ data() ์ชฝ์—์„œ ์ด๋ค„์ง„๋‹ค. ์ฆ‰, boolean์ด ์•„๋‹Œ CSS์˜ Property: Value ์Œ์ด ๋งคํ•‘๋œ๋‹ค.

1 ) v-bind:style by Object Mapping

<template>
  <div :style="styleObject"></div>
</template>

<script>
export default {
  data() {
    return {
      styleObject: {
        proeprty1: 'value1',
        proeprty2: 'value2'
      }
    }
  },
}
</script>


2 ) v-bind:style by Array Mapping

<template>
  <div :style="[style1, style2]"></div>
</template>

<script>
export default {
  data() {
    return {
      style1: 'property1: value1; property2: value2;',
      style2: 'proeprty3: value3;'
    }
  },
}
</script>

7. v-for

select์˜ option, table์˜ tr ๋ฐ์ดํ„ฐ์™€ ๊ฐ™์€ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์ฃผ๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ, v-for directive ๋ฅผ ์ด์šฉํ•˜๋ฉฐ, v-for="(item, index) in items" ์˜ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

<template>
  <table>
    <thead>
    <tr>
      <th>์ œํ’ˆ๋ช…</th>
      <th>๊ฐ€๊ฒฉ</th>
      <th>์นดํ…Œ๊ณ ๋ฆฌ</th>
      <th>๋ฐฐ์†ก๋ฃŒ</th>
    </tr>
    </thead>
    <tbody>
    <tr v-for="(product, index) in productList" :key="index">
      <td>{{ product.product_name }}</td>
      <td>{{ product.price }}</td>
      <td>{{ product.category }}</td>
      <td>{{ product.delivery_price }}</td>
    </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  name: "VueFor",
  data() {
    return {
      productList: [
        {"product_name": "์‚ฌ๊ณผ", "price": 4000, "category": "๊ณผ์ผ", "delivery_price": 3000},
        {"product_name": "๋ฐฐ", "price": 6000, "category": "๊ณผ์ผ", "delivery_price": 3000},
        {"product_name": "์ฐธ์น˜", "price": 30000, "category": "์ƒ์„ ", "delivery_price": 10000},
        {"product_name": "์•ˆ์‹ฌ", "price": 40000, "category": "์œก๋ฅ˜", "delivery_price": 6000},
        {"product_name": "์™€์ธ", "price": 12000, "category": "์ฃผ๋ฅ˜", "delivery_price": 0},
      ]
    }
  }
}
</script>

<style scoped>
table {
  font-family: Arial, sans-serif;
  border-collapse: collapse;
  width: 100%;
}

td, th {
  border: 1px solid #ddd;
  text-align: left;
  padding: 8px;
}
</style>

v-for examples

8. v-if, v-show

1. v-if

<template>
  <div>
    <h1 v-if="type === 'A'">A</h1>
    <h1 v-else-if="type === 'B'">B</h1>
    <h1 v-else>Others</h1>
  </div>
</template>

<script>
export default {
  name: "VueIf",
  data() {
    return {
      type: 'B'
    }
  },
}
</script>

v-if examples

2. v-show

<template>
  <div>
    <h1 v-show="type === 'A'">A</h1>
    <h1 v-show="type === 'B'">B</h1>
    <h1 v-show="!(type === 'A' || type === 'B')">Others</h1>
  </div>
</template>

<script>
export default {
  name: "VueSHow",
  data() {
    return {
      type: 'B'
    }
  }
}
</script>

v-show examples


v-if๋Š” DOM ์„ ์ƒ์„ฑ/์‚ญ์ œํ•˜๊ณ , v-show๋Š” DOM ์„ ๋ชจ๋‘ ์ƒ์„ฑ ํ›„ display=none ์ฒ˜๋ฆฌ๋งŒ ํ•œ๋‹ค.
๋”ฐ๋ผ์„œ ์ตœ์ดˆ DOM ์ƒ์„ฑ์€ v-show๊ฐ€ ๋” ๋งŽ์€ ๋น„์šฉ์ด ๋“ค์ง€๋งŒ, ์ดํ›„ ํ™”๋ฉด์—์„œ ์ƒ์„ฑ/์‚ญ์ œ๊ฐ€ ์ผ์–ด๋‚  ๋•Œ๋Š” ๊ฐ์ถ”๊ธฐ๋งŒ ํ•˜๋ฏ€๋กœ ๋” ์ ์€ ๋น„์šฉ์œผ๋กœ ์ž‘๋™ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ํ•ด๋‹น ๋ณ€์ˆ˜์— ํ† ๊ธ€์ด ์ž์ฃผ ์ผ์–ด๋‚œ๋‹ค๋ฉด v-show๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

9. v-on

HTML์˜ onclick, onchange, onkeyup๊ณผ ์‚ฌ์šฉ๋ฒ•์ด ๋™์ผํ•˜๋‹ค.
์ฐจ์ด์ ์€ Vue์— ์˜ํ•ด ๊ด€๋ฆฌ๋  ์ˆ˜ ์žˆ๋„๋ก v-on:x directive ๋˜๋Š” @x directive ๋ฅผ ์‚ฌ์šฉํ•ด Vue์˜ methods์— ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ๊ฒƒ๋งŒ ๋‹ค๋ฅด๋‹ค.

v-on:click="someMethodName" ๋˜๋Š” @click="someMethodName" ์˜ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

1. v-on:click

  • Whitout Arguments
<template>
  <button type="button" @click="increaseCounter">Add 1</button>
  <p>The counter is : {{ counter }}</p>
</template>

<script>
export default {
  name: "VueOnEvents",
  data() {
    return {
      counter: 0
    }
  },
  methods: {
    increaseCounter() {
      this.counter++
    }
  },
}
</script>
  • With Arguments
<template>
  <button type="button" @click="resetCounter(0)">Reset</button>
  <p>The counter is : {{ counter }}</p>
</template>

<script>
export default {
  name: "VueOnEvents",
  data() {
    return {
      counter: 0,
    }
  },
  methods: {
    resetCounter(value) {
      this.counter = value
    }
  },
}
</script>
  • Pseudo Pipe

์ •ํ™•ํžˆ reduce๋ฅผ ์ด์šฉํ•œ Pipe ํ•จ์ˆ˜์™€๋Š” ์กฐ๊ธˆ ๋‹ค๋ฅด์ง€๋งŒ, data์— ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ด ๋ฉ”์„œ๋“œ๋ฅผ ์—ฐ์†ํ•ด ํ˜ธ์ถœํ•˜๋ฏ€๋กœ์จ ์œ ์‚ฌ Pipe ๊ตฌํ˜„๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

<template>
  <button type="button" @click="first(pipeInitialValue = 5), second(pipeInitialValue)">Multi Call</button>
</template>

<script>
export default {
  name: "VueOnEvents",
  data() {
    return {
      pipeInitialValue: 0
    }
  },
  methods: {
    first(value) {
      alert(value)
      this.pipeInitialValue += 10
    },
    second(value) {
      alert(value)
    }
  },
}
</script>
5
15

2. v-on:change

<template>
  <select v-model="selectedValue" @change="popSelected">
    <option v-for="(city, index) in cities" :key="index" :value="city">{{ city }}</option>
  </select>
</template>

<script>
export default {
  name: "VueOnEvents",
  data() {
    return {
      cities: ["์„œ์šธ", "๋ถ€์‚ฐ", "์ œ์ฃผ"],
      selectedValue: "",
    }
  },
  methods: {
    popSelected() {
      alert(this.selectedValue)
    },
  },
}
</script>

<style scoped>

</style>

3. v-on:keyup

Vue๋Š” keyup ์ด๋ฒคํŠธ์— ํŠน์ • ํ‚ค ์กฐ๊ฑด๋ฌธ์„ ์ง์ ‘ ์ •ํ•˜์ง€ ์•Š๊ณ ๋„ ์†์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์šด์˜์ฒด์ œ์— ๋”ฐ๋ผ key-code๊ฐ€ ๋‹ค๋ฅธ ๊ฒƒ์— ๋Œ€ํ•ด ๋ณ„๋„๋กœ ์ฒ˜๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

  • @keyup.enter : enter, return
  • @keyup.tab
  • @keyup.delete : delete, backspace
  • @keyup.esc
  • @keyup.space
  • @keyup.up
  • @keyup.down
  • @keyup.left
  • @keyup.right

๋˜ํ•œ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‚ค ์กฐํ•ฉ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • @keyup.alt.enter
  • @click.ctrl
<template>
  <h4>Keyup (Win: alt + enter / Mac: option + return)</h4>
  <input type="text" @keyup.alt.enter="altEnterCalled">

  <div style="display: grid">
    <div class="btn-style" @click.meta="commandClickCalled">Command Click</div>
  </div>
</template>

<script>
export default {
  name: "VueOnEvents",
  data() {
    return { }
  },
  methods: {
    altEnterCalled() {
      alert(`(alt + enter) or (option + return) called!!`)
    },
    commandClickCalled() {
      alert(`(win + click) or (command + click) called!!`)
    },
  },
}
</script>

<style scoped>
.btn-style {
  justify-self: center;
  width: 200px;
  padding: 5px 10px;
  margin: 10px;
  background-color: burlywood;
  border: blanchedalmond solid 3px;
  border-radius: 10px;
}
</style>

10. Computed, Watch

1. Computed Properties

Swift Computed Properties ์™€ ๊ฐ™๋‹ค.

๊ฐ’์„ ๊ณ„์‚ฐํ•ด ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋ฉฐ, ๊ฐ’์€ ์บ์‹ฑ๋œ๋‹ค.

  • Getter/Setter
<template>
  <h4>Perform every times</h4>
  <div>{{ `${firstName} ${lastName}` }}</div>

  <h4>Computed</h4>
  <div>{{ fullName }}</div>

  <hr>

  <h4>firstName</h4>
  <input type="text" v-model="firstName">

  <h4>lastName</h4>
  <input type="text" v-model="lastName">

  <h4>fullName</h4>
  <input type="text" v-model="fullName">
</template>

<script>
export default {
  name: "VueComputedAndWatch",
  data() {
    return {
      firstName: "Harry",
      lastName: "Potter"
    }
  },
  methods: {},
  computed: {
    fullName: {
      get: function () {
        return `${this.firstName} ${this.lastName}`
      },
      set: function (newValue) {
        const names = newValue.split(' ')
        this.firstName = names[0]
        this.lastName = names[1]
      }
    }
  }
}
</script>


  • Read-Only
<template>
  <h4>Perform every times</h4>
  <div>{{ `${firstName} ${lastName}` }}</div>

  <h4>Computed</h4>
  <div>{{ fullName }}</div>

  <hr>

  <h4>firstName</h4>
  <input type="text" v-model="firstName">

  <h4>lastName</h4>
  <input type="text" v-model="lastName">

  <h4>fullName</h4>
  <input type="text" v-model="fullName">
</template>

<script>
export default {
  name: "VueComputedAndWatch",
  data() {
    return {
      firstName: "Harry",
      lastName: "Potter"
    }
  },
  methods: {},
  computed: {
    fullName: function() {
      return `${this.firstName} ${this.lastName}`
    },
  }
}
</script>

Read-Only ์˜ ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

computed: {
  fullName() {
    return `${this.firstName} ${this.lastName}`
  },
}

Computed Properties ์˜ Getter/Setter์— Arrow Functions๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

2. Watch(Property Observers)

Swift Property Observers ์—์„œ didSet๋งŒ ์กด์žฌํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

<template>
  <h4>Perform every times</h4>
  <div>{{ `${firstName} ${lastName}` }}</div>

  <h4>Computed</h4>
  <div>{{ fullName }}</div>

  <hr>

  <h4>firstName</h4>
  <input type="text" v-model="firstName">

  <h4>lastName</h4>
  <input type="text" v-model="lastName">

  <h4>fullName</h4>
  <input type="text" v-model="fullName">
</template>

<script>
export default {
  name: "VueComputed",
  data() {
    return {
      firstName: "Harry",
      lastName: "Potter"
    }
  },
  methods: {},
  computed: {
    fullName: {
      get: function () {
        return `${this.firstName} ${this.lastName}`
      },
      set: function (newValue) {
        const names = newValue.split(' ')
        this.firstName = names[0]
        this.lastName = names[1]
      }
    }
  },
  watch: {
    firstName(newValue, oldValue) {
      console.log(`firstName(old) : ${oldValue}`)
      this.firstName = `${newValue.substring(0, 1).toUpperCase()}${newValue.substring(1)}`
    },
    lastName(newValue, oldValue) {
      console.log(`lastName(old) : ${oldValue}`)
      this.lastName = `${newValue.substring(0, 1).toUpperCase()}${newValue.substring(1)}`
    },
  }
}
</script>




Reference

  1. ๊ณ ์Šน์›. Vue.js ํ”„๋กœ์ ํŠธ ํˆฌ์ž… ์ผ์ฃผ์ผ ์ „. ๋น„์ œ์ดํผ๋ธ”๋ฆญ Chapter 4, 2021.
  2. ๊ณ ์Šน์›. Vue.js ํ”„๋กœ์ ํŠธ ํˆฌ์ž… ์ผ์ฃผ์ผ ์ „. ๋น„์ œ์ดํผ๋ธ”๋ฆญ Chapter 5, 2021.