728x90
728x90
 

 

Props

하나의 컴포넌트의 스타일을 가져와 루트 컴포넌트에 연결할 때 props에서 type과 default를 설정해둔다.

 

RootComponents.vue

<template>
  <MyBtn color="yellow"/>
  <MyBtn />
  <MyBtn />
</tempalte>

<script>
 import MyBtn from '~/components/MyBtn'
 
  export default {
   components: {
     MyBtn
   }
  }
</script>

 

MyBtn.vue

<template>
  <div
    :style="{ backgroundColor: color }"
    class="btn">
    button
  </div>
</template>

<script>
export default {
  props: {
    color: {
      type: String,
      default: 'gray'
    }  
  }
}
</script>

 

 

Provide Inject

Props의 단점은 중간매개체를 꼭 거쳐야 상속이 되기 때문에 5단계일 경우 모든 컴포넌트에 Props를 설정해야 하는 Props지옥이 생성된다. 이때 사용할 수 있는 것이 Provide인데 중간매개체를 거치지 않을 수 있지만 반응성을 유지하지는 않기 때문에 vue의 computed옵션을 가져와야 한다. 이 기능은 라이브러리를 사용해 개선할 수 있으니 개념 정도만 알아두자

 

App.vue > Parent.vue > Child.vue 에서 Provide, Inject할 때

//App.vue
<Parent :msg="message" />
// Parent.vue
<Child :msg="msg" />
// Child.vue
<div>inject:['msg']</div>
// App.vue
return {
  message: 'Hello!'
},
provide() {
  return {
    msg:this.message
  }
}
// Parent.vue
props: {
  msg: {
    type: String,
    defalut: ''
  }
}
// Child.vue
props: {
  msg: {
    type: String,
    defalut: ''
  }
}

 

Computed

반응성을 추가할 때

컴포넌트 기본 형태(빈 태그)로 사용하며 props는 사용할 필요가 없다.

// App.vue
import {computed} from 'vue'
// export default
provide() {
  return {
    msg: computed(() => this.message)
  }
}

// child.vue
<div>{{ msg.value }}</div>

 

 

Slot

하위 엘리먼트의 값을 포함

- 텍스트 삽입

<template>
  <div class="btn">
    <slot></slot>
  </div>
</template>
<MyBtn>Banana</MyBtn>

- style 적용

<MyBtn
  :color="color">
  <span style="color: red;">Banana</span>
</MyBtn>

 

Fallback Contents

slot내부에 대체 내용을 미리 정할 수 있다. 최상위 컴포넌트에서 내용을 수정 시 이는 대체된다.

Named Slots 

이름을 갖는 슬롯. slot 이름을 icon과 text로 지정해줬을 때, 최상위 컴포넌트에서 작성 순서와 상관없이 개별 컴포넌트에서 순서를 보장해icon->text 순으로 출력한다.

v-slot의 약어

<template #icon>(B)</template>

App.vue

<MyBtn>
  <template v-slot:text>Banana</template>
  <template v-slot:icon>(B)</template>
</MyBtn>

 

MyBtn.vue

<div class="btn">
  <slot name="icon"></slot>
  <slot name="text"></slot>
</div>

 

 

속성 상속

Attribute Inheritance

  • 루트 컴포넌트에 class를 추가하면 개별 컴포넌트에도 같은 class가 추가됨
  • template의 최상위요소가 2개 이상일 때는 속성이 상속되지 않음

 

속성을 상속하지 않을 때

export default {
  inheritAttrs: false
}

 

원하는 요소(h1)에 상속할 때

<h1 :class="$attrs.class"
  :style="$attrs.style">
</h1>

 

$attrs

원하는 요소(h1)에 attrs객체 데이터를 모두 상속할 때

<h1 v-bind="$attrs"></h1>

 

 

Emit

이벤트를 컴포넌트에 직접적으로 연결하는 방법

emit을 통해 부모 요소에 연결된 이벤트를 상속받아 실행하게 된다.

<h1 @click="$emit()">click</h1>
export default {
  emits: [
    'click' 
  ]
}
728x90
728x90
 

