본문 바로가기
Vue

vue 기본 문법

by Coarti 2024. 6. 17.

Life-Cycle 

컴포넌트 생성부터 소멸까지

 

Life-Cycle Hooks

Life-Cycle 중간중간 생성 단계 이름으로 된 함수를 지칭

Hook 이름으로 함수를 선언하고 실행해보는게 이해하는데 편안함

<template>
  <div>
    {{ count }}
  </div>
  <h1>Vue.js 라이플 사이클 테스트</h1>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  beforeCreate() {
    console.log("LifeCycle is beforCreate", this.count);
    // this.test() 
  },
  created() {
    console.log("LifeCycle is created", this.count);
    this.test();
  },
  // beforeMount() {
  //   console.log("LifeCycle is beforeMount", document.querySelector('h1'));
  // },
  // mounted() {

  //   console.log("LifeCycle is mounted", document.querySelector('h1'));
  // },
  methods: {
    test() {
      console.log('함수 호출!!')
    }
    
  },
};
</script>

<style lang="scss" scoped></style>

출력

보간법이라고 하는데 중괄호 2개 겹쳐서 사용 '{{  }}'

출력타입은 무조건 문자열

혹여나 태그를 삽입하고 싶으면 innerHTML 기능과 비슷한 것이 있음

<template>

  <div>{{ rawHtml2 }}</div> // 문자열로 나옴 
  <div v-html="rawHtml2"></div> // innerHTML 같은 기능
</template>

<script>
export default {
  data() {
    return {
      rawHtml2:
        '<span style="color: tomato;">이것은 토마토 색이여.</span>',
    }
  },
};
</script>

<style scoped>

</style>

바인드

data() 리턴 값으로

  1. 조건문을 만들어 활성화 여부를 정할수 있음, true | false 도 물론가능
    • 예시는 class인데 id도 있고 :disable 이런것도 있음
  2. inline style에도 속성 값으로도 사용
  3. 여기저기 다 쓰임
<template>
  <h2 v-bind:class="{ active: isActive }">클래스 바인딩 테스트</h2>
  <h2 :class="{ active: isActive }">클래스 바인딩 테스트</h2>
  <button @click="change">버튼</button>

  <h3 style="color: red; font-size: 24pt">스타일 바인딩 테스트</h3>
  <h3 :style="{color:'#888888', fontSize: 24 + 'pt'}">스타일 바인딩 테스트</h3>
  <h3 :style="{color:fontColor, fontSize: fontSize + 'pt'}">스타일 바인딩 테스트</h3>
</template>

<script>
export default {
  data() {
    return {
      isActive: false,
      fontColor: '#888888',
      fontSize: 36
    };
  },
  methods: {
    change() {
      this.isActive = !this.isActive;
    },
  },
};
</script>

<style scoped>
h2.active {
  color: green;
}
</style>

조건문

태그에 속성으로 사용하면 되고

흔히 아는거하고 비슷함

  • v-if="조건"
  • v-else-if="조건"
  • v-else
  • v-show 이건 css display 속성 달고 나옴 안보이는 거지 없는건 아님

이벤트 핸들러

onclick 이런거 표시하는 방법임

  • 정식 : v-on:click="실행할 함수"
  • 약식 : @click="실행할 함수"
  • @chagne, @checked, @keyup, ... 많겠지?
  • 함수대신에 data() 여기서 넘어온 변수명 조작도 됨 count ++ 이런거
<template>
  <div>
    <button v-on:click="count++">인라인 핸들러</button>
    <h1>{{ count }}</h1>
    <br>
    <button v-on:click="changeName()">메서드 핸들러</button>
    //<button @click="changeName()">메서드 핸들러</button>
    <h1>{{ name }}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
      name: "Vue.js",
    };
  },
  methods: {
    changeName() {
      this.name = "변경된 텍스트 데이터 입니다."
    }
  }
};
</script>

<style lang="scss" scoped></style>

for문

이것도 아는거 하고 비슷함

Jquery로 for문 돌려봤으면 한번에 이해 가능 

:key는 꼭하래, 공식문서에서도 권장하네

페이지 새로고침하면 :key 확인해서 변경점이 있는 녀석만 다시 만들어 내어서 전기세 덜 내고 로딩 시간 절약 가능
<template>
  <ul>
    <li>{{ sampleArr[0] }}</li>
    <li>{{ sampleArr[1] }}</li>
    <li>{{ sampleArr[2] }}</li>
    <li>{{ sampleArr[3] }}</li>
    <br />
    <li v-for="(item, idx) in sampleArr" :key="item" @click="openDialog(item || idx)">{{ item }} - {{ idx }}</li>
    <br />
    <li v-for="(item, idx) in ortherArr" :key="item.id">
      {{ item.id }} / {{ item.name }} / {{ idx }}
    </li>
  </ul>
</template>

