Skip to content

Vue.js

사용자 인터페이스를 구축하기 위한 JavaScript 표준 프레임워크
표준 HTML, CSS, JS를 기반으로 구축되며 컴포넌트 기반 프로그래밍 모델 제공

Introduction

핵심 기능

  • 선언적 렌더링(Declarative Rendering) : 표준 HTML을 템플릿 문법으로 확장하여 JavaScript 상태(State)를 기반으로 화면에 출력될 HTML을 선언적(declaratively)으로 작성할 수 있음
  • 반응성(Reactivity) : JavaScript 상태(State) 변경을 추적하고, 변경이 발생하면 DOM을 효율적으로 업데이트하는 것을 자동으로 수행

Progressive Framework

  • 빌드 과정 없이 Static HTML에 적용
  • 모든 페이지에 웹 컴포넌트로 추가
  • SPA (Single Page Application)
  • SSR (Server Side Rendering)
  • SSG (Static Site Generation)
SFC
Single File Component : 컴포넌트의 논리(JS), 템플릿(HTML) 및 스타일(CSS)을 하나의 파일에 캡슐화
Example
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
  <button @click="count++">Count is: {{ count }}</button>
</template>

<style scoped>
button {
  font-weight: bold;
}
</style>

API Style

정확히 동일한 기본 시스템에 의해 구동되는 서로 다른 인터페이스이며, 옵션 API는 컴포지션 API 위에 구현된다
Options API
옵션의 data, methods 및 mounted 같은 객체를 사용하여 컴포넌트의 로직 정의
옵션으로 정의된 속성은 컴포넌트 인스턴스를 가리키는 함수 내부의 this에 노출됨
<script>
export default {
  // data()에서 반환된 속성들은 반응적인 상태가 되어 `this`에 노출됩니다.
  data() {
    return {
      count: 0
    }
  },

  // methods는 속성 값을 변경하고 업데이트 할 수 있는 함수.
  // 템플릿 내에서 이벤트 헨들러로 바인딩 될 수 있음.
  methods: {
    increment() {
      this.count++
    }
  },

  // 생명주기 훅(Lifecycle hooks)은 컴포넌트 생명주기의 여러 단계에서 호출됩니다.
  // 이 함수는 컴포넌트가 마운트 된 후 호출됩니다.
  mounted() {
    console.log(`숫자 세기의 초기값은 ${ this.count } 입니다.`)
  }
}
</script>

<template>
  <button @click="increment">숫자 세기: {{ count }}</button>
</template>
Composition API
import해서 가져온 API 함수들을 사용하여 컴포넌트의 로직 정의
SFC에서 컴포지션 API는 일반적으로 <script setup>과 함께 사용된다
<script setup>
import { ref, onMounted } from 'vue'

// 반응적인 상태의 속성
const count = ref(0)

// 속성 값을 변경하고 업데이트 할 수 있는 함수.
function increment() {
  count.value++
}

// 생명 주기 훅
onMounted(() => {
  console.log(`숫자 세기의 초기값은 ${ count.value } 입니다.`)
})
</script>

<template>
  <button @click="increment">숫자 세기: {{ count }}</button>
</template>

Pinia

  • storeToRefs :

Example 1

<template>
    <h3>현재 값: {{ counter.count }}</h3>
    <h3>{{ counter.name }}</h3>
    <h3>{{ counter.myInfo }}</h3>
    <img :src="counter.logo" />
</template>

<script setup>
import { useCounterStore } from "@/stores/counter";

const counter = useCounterStore();
counter.increment();
counter.increment();
counter.increment();
</script>
<template>
    <h3>현재 값: {{ count }}</h3>
    <h3>{{ name }}</h3>
    <h3>{{ myInfo }}</h3>
<img :src="logo">        
</template>

<script setup>
import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia'

const counter = useCounterStore()
const {count, name, myInfo} = storeToRefs(counter); // 반응형 객체에 사용
const {logo, increment} = counter;

increment();
increment();
increment();
</script>
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useCounterStore = defineStore('counter', () => {
    const count = ref(0);
    const name = ref('유니코');
    const logo = '/src/assets/pinialogo.png';

    const myInfo = computed(() => `이름은 ${name.value} 입니다`);

    function increment() {
    count.value++
    }
    return { count, name, logo, myInfo, increment }
},
)

Example 2 - click

<template>
    <div>
        <input type="text" v-model="text" />
        <button @click="addList(text)">추가</button>
        <h3>[ 추가된 목록 ]</h3>
        <p v-for="(item, index) in getDataAll" :key="index">
        {{ item }}
        </p>
    </div>
</template>
<script setup>
    import { ref } from 'vue';
    import { useListStore } from '@/stores/liststore';
    import { storeToRefs } from 'pinia';

    const text = ref("");
    const list = useListStore();
    const { getDataAll } = storeToRefs(list);

    function addList() {
        if (!text.value) 
        return;
        list.addList(text.value);
        text.value = "";
    }
</script>
import { defineStore } from "pinia";
import { ref, computed } from "vue";

export const useListStore = defineStore("list", () => {
    const list = ref([]);
    function addList(param) {
        list.value.push(param);
    }
    const getDataAll = computed(() => list.value);
    return { list, addList, getDataAll };
});

Example 3 - watch

<template>
    <h2>watch와 watchEffect 테스트</h2>
    <div>
        <h3>{{ num1 }}</h3>
        <button @click="num1++">increase num1</button>
        <h3>{{ num2 }}</h3>
        <button @click="num2++">increase num2</button>
    </div>
</template>

<script setup>
import { ref, watch, watchEffect } from 'vue';
const num1 = ref(10);
const num2 = ref(100);

// watch : num1 값의 변경이 감지되어야 실행이됨.
watch(num1, (after, previous) => {
    console.log(`[W]현재값 : ${after}`);
    console.log(`[W]이전값 : ${previous}`);
});

watchEffect(() => {
    console.log("num1 이나 num2 가 변경됨!!!");
    console.log(`[WE]num1 : ${num1.value}`);
    console.log(`[WE]num2 : ${num2.value}`);
});        
</script>

Quote