/Vue

๐Ÿ“Œ Study Repository

Primary LanguageJavaScript

๐Ÿ“Œ Vue.Js Study

  • Vue.JS๋ฅผ ์Šคํ„ฐ๋””ํ•˜๋Š” ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ ์ž…๋‹ˆ๋‹ค.

1. binding

  • ๋‹จ๋ฐฉํ–ฅ data binding
  • ์–‘๋ฐฉํ–ฅ data binding

2. directive

  • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ DOM์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ๋ฌด์–ธ๊ฐ€๋ฅผ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์ง€์‹œํ•˜๋Š” ํŠน์ˆ˜ํ•œ ํ† ํฐ

(1) v-if / v-show

  • ์กฐ๊ฑด์— ๋”ฐ๋ผ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ํ™”๋ฉด์— ํ‘œ์‹œ

(1-1) v-else

  • v-if์˜ ํ‰๊ฐ€ ๊ฒฐ๊ณผ๊ฐ€ ๊ฑฐ์ง“์ด๋ฉด ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ํ‘œ์‹œ

(2) v-for

<li v-for="(value, key, index) in story" class="list-group-item">
  {{index}} : {{key}} : {{value}}
</li>

(3) v-on (์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์—˜๋ฆฌ๋จผํŠธ์— ๋ถ™ํž˜)

  • 4๊ฐ€์ง€ ์ด๋ฒคํŠธ ํ•œ์ •์ž
    1. .prevent
    2. .stop
    3. .capture
    4. .self
<!-- prevent๋ฅผ ์ด์šฉํ•œ ์ œ์ถœ๋ฒ„ํŠผ -->
<button type="submit" @click="calculate">Calculate</button>
 <!-- submit ์ด๋ฒคํŠธ๋Š” ๋”๋Š” ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -->
<button type="submit" @click.prevent="calculate">Calculate</button>
  • :click or @
  • ํ‚ค ํ•œ์ •์ž :keyup.enter = :keyup.13
enter, tab, delete, esc, space, up, down, left, right
-------------------
<!-- ์ „์ฒด ๋ฌธ๋ฒ• -->
<a v-on:click="doSomething"> ... </a>

<!-- ์•ฝ์–ด -->
<a @click="doSomething"> ... </a>
  • :keypress
  • :keydown

(4) v-bind or :

  • ํ•˜๋‚˜ ์ด์ƒ์˜ ์†์„ฑ ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ ํ”„๋กœํผํ‹ฐ๋ฅผ ํ‘œํ˜„์‹์— ๋™์ ์œผ๋กœ ๋ฐ”์ธ๋”ฉํ•˜๋Š”๋ฐ ์‚ฌ์šฉ(๋™์ ์œผ๋กœ ๋ฐ”๊พธ๊ธฐ)
<!-- ์ „์ฒด ๋ฌธ๋ฒ• -->
<a v-bind:href="url"> ... </a>

<!-- ์•ฝ์–ด -->
<a :href="url"> ... </a>

(5) v-model

  • v-model.number (์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ์„ ์ˆซ์ž๋กœ ์ €์žฅ)
<body>
  <div class="container">
    a={{ a }}, b={{ b }}
    <input v-model.numbr="a">
    <pre> {{data}} </pre>
  </div>
</body>

3. methods

<script>
export default {
//  ๋ฉ”์„œ๋“œ ๊ฐ์ฒด ์•„๋ž˜ ๋ฉ”์„œ๋“œ ์ •์˜
  methods: {
    clickEvent: function() {
    //  ๋ฉ”์„œ๋“œ ๋‚ด this๋Š” Vue ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ด
    this.data++;
    }
  }
};
</script>

4. computed

  • ๊ณ„์‚ฐ๋œ ํ”„๋กœํผํ‹ฐ
  • ๋ทฐ์˜ ์ธ๋ผ์ธ ํ‘œํ˜„์€ ํŽธํ•˜์ง€๋งŒ ๋กœ์ง์ด ๋ณต์žกํ•ด์ง€๋ฉด computed๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•จ
  • computed properties๋ž€ ๋‹ค๋ฅธ ์š”์ธ์— ๋”ฐ๋ผ ๊ฐ’์ด ๋ฐ”๋€Œ๋Š” ๋ณ€์ˆ˜. ๊ฐ์ฒด ํ”„๋กœํผํ‹ฐ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜์ฒ˜๋Ÿผ ๋™์ž‘.
