014

πŸ˜‰ ν—·κ°ˆλ Έλ˜ & λͺ°λžλ˜ λΆ€λΆ„λ“€λ§Œ μ •λ¦¬ν•˜λŠ” λ‚˜λ§Œμ˜ TIL
😯 λͺ¨λ“  κ°•μ˜ λ‚΄μš©μ€ 적지 μ•Šμ•„μš”!

였늘의 μ†Œκ°μ€?
Vuex 되게 νŽΈλ¦¬ν•˜λ„€μš”.
데이터듀을 μ»΄ν¬λ„ŒνŠΈ λ‚΄λΆ€μ—μ„œ μ„ μ–Έν•˜μ§€ μ•Šκ³ 
μ „μ—­μ μœΌλ‘œ μ“°μ΄λŠ” 데이터듀을 ν•œλ²ˆμ— λ¬Άμ–΄ 관리할 수 μžˆλ‹€λ‹ˆ.
κ²Œλ‹€κ°€ λͺ¨λ“ˆν™”도 κ°€λŠ₯ν•˜λ‹€λ‹ˆ..!




[1] ν”ŒλŸ¬κ·ΈμΈ

ν”ŒλŸ¬κ·ΈμΈμ„ μž‘μ„±ν•¨μœΌλ‘œμ¨ Vue에 μ „μ—­ κΈ°λŠ₯을 λ§Œλ“€μ–΄μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

export default {
	install: (app, options) => {
		// ν”ŒλŸ¬κ·ΈμΈμ˜ λ‚΄λΆ€ λ‚΄μš©μ€ install λ©”μ†Œλ“œ 내뢀에 μž‘μ„±ν•©λ‹ˆλ‹€.
	});
}
// fetch ν”ŒλŸ¬κ·ΈμΈμ„ λ§Œλ“­λ‹ˆλ‹€.
// $fetch와 같이 $κ°€ λΆ™λŠ” κ²½μš°λŠ” this둜 μ ‘κ·Όν•΄μ„œ μ‚¬μš©ν•  수 μžˆλ‹€λŠ” Vue의 톡상적인 μ˜λ―Έμž…λ‹ˆλ‹€.
export default {
  install(app, component) {
    app.config.globalProperties[options.pluginName || "$fetch"] = (
      url,
      opts
    ) => {
      return fetch(url, opts).then((res) => res.json());
    };
  },
};
import { createApp } from "vue";
import App from "./App.vue";
import fetchPlugin from "~/plugins/fetch";

const app = createApp(App);
app.use(fetchPlugin. {
	pluginName: '$myname'
});
// use둜 μ‚¬μš©ν•΄μ„œ λ“±λ‘ν•©λ‹ˆλ‹€.
// νŠΉμ • 이름을 지정할 수 μžˆμŠ΅λ‹ˆλ‹€.
app.mount("#app");
methods: {
	async init() {
		const res = await this.$myname('url');
		console.log(res);
	}
}




[2] 믹슀인

믹슀인으둜 Vue μ»΄ν¬λ„ŒνŠΈμ— μž¬μ‚¬μš© κ°€λŠ₯ν•œ κΈ°λŠ₯을 λ§Œλ“€μ–΄μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


λ―ΉμŠ€μΈμ€ ν•˜λ‚˜μ˜ μ»΄ν¬λ„ŒνŠΈμ™€ μœ μ‚¬ν•œ ꡬ쑰λ₯Ό μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

mixins: [myMixins]; // 믹슀인의 이름을 props와 λ™μΌν•œ ν˜•νƒœλ‘œ λΆˆλŸ¬μ™€ μ‚¬μš©ν•©λ‹ˆλ‹€.

같은 μ΄λ¦„μ˜ ν›… ν•¨μˆ˜(라이프사이클)λŠ” λͺ¨λ‘ 호좜될 수 있게 배열에 λ³‘ν•©λ©λ‹ˆλ‹€.


λ˜ν•œ methods, data 등도 ν•¨κ»˜ μ‚¬μš©ν•  수 있게 μ μ ˆν•˜κ²Œ λ³‘ν•©λ©λ‹ˆλ‹€.

