2) vue 공식 문서 보면서 메모 1

vue 공식 문서는 한국어로 번역이 잘 되어 있는 편이다. 어려운 부분은 건너뛰고 순서대로 보면서 추가적으로 메모한 부분을 정리했다. 따로 적어두지 않은 부분도 일단 다 중요한 것 같다.

폴더 세팅

공식문서는 ‘Vue 인스턴스‘부터 보기 시작했다.

간단하게 바로 cdn을 이용해서 실습하기로 한다.

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

뷰를 가져오면 생성자 함수로 (new Vue()) 뷰 객체를 만들 수 있다. 인스턴스가 결과로 나온다.

vscode에서 라이브 서버로 확인할 수 있다.

반응형 데이터는 data에 정의가 되어 있어야 한다.

data에 객체로 바로 값을 쓰면 안되고 무조건 함수로 만들어야 한다. 인스턴스를 복제해서 사용할 때 문제가 생기기 때문이다. 함수로 만들어서 사용하면 실행될 때마다 새롭게 값이 만들어져 메모리에 할당된다.

Vue인스턴스 ~ 리스트 렌더링

lifecycle

뷰 인스턴스의 생애 주기. 라이프사이클에서 생성될 때, 마운트될 때, 데이터 변경 될 때, 파괴될 때 실행되어야 할 로직을 추가해줄 수 있다.

반응형 데이터가 바뀔 때 해당하는 부분은 beforeupdate, updated 이다.

destroy되면, 즉 인스턴스가 파괴되면 반응성을 가질 수 없는 상태가 된다.

virtual DOM

가상의 HTML구조.

데이터가 바뀔 때 버추얼 돔의 역할: 가짜 HTML구조가 만들어지고 진짜 HTML구조와 비교한다. 비교해서 다른 부분만 갱신한다.

템플릿 문법

보간법.

  • HTML속성이면 ⇒ v-bind:style=”myStyle”
  • 컨텐트면 ⇒ {{ myStyle }}

v-once: 한 번만 반응성을 가진다. 메모리 사용 down

v-html: xss취약점이 있지만 내가 만든 건 신뢰할 수 있으니깐 괜찮다. 외부 데이터 가져올 때 (ex. 댓글) 주의해야 한다.

computed

계산된 데이터를 만들어 주는 옵션. 캐싱 기능도 있다. 정의된 데이터를 활용해서 반응성이 있다. 그래서 계산된 데이터도 다시 계산된다. 계산 기능은 메소드로 쓸 수도 있지만 캐싱을 생각하면 computed가 더 적합할 수도.

getter, setter 는 vuex에서 유용하다(심화 기술)

<style>
  .active {
    color: salmon;
  }
</style>
<div id="app">
  <div :class="{ active: msg }">
    
  </div>
</div>

<script>
  // Vue 인스턴스
  const vm = new Vue({
    el: '#app',
    data() {
      return {
        msg: 'Hello Vue?!'
      }
    },
    computed: {
      reversedMsg: {
        // Getter 값을 얻는 용도
        get() {
          return this.msg.split('').reverse().join('')
        },

        // Setter 값을 지정하는 용도
        set(value) {
          this.msg = value
        }
      }
    }
  })
</script>

watch

정의된 데이터를 감시한다. 변경이 있으면 처리해야 할 로직을 작성하면 된다. (쓸 일이 별로 없다고 한다)

<div id="app">
  <div>{{ reverseMsg() }}</div>
  <div>{{ msg.split('').reverse().join('') }}</div>
  <div>{{ reversedMsg }}</div>
</div>

<script>
  // Vue 인스턴스
  const vm = new Vue({
    el: '#app',
    data() {
      return {
        msg: 'Hello Vue?!'
      }
    },
    computed: {
      reversedMsg() {
        return this.msg.split('').reverse().join('')
      }
    },
    watch: {
      msg() {
        console.log('msg 변경됨!!')
      },
      reversedMsg() {
        console.log('reversedMsg changed!!')
      }
    },
    methods: {
      reverseMsg() {
        return this.msg.split('').reverse().join('')
      }
    }
  })
</script>

클래스와 스타일 바인딩

<style>
  .color-red { color: salmon; }
</style>
<div id="app">
  <div v-bind:[attrname]="msg">Hello Vue?!</div>
</div>

<script>
  // Vue 인스턴스
  const vm = new Vue({
    el: '#app',
    data() {
      return {
        msg: 'color-red',
        attrname: 'class'
      }
    }
  })