<script>
export default {
   computed: {
    showList() {
    //  this๋Š” Vue์˜ ์ธ์Šคํ„ด์Šค
      return this.models;
    }
  }
};
  • ์˜ˆ๋ฅผ ๋“ค๋ฉด, ์—ฐ์‚ฐ๋Ÿ‰์ด ๋งŽ๊ฑฐ๋‚˜ data๋ฅผ ์œ ์ง€ํ•ด์•ผํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์Œ
  • ๊ณ„์‚ฐ๋œ ์บ์‹ฑ(Computed Caching) vs ๋ฉ”์†Œ๋“œ(Methods)
๊ณ„์‚ฐ๋œ ์†์„ฑ ๋Œ€์‹  methods๋กœ ์ •์˜ ๊ฐ€๋Šฅ, ๋‘๊ฐ€์ง€์˜ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์„œ๋กœ ๋™์ผํ•จ 
์ด๋•Œ ์ฐจ์ด์ ์€ ๊ณ„์‚ฐ๋œ ์†์„ฑ์€ ์ข…์†์„ฑ์— ๋”ฐ๋ผ ์บ์‹œ๋œ๋‹ค

๋ฌด์Šจ๋ง์ธ์ง€ ์•Œ์•„๋ณด๋ฉด 
๊ณ„์‚ฐ๋œ ์†์„ฑ(computed)์€ ์ข…์†์„ฑ ์ค‘ ์ผ๋ถ€๊ฐ€ ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ์—๋งŒ ๋‹ค์‹œ ๊ณ„์‚ฐ 
์œ„์˜ ์˜ˆ์—์„œ message ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ํ•œ,  reversedMessage์— ๋Œ€ํ•œ ๋‹ค์ค‘ ์ ‘๊ทผ์€
ํ•จ์ˆ˜๋ฅผ ๋‹ค์‹œ ์ˆ˜ํ–‰ํ•  ํ•„์š” ์—†์ด ์ด์ „์— ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋ฅผ ์ฆ‰์‹œ ๋ฐ˜ํ™˜ํ•จ 

๋งŒ์•ฝ computed ์•ˆ์— ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋‚ ์งœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ•จ์ˆ˜ Date.now() ๋ฅผ ๋„ฃ๋Š”๋‹ค๋ฉด ์—…๋ฐ์ดํŠธ ๋˜์ง€ ์•Š์Œ! 
ํ•˜์ง€๋งŒ methods ํ˜ธ์ถœ์€ ๋ Œ๋”๋ง ํ•  ๋•Œ๋งˆ๋‹ค ํ•ญ์ƒ ํ˜ธ์ถœ
์บ์‹ฑ์ด ํ•„์š”ํ•œ ์ด์œ ๋Š”?
์บ์‹ฑํ•˜์ง€ ์•Š์œผ๋ฉด ์‹œ๊ฐ„์ด ๋งŽ์ด ์†Œ์š”๋˜๋Š” A ์†์„ฑ์ด ํ•„์š”ํ•œ ๊ฒƒ๋ณด๋‹ค getter๋ฅผ ๋” ์‹คํ–‰ํ•˜๊ฒŒ ๋˜์–ด ๋ถˆํ•„์š”ํ•œ ์ž‘์—… ์‹คํ–‰
๋”ฐ๋ผ์„œ ์บ์‹ฑ์ด ํ•„์š”ํ•˜์ง€ ์•Š์„๋•Œ๋Š” methods๋ฅผ ์‚ฌ์šฉ
์ถœ์ฒ˜: https://takeuu.tistory.com/25 [์›Œ๋„ˆ๋น„์ŠคํŽ˜์…œ]

5.filter

  • ๋ฐฐ์—ด์˜ ํ•ญ๋ชฉ ํ•„ํ„ฐ๋ง
