Vue3 - ynjch97/YNJCH_WIKI GitHub Wiki

1. Vue Lifecycle

> ๊ฐ Vue ๊ตฌ์„ฑ ์š”์†Œ Instance๋Š” ์ƒ์„ฑ๋  ๋•Œ ์ผ๋ จ์˜ ์ดˆ๊ธฐํ™” ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์น˜๊ฒŒ ๋œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ ๊ด€์ฐฐ(Create)์„ ์„ค์ •ํ•˜๊ณ  ํ…œํ”Œ๋ฆฟ์„ ์ปดํŒŒ์ผํ•˜๊ณ  DOM์— ์ธ์Šคํ„ด์Šค๋ฅผ ๋งˆ์šดํŠธ(Mount)ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ DOM์„ ์—…๋ฐ์ดํŠธ(Update)ํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ ๊ณผ์ •์—์„œ Lifecycle Hooks ์ด๋ผ๋Š” ๊ธฐ๋Šฅ๋„ ์‹คํ–‰ํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ • ๋‹จ๊ณ„์—์„œ ์ž์‹ ์˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

1-1. Vue Instance

  • ๋ชจ๋“  Vue.js ์•ฑ์€ Vue๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฃจํŠธ Vue ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ถ€ํŠธ์ŠคํŠธ๋žฉ ๋จ
  • Instance๋Š” Vue.js ๋กœ ํ™”๋ฉด์„ ๊ฐœ๋ฐœํ•˜๊ธฐ ์œ„ํ•ด ๊ผญ ์ƒ์„ฑํ•ด์•ผ ํ•˜๋Š” ํ•„์ˆ˜ ๋‹จ์œ„
  • new Vue({...}) ๋กœ ์„ ์–ธํ•˜์—ฌ ๋งŒ๋“ค์–ด์ง„ ๊ฐ์ฒด๋ฅผ Vue ์ธ์Šคํ„ด์Šค๋ผ๊ณ  ํ•จ
<script>
new Vue({
  // instance ์ƒ์„ฑ
  // instance option properties
});
</script>

1-2. Composition API

์ปดํฌ์ง€์…˜(Composition) API๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํŠน์ • ๊ธฐ๋Šฅ์„ ๊ฐ–๋Š” ์ฝ”๋“œ๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ๊ตฌ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก Vue3 ๋ฒ„์ „์— ์ถ”๊ฐ€๋œ ํ•จ์ˆ˜ ๊ธฐ๋ฐ˜์˜ API์ด๋‹ค. ์ปดํฌ๋„ŒํŠธ API๊ฐ€ ์ƒ๊ธด ์ด์œ ๋Š” Vue๋Š” ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ๊ด€๋ฆฌํ•˜๊ธฐ ํž˜๋“  ๋‹จ์ ๊ณผ ์ปดํฌ๋„ŒํŠธ์˜ ๊ณ„์ธต๊ตฌ์กฐ๊ฐ€ ๋ณต์žกํ• ์ˆ˜๋ก ์ฝ”๋“œ์— ๋Œ€ํ•œ ์ถ”์  ๋ฐ ๊ด€๋ฆฌ๊ฐ€ ํž˜๋“  ์ ์„ ๋ณด์•ˆํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