ν•˜μ§€λ§Œ λ§Œμ•½ 믹슀인 λ‚΄ μ˜΅μ…˜λ“€κ³Ό μ»΄ν¬λ„ŒνŠΈμ˜ μ˜΅μ…˜λ“€μ΄ 쀑볡될 경우, μ»΄ν¬λ„ŒνŠΈμ˜ μ˜΅μ…˜μ΄ μš°μ„ λ˜μ–΄ μ μš©λ©λ‹ˆλ‹€. (ν›… ν•¨μˆ˜ μ œμ™Έ)

// sampleMixin

export default {
  data() {
    return {
      count: 1,
      mag: "HI~",
    };
  },
};
// App.vue

import Hello from "~/components/Hello";
import sampleMixin from "~/mixins/sample";

export default {
  components: {
    Hello,
  },
  mixins: [sampleMixin],
  data() {
    return {
      msg: "Hello Vue!",
    };
  },
};

Untitled

{{ msg }}λ₯Ό 좜λ ₯ν–ˆμ„ λ•Œ, μ»΄ν¬λ„ŒνŠΈμ˜ msgκ°€ 좜λ ₯λ˜λŠ” 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.



[+] 동적 μ»΄ν¬λ„ŒνŠΈ + 믹슀인 예제

λΉ„μŠ·ν•œ 데이터 ν˜•μ‹μ„ λ Œλ”λ§ν•˜λŠ” 두 개의 μ»΄ν¬λ„ŒνŠΈλ₯Ό 동적 μ»΄ν¬λ„ŒνŠΈμ˜ κ°œλ…μœΌλ‘œ 묢은 ν›„,

믹슀인으둜 ν•΄λ‹Ή μ»΄ν¬λ„ŒνŠΈλ“€μ˜ props듀을 μ •μ˜ν•΄μ€„ 수 μžˆμŠ΅λ‹ˆλ‹€.


// App.vue
<template>
  <component
    :is="field.component"
    v-for="field in fields"
    :key="'component-' + field.title"
    v-model="field.value"
    :title="field.title"
    :items="field.items"
  />

  <h1>κ²°κ³Ό</h1>
  <div v-for="field in fields" :key="'result-' + field.title">
    {{ field.value }}
  </div>

  <button @click="submit">제좜</button>
</template>

<script>
import * as FieldComponents from "~/components/fields/index";

export default {
  components: {
    ...FieldComponents,
  },
  data() {
    return {
      fields: [
        {
          component: "TextField",
          title: "이름",
          value: "",
        },
        {
          component: "SimpleRadio",
          title: "λ‚˜μ΄λŒ€",
          value: "",
          items: ["20λŒ€", "30λŒ€", "40λŒ€", "50λŒ€"],
        },
      ],
    };
  },
  methods: {
    submit() {
      const results = this.fields.map(({ title, value }) => ({
        title,
        value,
      }));
      console.log(results);
    },
  },
};
</script>

// index.js - μ΄λ ‡κ²Œ importλ₯Ό λ¬Άμ–΄μ„œ μ‚¬μš©ν•˜λ©΄ μ»΄ν¬λ„ŒνŠΈκ°€ λ§Žμ•„μ§ˆ κ²½μš°μ—λ„ μ½”λ“œκ°€ κΉ”λ”ν•©λ‹ˆλ‹€.
export { default as TextField } from "./TextField";
export { default as SimpleRadio } from "./SimpleRadio";

// mixin.js
export default {
  props: {
    items: {
      type: Array,
      default: () => [],
    },
    title: {
      type: String,
      default: "",
    },
    modelValue: {
      type: String,
      default: "",
    },
  },
  emits: ["update:modelValue"],
};

// SimpleRadio.vue
<template>
  <h3>{{ title }}</h3>
  <ul>
    <li v-for="item in items" :key="item">
      <label>
        <input
          type="radio"
          :value="item"
          :name="title"
          @input="$emit('update:modelValue', $event.target.value)"
        />
        {{ item }}
      </label>
    </li>
  </ul>
</template>

<script>
import fieldMixin from "./mixin";

export default {
  mixins: [fieldMixin],
};
</script>