<script>
export default {
  methods: {
  //  ์ž‘๊ฐ€์— ๋”ฐ๋ผ ์ด์•ผ๊ธฐ๋ฅผ ํ•„ํ„ฐ๋งํ•˜๋Š” ๋ฉ”์„œ๋“œ
    storiesBy: function (writer) {
      return this.stories.filter(function (story) {
        return story.writer === writer
      }
  }
};
</script>
  • ๋ฐฐ์—ด์˜ ํ•ญ๋ชฉ ์ •๋ ฌ
<script>
export default {
   computed: {
    orderedStories: function () {
    //  JS ๋‚ด์žฅํ•จ์ˆ˜ sort์‚ฌ์šฉ
    //  ๋ฐฐ์—ด์˜ ์š”์†Œ๋ฅผ ์ •๋ ฌ
      return this.stories.sort(function(a, b){
      //  ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜
        return a.upvotes - b.upvotes;
      })
    }
  }
};
</script>
  1. compareFunction(a, b) = 0๋ณด๋‹ค ์ž‘์œผ๋ฉด, a๋ฅผ b๋ณด๋‹ค ๋‚ฎ์€ ์ธ๋ฑ์Šค๋กœ ์ •๋ ฌ
  2. compareFunction(a, b) = 0์ด๋ฉด, a์™€ b์˜ ์œ„์น˜๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  3. compareFunction(a, b) = 0๋ณด๋‹ค ํฌ๋ฉด, b๋ฅผ a๋ณด๋‹ค ๋‚ฎ์€ ์ธ๋ฑ์Šค๋กœ ์ •๋ ฌ
  • ์‚ฌ์šฉ์ž ์ •์˜ ํ•„ํ„ฐ ์ ์šฉ
  • ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™œ์šฉ : CDN์„ ํ†ตํ•ด html ํŒŒ์ผ์— ์ถ”๊ฐ€
    1. Lodash
    2. Underscore
    3. sugar
//  ๋ฌธ๋ฒ•
//  ์ฒซ๋ฒˆ์งธprop : ์ •๋ ฌํ•  ๋ฐฐ์—ด
//  ๋‘๋ฒˆ์งธprop : ์ •๋ ฌ ๊ธฐ์ค€์ด ๋  ํ‚ค์˜ ๋ฐฐ์—ด
//  ์„ธ๋ฒˆ์งธprop : ๊ฐ ํ‚ค์˜ ์ˆœ์„œ๋กœ ๊ตฌ์„ฑ๋œ ๋ฐฐ์—ด
_.orderBy(collection, [iteratees=[_.identity]], [orders])

6. LifeCycle

(1) Creation : ์ปดํฌ๋„ŒํŠธ ์ดˆ๊ธฐํ™” (์ด๋ฒคํŠธ, ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์†Œ๋“œ ์ดˆ๊ธฐํ™”, ๋ฉ”์†Œ๋“œ ๋ฐ ๋ฐ์ดํ„ฐ ์˜ต์…˜์„ ํ•˜๊ณ  ๋ฐ˜์‘ํ˜•์œผ๋กœ ์„ค์ •)

  • before create : data, events ์„ธํŒ… ์ „
  • created : data, events ํ™œ์„ฑํ™”( template, ๊ฐ€์ƒ๋” -> mount, rendering X )

(2) Mounting : ๋”(DOM) ์‚ฝ์ž…๋‹จ๊ณ„ (ํ…œํ”Œ๋ฆฟ์„ ์ฝ์–ด์™€ ๋ฌธ๋ฒ• ์ ์šฉ, ํ™”๋ฉด ๋ Œ๋”๋ง)

  • before Mount : template, ๋ Œ๋”ํ•จ์ˆ˜๊ฐ€ ๋ Œ๋”๋ง๋œ ํ›„ ์ฒซ ๋ Œ๋”๋ง ์ง์ „์— ์‹คํ–‰ ( ๋น„๊ถŒ์žฅ, server-side-rendering์‹œ ํ˜ธ์ถœ X )
  • Mounted : component, template, ๋ Œ๋”๋ง๋œ DOM ์ ‘๊ทผ ๊ฐ€๋Šฅ (๋ชจ๋“  ํ•˜์œ„ component๊ฐ€ ๋งˆ์šดํŒ… ์ƒํƒœ ๋ณด์žฅ์€ X, s-s-r ํ˜ธ์ถœ X )

(3) Updating : Diff. ์žฌ๋ Œ๋”๋ง ๋‹จ๊ณ„ (๋ฐ์ดํ„ฐ ์†์„ฑ์˜ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜๋ฉด ํ™”๋ฉด์„ ๋‹ค์‹œ ๋ Œ๋”๋ง)

  • before Update : ๋” ์žฌ๋ Œ๋”๋ง -> Before0Update -> ํŒจ์น˜ ( ์žฌ๋ Œ๋”๋ง ์ „์˜ ์ƒˆ ์ƒํƒœ์˜ data ์–ป์„ ์ˆ˜ O )
  • updated : ๋”์ด ์—…๋ฐ์ดํŠธ๋œ ์ƒํƒœ, ๋” ์ข…์† ์—ฐ์‚ฐ ๊ฐ€๋Šฅ
  • The lifecycle hooks around update respond to changes in the DOM. Watchers respond to changes in the data. DOM changes are generally in response to data changes, but they might not be data owned by the component in question. ex

(4) Destruction : ํ•ด์ œ ๋‹จ๊ณ„ (๋ฐ์ดํ„ฐ์˜ ๋ฐ˜์‘ ํ•ด์ œ ๋ฐ ์ด๋ฒคํŠธ๋ฅผ ์‚ญ์ œ)

  • before Destroy : ๋ทฐ์ธ์Šคํ„ด์Šค ์ œ๊ฑฐ ์ง์ „์— ํ˜ธ์ถœ๋จ
  • destroyed : ๋ทฐ์ธ์Šคํ„ด์Šค ์ œ๊ฑฐ ํ›„ ํ˜ธ์ถœ ๋จ

life-cycle Hooks Tutorial

7. ์‚ฌ์šฉ์ž ์ •์˜ ์ด๋ฒคํŠธ

1) $on(event)๋ฅผ ์ด์šฉํ•ด ์ด๋ฒคํŠธ ์ฒญ์ทจ

2) $emit(event)๋ฅผ ์ด์šฉํ•ด ์ด๋ฒคํŠธ ๋ฐœ์ƒ

  • ๋ถ€๋ชจ > ์ž์‹ : props

  • ์ž์‹ > ๋ถ€๋ชจ ๋ณ€๊ฒฝ์‚ฌํ•ญ ์ „๋‹ฌ : emit