1-3. ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜

  • beforeCreate ๋ฐ created(setup() ๋ฉ”์„œ๋“œ ์ž์ฒด๋กœ ๋Œ€์ฒด๋จ)๋ฅผ ์ œ์™ธํ•˜๊ณ  ์„ค์ • ๋ฉ”์†Œ๋“œ์—์„œ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜ API Lifecycle Hooks ์ค‘ 9๊ฐœ
    • onBeforeMount : mounting์ด ์‹œ์ž‘๋˜๊ธฐ ์ „์— ํ˜ธ์ถœ
    • onMounted : ์ปดํฌ๋„ŒํŠธ๊ฐ€ mount๋  ๋•Œ ํ˜ธ์ถœ
    • onBeforeUpdate : ๋ฐ˜์‘ํ˜• ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ์™€ re-render๋˜๊ธฐ ์ „์— ํ˜ธ์ถœ
    • onUpdated : re-render๋œ ํ›„์— ํ˜ธ์ถœ
    • onBeforeUnmount : Vue ์ธ์Šคํ„ด์Šค๊ฐ€ ํŒŒ๊ดด(์‚ญ์ œ)๋˜๊ธฐ ์ „์— ํ˜ธ์ถœ
    • onUnmounted : ์ธ์Šคํ„ด์Šค๊ฐ€ ํŒŒ๊ดด(์‚ญ์ œ)๋œ ํ›„ ํ˜ธ์ถœ๋จ
    • onActivated : ๋ณด๊ด€๋œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ™œ์„ฑํ™”๋˜๋ฉด ํ˜ธ์ถœ
    • onDeactivated : ๋ณด๊ด€๋œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋น„ํ™œ์„ฑํ™”๋˜๋ฉด ํ˜ธ์ถœ
    • onErrorCaptured : ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ์บก์ฒ˜๋˜๋ฉด ํ˜ธ์ถœ

1-4. ์—…๋ฐ์ดํŠธ๋œ ํ•ญ๋ชฉ

  • Vue 2 ์ฝ”๋“œ๋ฅผ Vue 3 Lifecycle Hooks ๋กœ ์—…๋ฐ์ดํŠธ๋œ ํ•ญ๋ชฉ
    • beforeCreate -> use setup()
    • created -> use setup()
    • beforeMount -> onBeforeMount
    • mounted -> onMounted
    • beforeUpdate -> onBeforeUpdate
    • updated -> onUpdated
    • beforeDestroy -> onBeforeUnmount
    • destroyed -> onUnmounted
    • errorCaptured -> onErrorCaptured

2. Vue Component

2-1. props

  • props ๊ฐ€ ๋งŽ๋‹ค๋Š” ๊ฒƒ์€ ์ด๋ฏธ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ(Parent Component)์—์„œ ๋งŽ์€ ์†์„ฑ์„ ์ „๋‹ฌํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ
  • props ๋Š” ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์—์„œ ์ง์ ‘์ ์œผ๋กœ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ > ์ด๋ฏธ ๋„˜์–ด์˜จ props ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ๋ฐ”์ธ๋”ฉ ๋˜์–ด์žˆ๋Š” props ๋ฅผ data ์— ์žฌ ๋ฐ”์ธ๋”ฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ
    • watch ์™€ ๊ฐ™์€ ๊ฐ์‹œ์ž์™€ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋Š” $emit ์ด ๋งŽ์•„์ง

2-1. watch

  • watch ๊ฐ€ ๋งŽ๋‹ค๋Š” ๊ฒƒ์€ ์ด๋ฏธ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ˜๊ฐ•์ œ์ ์œผ๋กœ ๋ฐ˜์‘์ ์ธ ๋ชจ๋ธ์ด ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ
  • watch ๊ฐ€ ๋งŽ์•„์ง€๊ฒŒ ๋˜๋ฉด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค๋ฅธ ๊ณณ์— ๋ฐ”์ธ๋”ฉํ•˜์˜€์„ ๋•Œ ์˜๋„์น˜ ์•Š์€ ๋™์ž‘์„ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ์Œ
  • ํŠนํžˆ๋‚˜ Vue.js ์˜ ๋ฐ˜์‘์  ๋ชจ๋ธ์€ Application ์˜ ์„ฑ๋Šฅ์— ์ง์ ‘์ ์ธ ์—ฐ๊ด€ > watch ์ตœ์†Œํ™”

3. v-form, v-input