// TextField.vue
<template>
  <div>
    <h3>{{ title }}</h3>
    <input
      :value="modelValue"
      type="text"
      @input="$emit('update:modelValue', $event.target.value)"
    />
  </div>
</template>

<script>
import fieldMixin from "./mixin";

export default {
  mixins: [fieldMixin],
};
</script>




[3] Teleport

teleport νƒœκ·Έλ₯Ό μ‚¬μš©ν•˜μ—¬ μ»΄ν¬λ„ŒνŠΈ μš”μ†Œλ₯Ό μˆœκ°„μ΄λ™ μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

<template>
  <div @click="onModal">
    <slot name="activator"></slot>
  </div>
  <teleport to="body">
    <!-- ν•˜λ‹¨μ˜ μš”μ†Œλ“€μ„ body νƒœκ·Έ λ‚΄λΆ€λ‘œ μˆœκ°„μ΄λ™ μ‹œν‚΅λ‹ˆλ‹€. -->
    <template v-if="isShow">
      <div class="modal" @click="offModal">
        <div
          :style="{ width: `${parseInt(width, 10)}px` }"
          class="modal__inner"
          @click.stop
        >
          <slot></slot>
        </div>
      </div>
    </template>
  </teleport>
</template>

Untitled 1

fixed λ“± μƒμœ„ μš”μ†Œμ˜ μŠ€νƒ€μΌ 영ν–₯을 λ°›λŠ” μš”μ†Œλ“€μ„ μ΅œμƒλ‹¨μœΌλ‘œ μ΄λ™μ‹œν‚¬ λ•Œ, μ›ν•˜λŠ” λ³„λ„μ˜ μš”μ†Œλ‘œ μ΄λ™ν•˜κΈ° 원할 λ•Œ λ“± μœ μš©ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.



[+] @click.stop

ν•΄λ‹Ή μ½”λ“œμ—μ„œλŠ” 이벀트 버블링이 μΌμ–΄λ‚˜ modal__inner클래슀λ₯Ό 가진 divλ₯Ό 클릭해도 offModal ν•¨μˆ˜κ°€ μ‹€ν–‰λ©λ‹ˆλ‹€.

<template v-if="isShow">
  <div class="modal" @click="offModal">
    <div class="modal__inner">
      <slot></slot>
    </div>
  </div>
</template>

μ΄λ•Œ, modal__inner 클래슀λ₯Ό 가진 div에 @click.stop 속성을 λ„£μ–΄μ£Όμ–΄ 이벀트 μ „νŒŒλ₯Ό 막을 수 μžˆμŠ΅λ‹ˆλ‹€.

<template v-if="isShow">
  <div class="modal" @click="offModal">
    <div class="modal__inner" @click.stop>
      <slot></slot>
    </div>
  </div>
</template>


배운 λ‚΄μš©μ„ μžŠμ§€ λ§™μ‹œλ‹€! 😈




[4] Provide, Inject

일반적으둜 데이터λ₯Ό λΆ€λͺ¨μ—μ„œ μžμ‹ μ»΄ν¬λ„ŒνŠΈμ— 전달할 λ•Œ propsλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

ν•˜μ§€λ§Œ μ΄λŠ” λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ™€ μžμ‹ μ»΄ν¬λ„ŒνŠΈ μ‚¬μ΄μ˜ 데이터λ₯Ό 전달할 뿐, 쑰상 μ»΄ν¬λ„ŒνŠΈμ—μ„œ λ°”λ‘œ 맨 ν•˜μœ„ μ»΄ν¬λ„ŒνŠΈμ— 데이터λ₯Ό 전달해쀄 수 μ—†μŠ΅λ‹ˆλ‹€.

λ¬Όλ‘  propsλ₯Ό κ·Έ 사이에 μžˆλŠ” μ»΄ν¬λ„ŒνŠΈμ— μ „λΆ€ μ •μ˜ν•˜λ©΄ κ°€λŠ₯ν•˜μ§€λ§Œ 맀우 번거둜운 μž‘μ—…μž…λ‹ˆλ‹€.