<script>
  Vue.component('chariot', {
      template: '#chariot-template',
      //  ๋ถ€๋ชจ > ์ž์‹ ์ปดํฌ๋„ŒํŠธ ํ†ต์‹ 
      props:['chariot'],
      methods: {
          rideChariot: function (chariot) {
              //  ์ด๋ฒคํŠธ ์ด๋ฆ„ ์ธ์ž์™€ ํ•จ๊ป˜ ๋ฆฌ์Šค๋„ˆ ์ฝœ๋ฐฑํ•จ์ˆ˜์— ์ถ”๊ฐ€๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค(arrowํ•จ์ˆ˜)
              this.$emit('select', chariot)
          }
      }
      :
  • $emit์—์„œ ์„ค์ •ํ•œ 'select' ๊ฐ€ ์•„๋ž˜์˜ ๋ถ€๋ชจ์ž์‹ ํƒœ๊ทธ ์•ˆ์— @select๋กœ ๋“ค์–ด๊ฐ. ๊ทธ ๋•Œ, @select="๋‚ด๋ถ€ํ•จ์ˆ˜"์‹คํ–‰ ์‹œํ‚ด
<body>
  <div class="container">
      <h1>Chariot shopping</h1>
      <ul class="list-group">
          <chariot v-for="(chariot, index) in chariots" :key="index" :chariot="chariot" @select="updateChariot"></chariot>
      </ul>
      <pre>{{ $data }}</pre>
  </div>

3) $once(event)๋ฅผ ์ด์šฉํ•ด ์ด๋ฒคํŠธ๋ฅผ ํ•œ ๋ฒˆ๋งŒ ์ฒญ์ทจ

4) $off()๋ฅผ ์ด์šฉํ•ด ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ œ๊ฑฐ