3-1. Request ์ฐจ๋‹จ

  • ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฐ’์„ Submit ํ•˜๋ฉด ์ œ์ถœ ๋ฒ„ํŠผ์ด ๋น„ํ™œ์„ฑํ™” ๋˜๋Š” ๋“ฑ, ์ž˜๋ชป๋œ ํ˜•ํƒœ์˜ Request๋ฅผ ๋ณด๋‚ด์ง€ ์•Š๊ฒŒ ์ฐจ๋‹จํ•ด์•ผ ํ•จ
    • value ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด(@change) ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด ์กด์žฌํ•˜๋‚˜, ์‚ฌ์šฉ์ž๊ฐ€ focus out ํ•ด์•ผ๋งŒ change ์ƒํƒœ๊ฐ€ ์ธ์‹๋œ๋‹ค๋Š” ๋ฌธ์ œ์  ๆœ‰
  • ์œ ํšจ์„ฑ์„ ์ฒดํฌ๋ฅผ ๋ชจ๋‘ ํ†ต๊ณผํ•ด์•ผ Submit : v-form ์— ref="form" ๊ธฐ์žฌ
  • :rules : ๊ฐ€์ ธ์˜ฌ ๊ทœ์น™๋ช…์„ ์ž…๋ ฅ
<v-form ref="form" @submit.prevent="login">
  <v-text-field
    :rules="emailRule"
  />
</v-form>

<script lang="ts">
data: () => ({
  email: "",
  password: "",
  passwordShow: false,
  autoLoginCheckBox: false,
  emailRule: [
    (v) => !!v || "์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.",
    (v) => {
      const replaceV = v.replace(/(\s*)/g, "");
      const pattern =
        /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/;
      return pattern.test(replaceV) || "์ด๋ฉ”์ผ ํ˜•์‹์œผ๋กœ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”";
    },
  ],
  passwordRule: [
    (v) => !!v || "๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.",
    (v) => {
      const replaceV = v.replace(/(\s*)/g, "");
      return replaceV.length >= 8 || "8์ž๋ฆฌ ์ด์ƒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.";
    },
  ],
});
</script>
  • Submit ์‹œ์—๋Š” this.$refs.form.validate() ๋กœ ์œ ํšจ์„ฑ ์ฒดํฌ ๊ฒฐ๊ณผ ํ™•์ธ ๊ฐ€๋Šฅ
<script>
methods:{
    async login(){
      const validate = this.$refs.form.validate()
      if (validate){
        const email = this.email.replace(/(\s*)/g, '')
        const password = this.password.replace(/(\s*)/g, '')
        await this.$store.dispatch('LOGIN', { email, password, saveLogin:this.autoLoginCheckBox })
      }
    }
  }
</script>

3-2. Quasar ์œ ํšจ์„ฑ ์ฒดํฌ

  • q-form ์— ref ๊ฐ’ ์ง€์ •
    • :rules="[user_pw_rules]" : script ์—์„œ ์ฒ˜๋ฆฌํ•  ํ•จ์ˆ˜ user_pw_rules ๊ธฐ์žฌ
<q-form ref="loginForm" class="q-gutter-md">
    <q-input square filled clearable v-model="user_id" :rules="[user_id_rules]" type="text" label="ID" />
    <q-input square filled clearable v-model="user_pw" :rules="[user_pw_rules]" type="password" label="password" />
</q-form>

3-2-1. rules

  • ์œ ํšจ์„ฑ ์ฒดํฌ์— ์œ„๋ฐ˜๋˜๋Š” ๊ฒฝ์šฐ, ๋นจ๊ฐ„ ํ…Œ๋‘๋ฆฌ๊ฐ€ ์ƒ๊ธฐ๋ฉด์„œ ํ•˜๋‹จ์— ์—๋Ÿฌ ๋ฌธ๊ตฌ๊ฐ€ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์ด ๋””ํดํŠธ ๋™์ž‘
  • boolean ํ•จ์ˆ˜/๋ณ€์ˆ˜๋“ค์„ ๋„ฃ์„ ์ˆ˜ ์žˆ์œผ๋‚˜, async-await(Promise)๋Š” ๋„ฃ์„ ์ˆ˜ ์—†์Œ
  • ์•„๋ž˜์™€ ๊ฐ™์ด rules ์— ๋ฐ”๋กœ ์œ ํšจ์„ฑ ์ฒดํฌ ๋กœ์ง์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Œ