단방향 데이터 바인딩

이때는 폼에서 Hello World의 값을 달리 적어도 실제 msg에 할당된 데이터는 갱신되지 않는다. 

<input
  type="text"
  :value="msg" />
<h1>{{ msg }}</h1>
return {
 msg: 'Hello World'
}

 

양방향 데이터 바인딩

 

input태그의 value로 바로 연결되는 handler를 사용하기 때문에 양방향 데이터 바인딩이 완성된다.

@input="handler"
methods: {
  handler(e) {
    this.masg = e.target.value
  }
}

 

vue.js속성으로 표현

:value="msg"
@input="msg = $e.target.value"

 

v-model

더 간략하게 v-model을 사용해보자.

<input
  type="text"
  v-model="msg" />

 

주의사항

한글은 완성된 글자로 나타나야 반응하므로 v-model를 사용하면 한 박자 늦게 동작하는 것처럼 보인다. 한글은 단방향 연결과 input디렉티브 형태로 사용하는 것이 적합하다.

<input
  type="text"
  :value="msg"
  @input="msg = $e.target.value" />
<h1>{{ msg }}</h1>

 

v-model 수식어

change이벤트와 lazy

값의 변경이 모두 완료되면 동작하는 수식어

(폼 입력창에서 Enter나 Tab, 폼 바깥을 클릭했을 때 비로소 값이 갱신된다.)

:value="msg"
@change="msg = $e.target.value"
<input
  type="text"
  v-model.lazy="msg" />

 

number

데이터의 타입을 숫자로 변경

<input
  type="text"
  v-model.number="msg" />

 

trim

빈 공간을 제거

<input
  type="text"
  v-model.trim="msg" />
728x90
728x90
 

 

🌲 click 이벤트

인수가 없을 때 아래와 같이 사용되지만 이는 인수가 생략된 형태로 vue에서 지원하는 문법이다. 

<button @click="handler">
  click!!
</button>

인수를 직접 넣으면 작동한다.

<button @click="handler('Hello')">
	click!
</button>

 

🌲메소드 이벤트 핸들링

로직을 @click에 바로 넣는 것이 아니라 메소드를 만들어 핸들링하는 것이 많은 양의 데이터를 처리하기에 용이하다.

 

 

🌳inline method handler

handler에 들어가는 인수(여기서는 event)는 클릭 이벤트가 발생했을 때 정보를 갖는 객체(mouse event)로 이곳에서 필요한 속성을 가져와 사용할 수 있다. 이 인수는 매개변수이기 때문에 다른 이름으로 변경이 가능하다.

<button @click="handler">
  click!!
</button>
methods: {
  handler(event) {
    console.log(event)
    console.log(event.target) // <button>click!!</button>
    console.log(event.target.textContent) // click!!
  }
}

 

🌳인라인 + 이벤트

인라인 이벤트 핸들러(인수사용)에 이벤트 핸들러를 함께 사용하는 방법

$를 붙인다.

<button @click="handler('hello', $event)">
  click!!
</button>

 

🌳Multiple event handlers

다중 메소드 핸들러를 사용할 때는 인수가 없어도 호출하겠다는 의미로 소괄호()를 명시해야 한다.

<button @click="handlerA(), handlerB()">
  click!!
</button>
methods: {
  handlerA(){로직},
  handlerB(){로직}
}

 

 

🌲Event Modifiers

이벤트 수식어


<a 
  href="https://www.naver.com"
  target="_blank"
  @click="handler">
Naver</a>
methods: {
  handler() {
    console.log('N')
  }
}

 

🌳prevent

 

HTML의 기본 동작을 방지하고 method만 실행하는 기능이다.

(Naver를 클릭했을 때 새창은 열리지 않으나 콘솔창에 N은 출력된다.)

 

mouseevent에서 사용할 수 있는 메소드

handler(e) {
  e.preventDefault()
}

vuejs 문법

@click.prevent="handler"

 

🌳once

(HTML은 동작하나) method를 한 번만 실행