5) eventbus

8. Vuex

  • ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ ๊ฐ„ ํ†ต์‹ ๊ฐ„์—๋Š” ์ค‘์•™๊ด€๋ฆฌ์ฒด๊ณ„๊ฐ€ ํ•„์š”ํ•จ
  • props, emit, eventbus ๋Œ€์ฒด
  • vuex๋ž€ ? https://vuex.vuejs.org/kr/
  • vuex์— ํ•จ์ˆ˜, ์ƒํƒœ ์ €์žฅ -> ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์œ ๋กญ๊ฒŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
  • vuex์™€ ์ปดํฌ๋„ŒํŠธ ๋น„๊ต

  • vuex ์ „์ฒด flow

1) vue create

  • state : Vue ์ธ์Šคํ„ด์Šค์˜ data๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋จ
  • getters : computed
  • mutations : ๋ณ€์ด (state๊ฐ’์„ ๋ณ€ํ™”์‹œํ‚ด) (๋ชจ๋“  ๊ธฐ๋Šฅ์ด ๋™๊ธฐ๋กœ ๋™์ž‘ํ•จ)
  • actions : ๋น„๋™๊ธฐ ๋กœ์ง ์ฒ˜๋ฆฌ(mutation์„ ๋ณ€ํ™”์‹œํ‚ค๋Š” business ๋กœ์ง)

  • store.js : ์ €์žฅ์†Œ
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {  //  data
    allUsers:[
      {userId:'123', password: '1234', name: 'tonz', address: 'Seoul'}
        :
    ]
  },
  mutations: {
  },
  actions: {
  }
})
  • ์ค‘์•™ํ†ต์ œ๊ด€๋ฆฌ์†Œ ๊ฒฉ์ธ main.js ํŒŒ์ผ์— Vuex์„ค์ •(๊ฐ ์ปดํฌ๋„ŒํŠธ์—์„œ import X)
:

import store from './store'
:
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')
  • AllUsers.vue ์™€ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ์—์„œ์˜ ์ ‘๊ทผ : $store.state.allUsers
<template>
  <div>
    <h1>All Users ({{ $store.state.allUsers.length }})</h1>
    :
  <v-list-tile
    v-for="(user, index) in $store.state.allUsers"
    :key="index"
    avatar>
  :

</template>

<script>
  export default {
    data() {
      return {
      }
    },
    mounted () {
      EventBus.$on('SignUp'. users => {
        this.$store.state.allUsers.push(users)
      })
    }
  }
</script>

2) Getters

  • ๋ณต์žกํ•œ ๊ณ„์‚ฐ์‹์ด ๋  ๋•Œ ์šฉ์ดํ•จ
  • state ์ž์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ getter
  • store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {  //  data
    allUsers:[
      {userId:'123', password: '1234', name: 'tonz', address: 'Seoul'}
        :
    ]
  },
  getters: {  // computed
    allUsersCount: function(state) {  //  state๋กœ ๋ฐ˜๋“œ์‹œ ๋“ค์–ด๊ฐ€์•ผํ•จ
      return state.allUsers.length
    },
    countOfSeoul: state => {
      let count = 0
      state.allUsers.forEach(user => {
        if(user.address === 'Seoul') count ++
      })
      return count
    },
    percentOfSeoul: (state, getters) => { //  state๋กœ ๋ฐ˜๋“œ์‹œ ๋ฐ›์•„์•ผ ๋‘๋ฒˆ์งธ ์ธ์ž ์ธ์‹
      return Math.round(getters.countOfSeoul / getters.allUsersCount * 100)
    }
  },
  mutations: {
  },
  actions: {
  }
})
  • getters๋กœ AllUsers.vue ์™€ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ์—์„œ์˜ ์ ‘๊ทผ : $store.getters.allUsersCount