<script>
export default {
  data() {
    return {
      sampleArr: ["a", "b", "c", "d"],
      ortherArr: [
        { id: 0, name: "John" },
        { id: 1, name: "Kim" },
        { id: 2, name: "Han" },
        { id: 3, name: "Park" },
      ],
    };
  },
  methods: {
    openDialog(result) {
      console.log(result);
    }
  }
};
</script>

<style lang="scss" scoped></style>

 

Computed

Compute: 계산하다, Computer: 컴퓨터, 계산용 전자 기기, Computed: 계산된

(한번 || 미리) 계산된 정보를 가져다가 쓰는 것

캐싱 되어있는 데이터를 가져온다는 것인데 

한번 실행 하고 그 결과를 어딘가에 가지고 있다가 호출 될 때마다 결과만 꺼내주는 거임

<template>
  <h1>{{ text }}</h1>
  <h1>changeText 함수 호출 값: {{ changeText() }}</h1>
  <h1>changeText 함수 호출 값: {{ changeText() }}</h1>
  <h1>changeText 함수 호출 값: {{ changeText() }}</h1>

  <h2>{{ computedText }}</h2>
  <h2>{{ computedText }}</h2>
  <h2>{{ computedText }}</h2>
  <!-- 함수 모양이지만 데이터 이기에 함수호출 기호쓰면 컴퓨터가 혼냄 -->
  <!-- <h2>{{ computedText() }}</h2> -->
</template>

<script>
export default {
  data() {
    return {
      text: "Computed 테스트 데이터 문구입니다.",
    };
  },
  // computed는 캐싱 기능이 있기 때문에 method와 어떤 차이점이 있는지 확인
  // 결론 : 캐싱기능이 있어 콘솔로그가 1번만 출력됨
  computed: {
    computedText() {
      console.log("Computed 기능을 생성하였습니다.");

      return this.text.split('').reverse().join('')
    }

  },
// 결론 : 캐싱기능이 없어 콘솔로그가 3번 출력됨
  methods: {
    changeText() {
      console.log('함수 호출');

      return this.text.split('').reverse().join('')
    },
  },
};
</script>

<style lang="scss" scoped></style>

 

watch

보고 있다는데 뭘 보고 있냐면 data()에 선언한 변수를 보고 있다는 거임

왜 보고 있냐면 변수 값이 변하면 개발자가 정해준데로 해준다는 것

<template>
  <button v-on:click="changeMessage">{{ message }}</button>
  {{ watchMessage }}
  <br />

  //<button @click="changeMessage">{{ message }}</button>
</template>

<script>
export default {
  data() {
    return {
      message: "안녕하세요 Vue.js Watch 기능 테스트 오리지널 문구",
      watchMessage: "",
    };
  },
  watch: {
    // 함수처럼 생긴거지 변수를 바라보고 있는거임
    // 변경이 감지되었을 때 동작함
    // conputed도 감지 가능
    // 보통 게시판에서 한 컬럼을 선택하였을 때, 고유한 id 값이 바뀜을 감지하고
    // 이때, 그 id 값에 따른 상세 데이터를 호출할 때, 주로 사용한다.
    message() {
      // alert('또또 변경됨')
      this.watchMessage = "Watch 동작";
    },
    id() {
      // 해당 상세 데이터를 조회하는 api 호출
    }
  },
  methods: {
    changeMessage() {
      console.log(this.message);
      this.message = "변경됨";
    },
  },
};
</script>

<style lang="scss" scoped></style>

 


Vue3에서 구현하는 스타일이 2가지가 있음

OptionalAPI, CompositionAPI 팀원과 상의해서 사용하자

OptionalAPI

1. Props(부모가 자식에게)

 부모

<template>
  <div>
    <ChildComponent
      v-bind:sendProps1="title"
      v-bind:sendProps2="createAt"
      :sendProps3="obj"
    />
  </div>
</template>

<script>
import ChildComponent from "./components/ChildComponent_OptionalAPIWithProps.vue";

export default {
  components: {
    ChildComponent,
  },

  data() {
    return {
      title: "부모컴포넌트에서 선언된 데이터",
      createAt: 2024,
      obj: {
        id: 2000,
        name: "John",
      },
    };
  },
};
</script>

<style lang="scss" scoped></style>

 자식

<template>
  <div>{{ sendProps1 }}</div>
  <div>{{ sendProps2 }}</div>
  <div>{{ sendProps3.id }}</div>
  <div>{{ sendProps3.name }}</div>
</template>

<script>
export default {
  props: {
    sendProps1: String,
    sendProps2: Number,
    sendProps3: Object,
  },
  data() {
    return {};
  },
};
</script>

<style lang="scss" scoped></style>

부모에서 data()에 선언한 변수 값을 자식이 받는 형태

<script>에서 <templete> 방향으로 진행됨

2. Emit(자식이 부모에게)

자식

<template>
  <button @click="sendEvent">자식컴포넌트에서 만든 버튼</button>
</template>

<script>
export default {
  data() {
    return {
      text: "자식 컴포넌트에서 선언된 데이터",
    };
  },
  methods: {
    sendEvent() {
      this.$emit("send-event", this.text);
    },
  },
};
</script>