μ΄λ•Œ Provide와 InjectμŒμ„ μ‚¬μš©ν•΄μ„œ 데이터λ₯Ό 전달할 수 μžˆμŠ΅λ‹ˆλ‹€.

// App.vue
export default {
  components: {
    Parent,
  },
  provide() {
    return {
      msg: this.msg, // data μ˜΅μ…˜ μœ„μͺ½μ— provide μ˜΅μ…˜μœΌλ‘œ 데이터λ₯Ό 후손 μš”μ†Œλ“€μ—κ²Œ λ³΄λ‚΄μ€λ‹ˆλ‹€.
    };
  },
  data() {
    return {
      msg: "App Vue!",
    };
  },
};

// Child.vue
<template>
  <h1>Child {{ msg }}</h1>
</template>

<script>
export default {
  inject: ["msg"], // inject둜 쑰상 μš”μ†Œμ—μ„œ 보내쀀 데이터λ₯Ό λ°›μŠ΅λ‹ˆλ‹€.
};
</script>


ν•˜μ§€λ§Œ provide와 injectλ₯Ό μ‚¬μš©ν•΄μ„œ μ „λ‹¬λœ λ°μ΄ν„°λŠ” λ°˜μ‘ν˜• 데이터가 μ•„λ‹™λ‹ˆλ‹€.


[4-1] computed

computedλŠ” κ³„μ‚°λœ 데이터λ₯Ό λ§Œλ“€ λ•Œ μ‚¬μš©ν•  수 μžˆλŠ” μ˜΅μ…˜μž…λ‹ˆλ‹€.

이λ₯Ό ν•¨μˆ˜ ν˜•νƒœλ‘œ λΆˆλŸ¬μ™€μ„œ μ‚¬μš©ν•˜κ²Œ 되면, μ˜΅μ…˜μ΄ μ•„λ‹Œ ν•˜λ‚˜μ˜ ν•¨μˆ˜λ‘œμ¨ μ›ν•˜λŠ” λΆ€λΆ„μ—μ„œ κ³„μ‚°λœ 데이터λ₯Ό λ§Œλ“€μ–΄μ€„ 수 μžˆμŠ΅λ‹ˆλ‹€.

// App.vue
import Parent from "~/components/Parent";
import { computed } from "vue";

export default {
  components: {
    Parent,
  },
  provide() {
    return {
      msg: computed(() => this.msg),
      // computed ν•¨μˆ˜ 내뢀에 ν•˜λ‚˜μ˜ μ½œλ°±μ„ μƒμ„±ν•΄μ„œ κ³„μ‚°λœ 값을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
    };
  },
  data() {
    return {
      msg: "App Vue!",
    };
  },
};

// Child.vue
<template>
  <h1>Child {{ msg.value }}</h1>
</template>

ν•˜μ§€λ§Œ 이 computedν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜κ²Œ 되면 λ°˜ν™˜κ°’μ΄ μ›λž˜μ˜ 데이터 ν˜•μ‹μ΄ μ•„λ‹™λ‹ˆλ‹€.

λ°”λ‘œ 객체 ν˜•νƒœλ‘œ λ°˜ν™˜μ΄ λ©λ‹ˆλ‹€.

λ”°λΌμ„œ κ³„μ‚°λœ 데이터λ₯Ό 직접 κΊΌλ‚΄ μ‚¬μš©ν•˜κΈ° μœ„ν•΄ .valueλ₯Ό κΌ­ λΆ™μ—¬ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.


μ΄λŠ” Vuexλ₯Ό μ‚¬μš©ν•˜λ©΄ μ „λΆ€ 해결될 λ¬Έμ œμž…λ‹ˆλ‹€. πŸ˜†




[5] Vuex(Store)

μ—¬λŸ¬ μ»΄ν¬λ„ŒνŠΈμ—μ„œ λ™μ‹œμ— μ‚¬μš©λ˜λŠ” λ°μ΄ν„°λŠ” λ³„λ„μ˜ νŒŒμΌμ— μ €μž₯ν•΄μ„œ μ „μ—­μœΌλ‘œ ν™œμš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