:rules="[val => val.length <= item.maxLength || `${item.maxLength}์ž๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค.`]"

:rules="[val => !getNotNullYn(val, item) || 'ํ•„์ˆ˜๋กœ ์ž…๋ ฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.'
    , val => { let textLength = getTextLength(val);
          return textLength <= item.maxLength || `${item.maxLength}์ž๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค.`} ]"

3-2-2. ์‹ค์ œ ํ™œ์šฉํ•œ ์†Œ์Šค

<q-form ref="updateForm">
    <q-input
			v-if="item.type === 'text'"
			type="text"
			:rules="[val => !getNotNullYn(val, item) || 'ํ•„์ˆ˜๋กœ ์ž…๋ ฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.'
					    , val => { let textLength = getTextLength(val);
							return textLength <= item.maxLength || `${item.maxLength}์ž๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค.`} ]"
			v-model="item.data"
		/>
		<q-input
			v-if="item.type === 'number'"
			type="number"
			:rules="item.maxLength && [val => val.length <= item.maxLength || `${item.maxLength}์ž๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค.`]"
			v-model="item.data"
		/>
    <q-btn label="์ถ”๊ฐ€" @click="updateInfo('1', clickedRow)" />
</q-form>

<script setup>
const updateForm = ref(null); // ์ž…๋ ฅ/์ˆ˜์ • ํผ


const updateInfo = async (type, updatedRow) => {
	const valid = await updateForm.value.validate(); // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๊ฒฐ๊ณผ๋ฅผ ๋‹ด์Œ

	if (!valid) {
		$q.notify({ color: 'negative', message: '์œ ํšจํ•œ ๊ฐ’์ด ์•„๋‹™๋‹ˆ๋‹ค.' });
		return;
	}

	const bmigHeaders = new Headers();
	bmigHeaders.append('Content-Type', 'application/x-www-form-urlencoded');

  // ์ค‘๋žต (Submit ํ•˜๋Š” ๊ณผ์ •)
};
</script>

4. Vue Event

4-1. Vue Event

์ด๋ฒคํŠธ๋ช… ์„ค๋ช…
click ๋งˆ์šฐ์Šค๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ์‹คํ–‰ํ•จ
dblclick ๋งˆ์šฐ์Šค๋ฅผ ๋”๋ธ” ํด๋ฆญํ–ˆ์„ ๋•Œ ์‹คํ–‰ํ•จ
mouseover ๋งˆ์šฐ์Šค์˜ ํฌ์ธํŠธ๊ฐ€ ์š”์†Œ ์œ„๋กœ ์˜ฌ๋ผ์™”์„ ๋•Œ ์‹คํ–‰ํ•จ
mouseout ๋งˆ์šฐ์Šค์˜ ํฌ์ธํŠธ๊ฐ€ ์š”์†Œ ๋ฐ–์œผ๋กœ ๋ฒ—์–ด๋‚ฌ์„ ๋•Œ ์‹คํ–‰ํ•จ
mousemove ๋งˆ์šฐ์Šค์˜ ํฌ์ธํŠธ๊ฐ€ ์ด๋™ํ–ˆ์„ ๋•Œ ์‹คํ–‰ํ•จ
mousedown ๋งˆ์šฐ์Šค์˜ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์‹คํ–‰ํ•จ
mouseup ๋งˆ์šฐ์Šค์˜ ๋ฒ„ํŠผ์„ ๋†“์•˜์„ ๋•Œ ์‹คํ–‰ํ•จ
keydown ํ‚ค๋ณด๋“œ์˜ ํ‚ค๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ ์‹คํ–‰ํ•จ
keyup ํ‚ค๋ณด๋“œ์˜ ํ‚ค๋ฅผ ๋†“์•˜์„ ๋•Œ ์‹คํ–‰ํ•จ
keypress ํ‚ค๋ณด๋“œ์˜ ํ‚ค๋ฅผ ๋ˆŒ๋ €๋‹ค๊ฐ€ ๋†“์•˜์„ ๋•Œ ์‹คํ–‰ํ•จ
change ์š”์†Œ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ์‹คํ–‰ํ•จ
submit Form ์ด ์ œ์ถœ๋  ๋•Œ ์‹คํ–‰ํ•จ
reset Form ์ด ์žฌ์„ค์ •๋  ๋•Œ ์‹คํ–‰ํ•จ
select select ์˜ ๊ฐ’์ด ์„ ํƒ๋˜์—ˆ์„ ๋•Œ ์‹คํ–‰ํ•จ
focus ํƒœ๊ทธ์— ํฌ์ปค์Šค๊ฐ€ ์žˆ์„ ๋•Œ ์‹คํ–‰ํ•จ
blur ํƒœ๊ทธ์— ํฌ์ปค์Šค๋ฅผ ์žƒ์—ˆ์„ ๋•Œ ์‹คํ–‰ํ•จ