<template>
  <div>
    <h1>Seoul Users : ({{ $store.getters.countOfSeoul }}) ({{ $store.getters.percentOfSeoul }}%)</h1>
  :
  <v-list-tile
    v-for="(user, index) in $store.getters.allUsersCount"
    :key="index"
    avatar>
  :

</template>

<script>
  export default {
    data() {
      return {
      }
    },
    mounted () {
      EventBus.$on('SignUp'. users => {
        this.$store.state.allUsers.push(users)
      })
    }
  }
</script>

3) Map Getters

  • getters์—์„œ ์“ฐ๊ณ  ์žˆ๋Š” ๊ฐ’๋“ค์„ ์‚ฌ์šฉํ•˜๊ณ ์žํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์— ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ถˆ๋Ÿฌ๋‚ด๋Š” ๊ฒƒ
  • map getters๋กœ AllUsers.vue ์™€ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ์—์„œ์˜ ์ ‘๊ทผ : ๋ฐฐ์—ด๋กœ ๋ฐ›๊ธฐ
<template>
  <div>
    <h1>Seoul Users : ({{ countOfSeoul }}) ({{ percentOfSeoul }}%)</h1>
  :
</template>

<script>
import { mapGetters } from 'vuex' // vuex์—์„œ ๋ฏธ๋ฆฌ ์„ค์ •๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ vuex์—์„œ ์ž„ํฌํŠธ
  export default {
    data() {
      return {
      }
    },
    computed: {
      //  ๋ฐฐ์—ด๋กœ ๋ฐ›์Œ
      ...mapGetters(['allUsersCount', 'countOfSeoul', 'percentOfSeoul']) // mapGetters์—์„œ ๋ถˆ๋Ÿฌ์™€์•ผ ๊ฐ„๋‹จํžˆ ์‚ฌ์šฉ๊ฐ€๋Šฅ
    },
    mounted () {
      EventBus.$on('SignUp'. users => {
        this.$store.state.allUsers.push(users)
      })
    }
  }
</script>
  • AllUsers.vue ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ๋ฐ›์•„์„œ ์“ธ ๋•Œ mapGetters๋ฅผ ๊ฐ์ฒด๋กœ ๋ฐ›๊ธฐ
  • mapState
<template>
  <div>
    <h1>All Users : ({{ count }})</h1>
    <h1>Seoul Users : ({{ seouls }}) ({{ percent }}%)</h1>
  :
  <v-list-tile
    v-for="(user, index) in allUsers" //  mapState์—์„œ 
    :key="index"
    avatar>
  :
</template>

<script>
import { mapState, mapGetters } from 'vuex'
  export default {

    computed: {
      ...mapGetters({ //  ๊ฐ์ฒด๋กœ ๋ฐ›์Œ
        count: 'allUsersCount',
        seouls: 'countOfSeoul',
        percent: 'percentOfSeoul'
      }),
      ...mapState(['allUsers'])
    },
:
</script>

4) mutations

  • store.commit() : mutation ํ˜ธ์ถœ
  • WHY ? ๊ฐ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋™์ผํ•˜๊ฒŒ ์“ฐ์ด๋ฉด ์ฝ”๋“œ์ค‘๋ณต -> state๋ฅผ ๋ณ€ํ™”์‹œํ‚ค๋Š” mutation์„ ๊ฐ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ™œ์šฉ!(commit)
  • state์˜ setter ํ˜น์€ updater์˜ ์—ญํ• 
  • store.js
:
export default new Vuex.Store({
  state: {  //  data
    allUsers:[
      {userId:'123', password: '1234', name: 'tonz', address: 'Seoul'}
        :
    ]
  },
  mutations: {
    addUsers: (state, payload) => {
      state.allUsers.push(payload)
    }
  },
  actions: {
  }
})
  • SignUp.vue : mapMutations
<template>
  :
</template>