// store/index.js
import { reactive } from "vue"; // λ°˜μ‘ν˜• 데이터λ₯Ό μ œκ³΅ν•΄μ£ΌλŠ” vue λ‚΄μž₯ ν•¨μˆ˜μž…λ‹ˆλ‹€.

export const state = reactive({
  msg: "Hello vue",
  count: 1,
});

export const getters = {
  // computed(κ³„μ‚°λœ 데이터) 둜직
  reversedMsg() {
    return state.msg.split("").reverse().join("");
  },
};

export const mutations = {
  // 데이터λ₯Ό λ³€κ²½ν•˜λŠ” 둜직
  increaseCount() {
    state.count += 1;
  },
  decreaseCount() {
    state.count -= 1;
  },
  updateMsg(newMsg) {
    state.msg = newMsg;
  },
};

export const actions = {
  // 기타 둜직
  async fetchTodo() {
    const fetchResult = await fetch(
      "https://jsonplaceholder.typicode.com/todos/1"
    ).then((res) => res.json());

    mutations.updateMsg(fetchResult.title);
  },
};

μ΄λ ‡κ²Œ λ³„λ„μ˜ 파일둜 κ΄€λ¦¬ν•˜κ²Œ 되면 λ‹€μ–‘ν•œ μ»΄ν¬λ„ŒνŠΈμ—μ„œ 데이터λ₯Ό μ‚¬μš©ν•  수 있으며

ν•΄λ‹Ή λ°μ΄ν„°μ˜ 관리가 μ‰¬μ›Œμ§‘λ‹ˆλ‹€.


μ΄λŸ¬ν•œ 데이터 관리 λ‘œμ§μ„ 쑰금 더 μ‰½κ²Œ 해쀄 수 μžˆλŠ” λΌμ΄λΈŒλŸ¬λ¦¬κ°€ λ°”λ‘œ Vuexμž…λ‹ˆλ‹€.


VuexλŠ” μƒνƒœ 관리 νŽ˜ν„΄ λΌμ΄λΈŒλŸ¬λ¦¬μž…λ‹ˆλ‹€.

Vue μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λͺ¨λ“  μ»΄ν¬λ„ŒνŠΈμ— λŒ€ν•œ 쀑앙 집쀑식 μ €μž₯μ†Œ 역할을 ν•˜κ²Œ λ©λ‹ˆλ‹€.

Untitled 2


vuexλŠ” λ‹€μŒ λͺ…λ Ήμ–΄λ‘œ μ„€μΉ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

npm i vuex@next // next λ²„μ „μœΌλ‘œ μ„€μΉ˜ν•©λ‹ˆλ‹€. (4.0 이상)
// store/index.js
import { createStore } from "vuex";

export default createStore({
  state() {
    return {
      msg: "store data",
      count: 1,
    };
  },
  getters: {
    reverseMsg(state) {
      return state.msg.split("").reverse().join("");
    },
  },
  mutations: {
    increaseCount(state) {
      state.count += 1;
    },
    updateMsg(state, newMsg) {
      state.msg = newMsg;
    },
  },
  actions: {
    // context =>  state, getters, commit(mutations), dispatch
    async fetchTodo({ commit }) {
      const todo = await fetch(
        "https://jsonplaceholder.typicode.com/todos/1"
      ).then((res) => res.json());

      commit("updateMsg", todo.title);
    },
  },
});

μ—¬κΈ°μ„œ context 객체둜 μ˜΅μ…˜ μ•ˆμ—μ„œ λ‹€λ₯Έ μ˜΅μ…˜μœΌλ‘œ μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.

contextλŠ” state, getters, commit(mutations), κ·Έ 외인 dispatchλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.