4-2. Event ์—ฌ๋Ÿฌ ๊ฐœ ์‚ฌ์šฉ

  • Event ์—ฌ๋Ÿฌ ๊ฐœ ์‚ฌ์šฉ ์‹œ ๋Œ€๊ด„ํ˜ธ ์•ˆ์—์„œ ์ฝค๋งˆ๋กœ ๊ตฌ๋ถ„
<template>
  <div>
    <button @click="[method1(), method2()]">ํด๋ฆญ ๋ฒ„ํŠผ</button>
  </div>
</template>

5. Axios

  • https://axios-http.com/kr/docs/intro
  • node.js์™€ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์œ„ํ•œ Promise ๊ธฐ๋ฐ˜ HTTP ํด๋ผ์ด์–ธํŠธ
  • ๋™์ผํ•œ ์ฝ”๋“œ๋ฒ ์ด์Šค๋กœ ๋ธŒ๋ผ์šฐ์ €์™€ node.js์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Œ
    • ์„œ๋ฒ„ ์‚ฌ์ด๋“œ์—์„œ๋Š” ๋„ค์ดํ‹ฐ๋ธŒ node.js์˜ http ๋ชจ๋“ˆ์„ ์‚ฌ์šฉ, ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)์—์„œ๋Š” XMLHttpRequests๋ฅผ ์‚ฌ์šฉ

5-1. ํŠน์ง•

  • ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์œ„ํ•ด XMLHttpRequests ์ƒ์„ฑ
  • node.js๋ฅผ ์œ„ํ•ด http ์š”์ฒญ ์ƒ์„ฑ
  • Promise API๋ฅผ ์ง€์›
  • ์š”์ฒญ ๋ฐ ์‘๋‹ต ์ธํ„ฐ์…‰ํŠธ
  • ์š”์ฒญ ๋ฐ ์‘๋‹ต ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜
  • ์š”์ฒญ ์ทจ์†Œ
  • JSON ๋ฐ์ดํ„ฐ ์ž๋™ ๋ณ€ํ™˜
  • XSRF๋ฅผ ๋ง‰๊ธฐ์œ„ํ•œ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ์ง€์›

6. ๋ฐฐ์—ด๊ณผ ๊ฐ์ฒด

6-1. ๊ฐ์ฒด ๋ฐฐ์—ด์—์„œ ํŠน์ • ์›์†Œ ์ฐพ๊ธฐ

	if (res.status === 200) {
		res = await res.json();
		
		console.log(res.rows);
		console.log(res.rows[0]['bmigEnginePkey']);
		console.log(res.rows.findIndex((item) => item['bmigEnginePkey'] === 73));
		console.log(res.rows.findIndex((item) => item.bmigEnginePkey === 73));
	}
โš ๏ธ **GitHub.com Fallback** โš ๏ธ