<script>
import { mapMutations } from 'vuex'

  export default {
    :
    computed: {
      ...mapGetters({ //  ๊ฐ์ฒด๋กœ ๋ฐ›์Œ
        count: 'allUsersCount',
        seouls: 'countOfSeoul',
        percent: 'percentOfSeoul'
      }),
      ...mapState(['allUsers'])
    },
    methods: {
      ...mapMutations(['addUsers']),
      signUp () {
        let userObj = {
          userId : this.userId,
          :
        }
        this.addUsers(userObj) // userObj๋Š” store.js์˜ payload๋กœ ๋‚ ์•„๊ฐ
        //  EventBus.$emit('signUp', userObj)
        :
      }
    }
:
</script>
  • SignUp.vue : mapMutation์ด ์•„๋‹Œ commit('mutation์ด๋ฆ„', ๋„˜๊ธธ payload)์œผ๋กœ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
<template>
  :
</template>

<script>
//  import { mapMutations } from 'vuex'

  export default {
    :
    computed: {
      //  ...mapGetters({ //  ๊ฐ์ฒด๋กœ ๋ฐ›์Œ
        count: 'allUsersCount',
        seouls: 'countOfSeoul',
        percent: 'percentOfSeoul'
      }),
      ...mapState(['allUsers'])
    },
    methods: {
      ...mapMutations(['addUsers']),
      signUp () {
        let userObj = {
          userId : this.userId,
          :
        }
        this.$store.commit('addUsers', userObj)
        //  this.addUsers(userObj) // userObj๋Š” store.js์˜ payload๋กœ ๋‚ ์•„๊ฐ
        //  EventBus.$emit('signUp', userObj)
        :
      }
    }
:
</script>

5) actions

  • store.dispatch() : action ํ˜ธ์ถœ
  • ๊ฐ ์ปดํฌ๋„ŒํŠธ์—์„œ dispatch๋ฐ›์€ ํ›„ mutations์œผ๋กœ commit๋‚ ๋ฆผ
  • state๋ฅผ ๋ณ€ํ™”์‹œํ‚ค๊ธฐ์œ„ํ•œ business ๋กœ์ง ํฌํ•จ(ex. ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์™€ ํ†ต์‹ )
  • ๋น„๋™๊ธฐ ์ž‘์—… ํ›„ mutation ์‹คํ–‰
  • store.js
:
export default new Vuex.Store({
  state: {  //  data
    allUsers:[
      {userId:'123', password: '1234', name: 'tonz', address: 'Seoul'}
        :
    ]
  },
  mutations: {
    addUsers: (state, payload) => {
      state.allUsers.push(payload)
    }
  },
  actions: {  //  ์ด๋ฆ„ ๊ฒน์ณ๋„ ๋จ
    addUsers: context => {
      //  mutation์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ๋ฒ•
      context.commit('addUsers')

    }
  }
})
  • commit์ด ๋งŽ์•„์ง€๋ฉด ์œ„์˜ ๋ฐฉ๋ฒ•์€ ๋ถˆํŽธ
:
export default new Vuex.Store({
  state: {  //  data
    allUsers:[
      {userId:'123', password: '1234', name: 'tonz', address: 'Seoul'}
        :
    ]
  },
  mutations: {
    addUsers: (state, payload) => {
      state.allUsers.push(payload)
    }
  },
  actions: {  //  ์ด๋ฆ„ ๊ฒน์ณ๋„ ๋จ
    addUsers: ({ commit }, payload) => { //  function({commit})๊ณผ ๊ฐ™์€ ์˜๋ฏธ
    //  context, payload
    //  { commit }, payload
    
    //  ์ด๊ณณ์— ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๋Š” business๋กœ์ง ๋‚˜์—ด
    :
    :

     commit('addUsers', payload)  //  state๋ฅผ ๋ณ€ํ™”์‹œํ‚ค๋Š” ํ•œ ์ค„!
    }
  }
})
  • SignUp.vue : actions๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ dispatch
<template>
  :
</template>