// main.js
const app = createApp(App);
app.use(store); // λ“±λ‘ν•΄μ„œ μ‚¬μš©ν•©λ‹ˆλ‹€.
app.mount("#app");
// Hello.vue
export default {
  computed: {
    msg() {
      return this.$store.state.msg; // $store으둜 μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    },
    count() {
      return this.$store.state.count;
    },
  },
};


[5-1] λͺ¨λ“ˆν™”

vuex의 λ°μ΄ν„°λ‚˜ μ—¬λŸ¬ μ˜΅μ…˜λ“€μ— μ ‘κ·Όν•˜κΈ° μœ„ν•΄ this.$store. ... 의 ν˜•μ‹μœΌλ‘œ μ ‘κ·Όν•©λ‹ˆλ‹€.

ν•˜μ§€λ§Œ λ°μ΄ν„°μ˜ μ–‘, λ˜λŠ” μ—¬λŸ¬ μ˜΅μ…˜ λ‚΄λΆ€ 값듀이 λ§Žμ•„μ§ˆμˆ˜λ‘ store/index.js 파일 ν•˜λ‚˜μ—μ„œ λͺ¨λ“  데이터듀을 κ΄€λ¦¬ν•˜κΈ° νž˜λ“­λ‹ˆλ‹€.


λ”°λΌμ„œ vuexλŠ” store을 κΈ°λŠ₯λ³„λ‘œ μͺΌκ°œμ„œ μ œκ³΅ν•˜λŠ” λͺ¨λ“ˆν™”λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.

Untitled 3

κ·Έλ¦Όκ³Ό 같이 store λ‚΄λΆ€μ—μ„œ λΆ„λ¦¬ν•œ js νŒŒμΌμ„ index.js 파일 μ•ˆμ— λͺ¨λ“ˆν™”ν•΄μ„œ λΆˆλŸ¬μ™€ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

// message.js
export default {
  namespaced: true, // ν•΄λ‹Ήν•˜λŠ” 이름 λ²”μœ„(message)둜 데이터듀을 μ‚¬μš©ν•  수 μžˆλŠ” μ˜΅μ…˜
  state() {
    return {
      message: "hello Store Module",
    };
  },
  getters: {
    reversedMessage(state) {
      return state.message.split("").reverse().join("");
    },
  },
  mutations: {
    updateMessage(state, newMessage) {
      state.message = newMessage;
    },
  },
  actions: {
    async fetchTodo({ commit }) {
      const todo = await fetch(
        "https://jsonplaceholder.typicode.com/todos/1"
      ).then((res) => res.json());

      commit("updateMessage", todo.title);
    },
  },
};
// index.js
export default createStore({
  state() {
	...

	},
	modules: { // modules μ˜΅μ…˜ λ‚΄λΆ€μ—μ„œ λΆˆλŸ¬μ™€ μ‚¬μš©ν•©λ‹ˆλ‹€.
		message
	}
}
// Hello.vue
export default {
  computed: {
    msg() {
      return this.$store.state.msg;
    },
    count() {
      return this.$store.state.count;
    },
    storeMessage() {
      return this.$store.state.message.message;
      // λͺ¨λ“ˆμ˜ 이름, ν•΄λ‹Ή μƒνƒœμ˜ 이름도 λͺ…μ‹œν•΄μ€˜μ•Ό ν•©λ‹ˆλ‹€.
    },
  },
  methods: {
    increaseCount() {
      this.$store.commit("count/increaseCount");
    },
  },
};


[5-2] map~

vuex의 λ‚΄μž₯ ν•¨μˆ˜ mapState, mapGetters, mapMutations, mapActionsλ₯Ό ν™œμš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

import { mapState, mapGetters, mapMutations, mapActions } from "vuex";

export default {
  computed: {
    ...mapState("count", ["count"]),
    ...mapState("message", ["message"]),
  },
};

/* 
	1. λͺ¨λ“ˆμ—μ„œ μƒνƒœ κ°€μ Έμ˜€κΈ°
		...mapState('λͺ¨λ“ˆν™” 된 파일 이름', ['κ°€μ Έμ˜¬ μƒνƒœ 1', 'κ°€μ Έμ˜¬ μƒνƒœ 2'])
	2. λͺ¨λ“ˆν™” 된 파일 이름이 없을 경우 (index.js인 경우) 
		...mapState(['κ°€μ Έμ˜¬ μƒνƒœ1', 'κ°€μ Έμ˜¬ μƒνƒœ2']);
*/





좜처

ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€

Vue.js3 Document

μΉ΄ν…Œκ³ λ¦¬: ,

μ—…λ°μ΄νŠΈ:

λŒ“κΈ€λ‚¨κΈ°κΈ°