카테고리 없음

Vue.js 기초(3)

nh_3521099031483 2024. 3. 14. 18:37

핵심문법 - Data

 

인라인 핸들러 : 이벤트가 트리거될 때, 실행되는 인라인 javaScript 기능 인라인 핸들러는 말 그래도 어떤 기능을 동작하는 코드가 HTML Element 내에 직접 할당되는 것을 의미한다.

메서드 핸들러 : 컴포넌트 script 부분에 정의된 메서드(함수)를 이벤트 핸들러에 할당해주는 방식

 

computed : 함수처럼 코드를 작성하지만. return 시키는 데이터를 사용하기 때문에 데이터 취급을 하는 공통적으로 사용ㅇ되는 로직 혹은 복잡한 로직을 미리 처리하여 반복된 로직처리를 방지하는 계산된 형태의 데이터를 만드는 속성. 너무 많은 연산을 스크립트나 템플릿 HTML 안에서 처리하면 코드가 비대해지고 유지보수가 어렵기 때문에 사용한다.

 

Watch : 어떤 데이터를 감시하고 있다가 그 데이터의 값이 변했을 때 그것을 감지하여 그와 관련된 함수, 로직, 연산 등 다양한 기능을 추가적으로 활용할 수 있도록 도와주는 속성

 

Props & Emits: Props는 부모컴포넌트에 선언된 데이터를 자식컴포넌트에서 사용해야 할 경우에 사용되는 문법이다. Emits는 반대

 

v-model : Vue.js에서 양방향 데이터 바인딩을 가능토록 한 강력한 기능을 갖춘 디렉티브

 

인라인 핸들러 실습

<template>
  <div>
    <button v-on:click="count++">인라인 핸들러</button> <!-- 태그 안에 로직 자체가 들어있기 때문에 인라인 핸들러라고 부른다 -->

    <h1>{{ count }}</h1>
  </div>
</template>

<script>
export default {
  data(){
    return {
      count: 0
    }
  },
}

</script>

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

 

메서드 핸들러 실습

<template>
  <div>
    <!-- 태그 안에 로직 자체가 들어있기 때문에 인라인 핸들러라고 부른다 -->
    <!-- <button v-on:click="count++">인라인 핸들러</button>

    <h1>{{ count }}</h1> -->

    <button v-on:click="changeName">메서드 핸들러</button>

    <h1>{{ name }}</h1>
  </div>
</template>

<script>
export default {
  data(){
    return {
      count: 0,
      name: 'vuejs',
    }
  },
  methods: {
    // 로직을 스크립트 부분에 빼서 관리하는 걸 메소드 핸들러라고 한다.
    changeName() {
      this.name = '변경된 텍스트 데이터 입니다.'
    },
  },
}

</script>

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

 

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 테스트 데이터 문구입니다'
    }
  },
  // methods 부분에 선언된 함수와 동일한 로직일 때,
  // 캐싱 기능이 없는 methods는 호출될 때마다 console 값이 출력된다.
  // 반면에, computed는 캐싱 기능이 있기 때문에 methods와 어떤 차이점이 있는지
  // 살펴보는게 포인트다
  computed: {
    computedText() {
      console.log('Computed 기능을 생성했다')

      // computed는 함수모양이지만 데이터이기 때문에 return값이 반드시 있어야 한다.
      return this.text.split('').reverse().join('')
    }
  },
  methods: {
    changeText() {
      console.log('함수호출')
      console.log(this.text)

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

</script>

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

 

함수는 세 번 호출되었는데 computed는 한 번 호출된 모습을 볼 수 있다.

 

watch 실습

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

<script>
export default {
  data(){
    return {
      message: 'watch 실습 오리지널 문구입니다.',
    }
  },
  watch: {
    // 함수가 아니라 message라는 데이터를 지켜보고 있다는 뜻
    // 데이터 뿐만 아니라 computed로 계산된 형태의 데이터도 watch로 감시할 수 있다
    // 보통 게시판에서 한 컬럼을 선택하였을 때, 고유한 id 값이 바뀜을 감지하고
    // 이때, 그 id값에 따른 상세 데이터를 호출할 때, 주로 사용한다
    message() {
      window.alert('message에 담긴 데이터가 변경되었습니다.')
    },
  },
  methods: {
    changeMessage() {
      console.log('함수호출')
      this.message = '변경된 message 데이터 입니다'
    },
  },
}

</script>

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

버튼이 눌리면 메세지 데이터가 변경되고 메세지 데이터를 감지하고 있던 watch로 인해 변경되면 alret가 발생한다.

 

Props & Emits 실습

 

options API 방식

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

<script>
import asd from './components/asd.vue'

export default {
  components: {
    asd,
  },
  data(){
    return {
      title: '부모컴포넌트에서 선언된 데이터 입니다',
      createAt: 2024,
      obj: {
        id: '2024',
        name: '김',
      }
    }
  },
}

</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>
 

composition API 방식

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

<script setup lang="ts"> // 컴포지션에서는 setup반드시 명시
import { reactive, ref } from 'vue';
import asd from './components/asd.vue'

interface Obj {
  id: number
  name: string
}

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

<style lang="scss" scoped>
</style>
<template>
    <div>{{ props.sendProps1 }}</div>
    <div>{{ props.sendProps2 }}</div>
    <div>{{ props.sendProps3.id }}</div>
    <div>{{ props.sendProps3.name }}</div>

</template>
 
<script setup lang="ts">
interface Obj {
  id: number
  name: string
}
 
interface Props{
    sendProps1: String
    sendProps2: Number
    sendProps3: Obj
}
const props = defineProps<Props>()
</script>

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

 

컴포지션 API에서 타입스크립트를 활용하는 방법

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

</template>
 
<script setup lang="ts">
import { toRefs } from 'vue';

interface Obj {
  id: number
  name: string
}

// 1. 컴포지션 API에서 타입스크립트를 활용하는 방법
// 1-1. Props 받은 데이터 형식에 맞게 타입을 지정한다.

// 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>
 

 

컴포지션 API에서 Emit 실습

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

<script setup lang="ts">
import asd from './components/asd.vue'

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

<style lang="scss" scoped>
</style>
<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>
 

 

옵션API에서 Emit 실습

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

<script>
import asd from './components/asd.vue'

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

<style lang="scss" scoped>
</style>
<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>
 

 

v-model 실습

 

<template>
  <div>
    <input type="text" v-model="inputValue1" />
    <input type="text" :value="inputValue2" @input="inputValue2=$event.target.value" />
  </div>
  <div>{{ inputValue1 }}</div>
  <div>{{ inputValue2 }}</div>
</template>

<script>

export default {
  data() {
    return {
      inputValue1 : '',
      inputValue2 : '',
    }
  },
}
</script>

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

영어를 쓸 때는 v-model이나 밑에 똑같이 만든 기능이나 동시에 잘 출력되는데 한글을 입력하면 v-model은 한박자 늦게 출력된다. 물론 api와 통신하여 데이터에 전달시키거나 할 때는 크게 상관없다. 하지만 vue.js에서 한글을 사용할 때는 밑과 같게 기능을 사용하라고 권장하고 있다