<script>
import { mapMutations } from 'vuex'

  export default {
    :
    methods: {
      ...mapMutations(['addUsers']),
      signUp () {
        let userObj = {
          userId : this.userId,
          :
        }
        // this.addUsers(usrObj)
        this.$store.dispatch('addUsers', userObj)
        :
      }
    }
:
</script>
  • SignUp.vue : mapActions ํ™œ์šฉ
<template>
  :
</template>

<script>

import { mapActions } from 'vuex'

  export default {
    :
    methods: {
      //...mapMutations(['addUsers']),
      ...mapActions(['addUsers']),
      signUp () {
        let userObj = {
          userId : this.userId,
          :
        }
        // this.addUsers(usrObj)
        //  this.$store.dispatch('addUsers', userObj)
        this.addUsers(userObj)
        :
      }
    }
:
</script>

9. nextTick

1) Vue.js์—์„œ nextTick ์‚ฌ์šฉํ•˜๊ธฐ

  • nextTick์œผ๋กœ ๊ฐ์‹ผ๋’ค callback์„ ํ†ตํ•ด DOM์„ ์กฐ์ž‘ํ•˜๊ฒŒ ๋˜๋ฉด Vue.js์—์„œ ๋ฐ์ดํ„ฐ๊ฐฑ์‹  ํ›„ UI๊นŒ์ง€ ์™„๋ฃŒํ•œ ๋’ค์— nextTick์— ์žˆ๋Š” ํ•จ์ˆ˜๋ฅผ ์ตœ์ข…์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
created: function() {

    // ...

    this.$nextTick(function() {
    	var dom = document.getElementById('item-0');
        dom.style.backgroundColor = 'red';
    });
}

2) Vue.js์—์„œ nextTick ํ™œ์šฉํ•˜๊ธฐ

์ฝ”๋“œ์ƒ์œผ๋กœ ์˜๋„๋Š” select box ์—์„œ pig ๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒฝ์šฐ
ํ™”๋ฉด์— pig ๋Š” animal ์ด๋ผ๊ณ  ํ‘œํ˜„ํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ํ˜น์€ apple ๋ฅผ ์„ ํƒํ•˜๋ฉด fruit ๋กœ ํ‘œ๊ธฐํ•œ๋‹ค.
ํ•˜์ง€๋งŒ ๋†€๋ž๊ฒŒ๋„(!) ์ฝ”๋“œ๋Š” ์˜๋„์™€ ๋ฐ˜๋Œ€๋กœ ๋™์ž‘ํ•œ๋‹ค.
  • why?
 click ์ด๋ฒคํŠธ๋Š” v-model ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๊ธฐ ์ „์— ํ˜ธ์ถœ๋˜๊ณ 
 ํ˜ธ์ถœ์ด ๋๋‚˜๊ณ  ๋‚˜์„œ์•ผ v-model ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
 ๋‹ค์‹œ๋งํ•ด select box ์— pig ๊ฐ€ ์„ ํƒ๋˜์–ด ์žˆ๋Š” ์ƒํƒœ์—์„œ apple ๋กœ ๋ณ€๊ฒฝํ•˜๋ ค๊ณ  ํ•  ๋•Œ
 ์•„์ง pig ์ธ ์ƒํƒœ์—์„œ click ์ด๋ฒคํŠธ๊ฐ€ ๋‹ค ๋๋‚˜๊ฒŒ ๋˜๊ณ 
 ๊ทธ ํ›„์— v-model ์€ apple ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค.
  • click ์ด๋ฒคํŠธ ํ˜ธ์ถœ์‹œ์ž‘, ๋๋‚จ (pig์ธ ์ƒํƒœ์—์„œ ํด๋ฆญ์ด๋ฒคํŠธ ์ข…๋ฃŒ)
  • v-model ๊ฐ’ ๋ณ€๊ฒฝ (์ด๋ฒคํŠธ ํ˜ธ์ถœ ๋๋‚œ ์ดํ›„ apple๋กœ ๊ฐ’ ๋ณ€๊ฒฝ)
<b-form-select v-model="selected" :options="options" @change="Changed"/>
{{ type }}
Changed() {
    if ( this.selected == "pig" )
         this.type = "animal";
    if ( this.selectd == "apple" )
         this.type = "fruit";
}
  • nextTick
Changed() {
    Vue.nextTick(() => {
        if ( this.selected == "pig" )
             this.type = "animal";
        if ( this.selectd == "apple" )
             this.type = "fruit";
    });
}