</script>

조건부 렌더링

v-if, v-else-if, v-else 는 바로 다음 형제 요소로 있어야함. 중간에 뭐가 끼어 있으면 안되고 붙어 있어야 한다.

여러 요소를 한 번에 v-if를 적용할 때 요소를 <template>으로 감싸고 여기에 v-if를 쓴다. 최종 렌더링 결과에는 포함되지 않는다.

  • v-if: 일반적으로 사용하면 된다. lazy..
  • v-show: 자주 바뀌어야 하는 요소에 쓰자. (요소를 처음부터 렌더링하고, display: none으로 보이고 안보이게 한다)

v-show부분 한국어 버전 잘려 있어서 원본은 여기서 보자.

https://vuejs.org/v2/guide/conditional.html#v-show

v-cloak

https://kr.vuejs.org/v2/api/#v-cloak

v-cloak 속성은 잠깐 붙어있다가 화면에 렌더링 되면 사라진다. 뷰가 최적화 되기 전에 잠깐 깜빡임이 있을 수도 있기 때문에 통상 display: none을 추가 한다.

[v-cloak] {
  display: none;
}

리스트 렌더링

v-for. 통상 배열을 사용하지만 객체도 가능하다.

key속성을 같이 사용해야 한다. key는 해당 리스트 내에서 고유한 값이면 된다.(다른 리스트까지 포함해서 고유값을 비교하지는 않음) 화면에 나타나는 것이랑 관련있지는 않지만 vue를 위해 써 주어야 한다.

<style>
  ul {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 70px;
  }
  ul li {
    border: 1px solid salmon;
    display: flex;
    justify-content: center;
    align-items: center;
  }
</style>
<div id="app">
  <h1></h1>
  <ul>
    <li v-for="item in news.list" :key="item.name">
      <img :src="item.logo" :alt="item.name">
      <div></div>
    </li>
  </ul>
</div>

<script>
  // Vue 인스턴스
  const vm = new Vue({
    el: '#app',
    data() {
      return {
        news: {
          title: '전체 언론사',
          list: [
            { name: '한겨레', logo: 'URL' },
            { name: '세계일보', logo: 'URL' },
            { name: 'SBS', logo: 'URL' },
            { name: '동아일보', logo: 'URL' },
            { name: '일간스포츠', logo: 'URL' },
            { name: '스포츠조선', logo: 'URL' },
            { name: 'KBS', logo: 'URL' },
          ]
        }
      }
    }
  })
</script>

배열 변경 감지

변이 메소드를 사용하면 변경이 감지 된다. 인덱스로 배열에 직접 설정하면 감지 안된다(반응성이 없다)

this.$set으로 하면 변경 감지 된다.

<div id="app">
  <button @click="pushFruit">Click me!</button>
  <ul>
    <li v-for="fruit in fruits" :key="fruit.id">
      
    </li>
  </ul>
</div>

<script>
  // Vue 인스턴스
  const vm = new Vue({
    el: '#app',
    data() {
      return {
        fruits: [
          { id: 'f1', name: 'Apple' }, 
          { id: 'f2', name: 'Banana' }, 
          { id: 'f3', name: 'Cherry' }, 
          { id: 'f4', name: 'Mango' }
        ]
      }
    },
    methods: {
      pushFruit() {
        // this.fruits.push({ id: 'f5', name: 'Orange' })
        // this.fruits[4] = { id: 'f5', name: 'Orange' }
        this.$set(this.fruits, 4, { id: 'f5', name: 'Orange' })
        console.log(this.fruits)
      }
    }
  })
</script>

객체 변경 감지

this.$set = Vue.set

<div id="app">
  <button @click="addProp">Click me!</button>
  <ul>
    <li v-for="(value, key, index) in user" :key="key">
      {{ index + 1 }} - {{ key }}: {{ value }}
    </li>
  </ul>
</div>

<script>
  // Vue 인스턴스
  const vm = new Vue({
    el: '#app',
    data() {
      return {
        user: {
          name: 'JOHN',
          age: 85,
          email: 'the@gmail.com',
          // isValid: undefined // 선언해둔다.
        }
      }
    },
    methods: {
      addProp() { 
        this.$set(this.user, 'isValid', true) // 이 속성을 반응성으로 추가할 것이다 - 데이터, 속성명, 값
        // this.user.isValid = true
        console.log(this.user)
      }
    }
  })
</script>

Leave a comment