(Naver는 클릭할 때마다 새 창이 나타나고 콘솔창에 N은 한 번만 출력된다.)

 

이벤트 수식어 체이닝

체이닝으로 사용 가능하며 html도 method도 한 번씩만 실행되는 결과를 출력한다.

@click.prevent.once="handler"

 

 

🌲이벤트 버블링, 캡쳐링

<div class="parent" @click="handlerA">
  <div class="child" @click="handlerB">
  </div>
</div>

 

🌳버블링

child를 포함하고 있는 상위의 영역에 영향을 주는 현상

=> child를 클릭했을 때, child->parent 순으로 클릭된다.

 

버블링을 방지하기 위하여  Vuejs에서는 stop이라는 수식어를 사용하며 이는 stopPropagation메소드와 동일한 기능을 한다.

handlerB(e) {
  e.stopPropagation()
}
@click.stop="handlerB"

=> child를 클릭해도 parent는 동작하지 않는다

 

🌳캡쳐링

버블링과 반대의 기능을 의도할 때 capture수식어를 이용한다. 상위 요소가 먼저 동작하고 하위 요소로 내려온다.

=> child를 클릭했을 때, parent->child 순으로 클릭된다.

@click.capture="handlerA"

캡쳐링 시 부모 요소에만 동작하려면?

@click.capture.stop="handlerA"

 

🌳self

target과 currenttarget이 동일할 때에만 동작되는 이벤트 수식어이다.

기본적으로 parent에만 클릭 이벤트가 있을 때, child를 선택하면 parent를 선택한 것과 동일하게 기능하는데 이를 방지할 때 사용한다.

@click.self="handlerA"

 

🌳passive

wheel이벤트가 동작할 때, 실제 화면에서 스크롤되는 것과 로직 처리를 독립시켜 화면에 부하가 되는 것을 막는다.

@wheel.passive="handler"

 

 

키 수식어

keydown

<input
  type="text"
  @keydown="handler" />
methods: {
  handler(e) {
    if(e.key === 'Enter'){
      console.log('Enter')
    }
  }
}

(마우스이벤트의 key속성이 Enter일 때 콘솔에 Enter를 출력하라.)

클릭이벤트가 갖고 있는 객체데이터에는 key속성이 있는데 input입력창에서 키보드를 누를 때마다 key속성값은 변화한다. 키보드에서 Enter키를 누르게 되면 key속성 역시 Enter로 변하는데 이것을 이용해 로직을 실행시키고자 하는 if문이다.

 

위 코드를 vuejs속성으로 간단히 표현할 수 있다. 이때 Enter는 케밥케이스(대쉬)로 명시해야 한다.

<input
  type="text"
  @keydown.enter="handler" />

keydown은 체이닝 형식으로도 사용가능하다. ctrl+a조합을 만들 때는 다음과 같이 사용한다.

<input
  type="text"
  @keydown.ctrl.a="handler" />

 

728x90
728x90
 

Vue.js instance & lifecycle hook

 

 

어플리케이션 & 컴포넌트 인스턴스 | Vue.js

어플리케이션 & 컴포넌트 인스턴스 어플리케이션 인스턴스 생성하기 모든 Vue 어플리케이션은 createApp 함수를 사용하여 새로운 어플리케이션 인스턴스를 생성하여 시작합니다 : const app = Vue.create

v3.ko.vuejs.org

라이프사이클 훅

 

🌳인스턴스 

 

🌳메소드 체이닝

Vue.createApp({ count }).mount(#app')
const app = Vue.createapp({})

createApp에 전달된 옵션은 루트 컴포넌트를 구성하는데 사용된다. 

 

🌳최상위 컴포넌트

Root component : 프로젝트를 시작할 때(어플리케이션을 mount할 때) 랜더링이 되는 시작점

 

🌳라이프사이클 훅

Lifecycle hook
beforeCreate 컴포넌트가 생성되기 직전
created 컴포넌트가 생성된 후
beforeMount HTML 연결되기 전
mounted HTML 연결된 후
<template>
  <h1>{{ count }}</h1>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  beforeCreate() {
    console.log('beforeCreate', this.count) //undefined
  },
  created() {
    console.log('created', this.count) // 0
  },
  beforeMount() {
    console.log('beforeMount', document.querySelector('h1')) // null
  },
  mounted() {
    console.log('mounted', document.querySelector('h1')) // <h1>0</h1>
  }
}
</script>

 

 