<style lang="scss" scoped></style>

 

부모

<template>
  <div>
    부모컴포넌트 레이아웃
    <ChildComponent @send-event="parentEvent" />
  </div>
</template>

<script>
import ChildComponent from "./components/ChildComponent_OptionalAPIWithEmit.vue";

export default {
  components: {
    ChildComponent,
  },
  methods: {
    parentEvent(event) {
      console.log(event);
    },
  },
};
</script>

<style lang="scss" scoped></style>

$emit을 사용한 것이 특징

 

Spring 에서 requset.setAttribute("send-event", text); 사용하는 느낌적인 느낌

부모쪽에서 자식이 만들어준 이벤트를 실행 하면 자식이 넘겨준 결과 값으로 부모가 조절하는 느낌

 

된장찌개 끓이다가 '두부가져와라' 하면 자식이 두부 한 모 부모님한테 주고 부모님은 두부 자르는 느낌

CompositionAPI

내장객체를 활용하며 TypeScript(setup lang="ts")와 같이 동작해 봄

import를 잘보자

  • ref: 단일 변수 초기값 지정
  • reactive: 객체의 속성 값 지정

Props

부모

<template>
  <div>
    <ChildComponent
      v-bind:sendProps1="title"
      v-bind:sendProps2="createAt"
      :sendProps3="obj"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from "vue";
import ChildComponent from "./components/ChildComponent_CompositionAPIWithProps.vue";

interface Obj {
  id: number;
  name: string;
}

const title = ref<string>("부모컴포넌트에서 선언된 데이터");
const createAt = ref<number>(2024);
const obj = reactive<Obj>({
  id: 2000,
  name: "John",
});
</script>

<style lang="scss" scoped></style>

자식

<template>
  <div>toRefs 미사용</div>
  <div>{{ props.sendProps1 }}</div>
  <div>{{ props.sendProps2 }}</div>
  <div>{{ props.sendProps3.id }}</div>
  <div>{{ props.sendProps3.name }}</div>
  <br />
  <div>toRefs 사용</div>
  <div>{{ sendProps1 }}</div>
  <div>{{ sendProps2 }}</div>
  <div>{{ sendProps3.id }}</div>
  <div>{{ sendProps3.name }}</div>
</template>

<script setup lang="ts">
// import { defineProps } from 'vue' // 안해도 됨
import { toRefs } from "vue";
interface Obj {
  id: number;
  name: string;
}
// 1. 컴포지션 API에서 타입스크립트를 활용하는 방법
// 1-1. Prop 받은 데이터 형식에 맞게 타입을 지정해준다.

// Prop 받은 데이터 이름 자체에 미리 선언해둔 타입을 설정해준다.
interface Props {
  sendProps1: String;
  sendProps2: Number;
  sendProps3: Obj;
}

// defineProps ToRefs 내장함수를 통해 Prop 받은 데이터를 활용하여 템플릿 부분에 호출하여 사용
const props = defineProps<Props>();
const { sendProps1, sendProps2, sendProps3 } = toRefs(props);
</script>

<style lang="scss" scoped></style>

조금더 체계화 되어 코드스러움이 느껴진다

defineProps()를 사용하는게 특징

Emit

자식

<template>
  <button @click="sendEvent">자식컴포넌트에서 만든 버튼</button>
</template>

<script setup lang="ts">
import { ref } from "vue";

const data = ref<string>("자식 컴포넌트에서 선언된 데이터");
const emit = defineEmits(["send-event"]);
const sendEvent = () => {
  emit("send-event", data.value);
};
</script>

<style lang="scss" scoped></style>

부모

<template>
  <div>
    부모컴포넌트 레이아웃
    <ChildComponent @send-event="parentEvent" />
  </div>
</template>

<script setup lang="ts">
import ChildComponent from "./components/ChildComponent_CompositionAPIWithEmit.vue";

const parentEvent = (event: string) => {
  console.log(event);
};
</script>

<style lang="scss" scoped></style>

defineEmit()을 사용한다

 

 


v-model, slot, provide, inject 등이 있는데 정리하다 보니 공식문서가 훨씬 정리가 잘 되어 있다

궁금한건 이쪽에서 찾아보는 편이 좋겠다

 

Vue는 문법적으로 간결하고 구현 방법이 정형화 된 것 처럼 보인다

Django와 비슷한 느낌을 받았고 진입장벽이 낮은 듯했다.

그렇다고 성능이 안좋은 것도 아니다

React 처럼 Virtual DOM 을 활용하여 속도와 리소스 측면에서 이점을 보인다.

 

 

 

영상을 참조하여 작성하였습니다.

728x90

'Vue' 카테고리의 다른 글

vue3 + spring legacy + axios 설정(install 생략)  (0) 2024.06.18
vue-persistedstate  (0) 2024.06.18
Cannot read properties of undefined (reading '__vccOpts')  (1) 2024.06.18
vue 실행  (1) 2024.06.18
vue 특징  (0) 2024.06.18