refs

특정 요소 참조 기능

 

h1의 id hello을 DOM에서 선택하려면 이와 같은 과정을 거쳐야 한다.

mounted() {
  const h1El = document.querySelector('#hello')
}

이를 간소화시켜주는 것이 ref 키워드다. id나 class등 구체적인 선택자가 아니어도 ref만 달아놓으면 언제든지 $refs로 mounted할 수 있다. 특징은 html이 연결된 직후에만 사용할 수 있기 때문에 created 라이프 사이클에서는 당연히 사용할 수 없다.

<template>
  <h1 ref="hello">
</tempalte>
<script>
export default {
  mounted() {
    this.$refs.hello
  }
}
</script>

 

최상위요소 연결

정확하게 refs를 설정하지 않으면 모든 최상위요소를 특정짓게 된다.

 

App.vue

<template>
  <Hello ref="hello" />
</template>
<script>
export default {
  mounted() {
    this.$refs.hello.$refs.good
  }
}
</script>

Hello.vue

<template>
  <h1>Hello~</h1>
  <h1 ref="good">Good</h1>
</template>
728x90
728x90

 

🌲V-for

🌳변수 추가

반복처리할 때 새로운 변수(두 번째 인자)를 추가하는 방법

<template>
  <ul>
    <li 
      v-for="(Fruit, index) in Fruits"
      :key="Fruit">
    {{ Fruit }} - {{ index }}
    </li>
  </ul>
</template>
<script>
export default {
  data () {
    return {
      Fruits: [ 'Apple', 'Banana', 'Cherry' ]
    }
  }
}
</script>
Apple - 0
Banana - 1
cherry - 2

 

🌳고유값 생성

무작위의 고유값을 출력하는 패키지

$ npm i -D shortid
import shortid from 'shortid'

 

🌵코드 비교 A-B

<template>
    <ul>
      <li 
        v-for="Fruit in newFruits"
        :key="Fruit.id">
      {{ Fruit.name }} - {{ Fruit.id }}
      </li>
    </ul>
  </template>

  <script>
  export default {
    data () {
      return {
        Fruits: [ 'Apple', 'Banana', 'Cherry' ]
      }
    },
    computed: {
      newFruits() {
        return this.fruits.map((fruit, index) => {
          return {
            id: index,
            name: fruit
          }
        }
      }
    }
  }
  </script>
<template>
    <ul>
      <li 
        v-for="{ id, name } in newFruits"
        :key="id">
      {{ name }} - {{ id }}
      </li>
    </ul>
  </template>

  <script>
  import shortid from 'shortid'

  export default {
    data () {
      return {
        Fruits: [ 'Apple', 'Banana', 'Cherry' ]
      }
    },
    computed: {
      newFruits() {
        return this.fruits.map(fruit => ({
          id: shortid.generate(),
          name: fruit
        })
      }
    }
  }
  </script>

객체데이터를 갖는다면 객체구조분해 문법을 사용하여 바로 속성값을 사용할 수 있다.

 

 

 

🌲Array Change Detection

배열 변경 감지


🌳변이 메소드

Mutation Methods


배열 변경을 감지하여 바로 적용되는 반응성을 갖는다.

push, pop, shift, unshift, splice, sort, reverse등의 메소드가 있다.

 

(예시) Fruits라는 배열에 마지막 데이터로 Orange를 추가

methods: {
  handler(){
    this.Fruits.push('Orange')
  {
}

이처럼 원본의 배열에 변형이 일어난다

 

🌳비변이 메소드


변이 메소드는 호출된 원래 배열을 변경하는 반면 filter, concat, slice는 원본은 변형하지 않고 새로운 배열로 바꿔 화면을 갱신한다.

 

728x90
+ Recent posts
728x90