2022-07-23

조지성·2022년 7월 23일
0

TIL

목록 보기
61/78
post-thumbnail

OptionsAPI vs Composition API 비교

OptionsAPI

  • data ,methods ,mounted와 같은 옵션을 사용
<template>
	<div>
		<button v-on:click="increment">Counter: {{ counter }}</button>
	</div>
</template>

<script>
export default {
	data() {
		return {
			counter: 0,
		};
	},
	methods: {
		increment() {
			this.counter++;
		},
	},
	mounted() {
		console.log('컴포넌트가 마운트 되었습니다!');
	},
};
</script>

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

Composition API

  • 반응형 코드를 작성하는 단일 setup 함수가 있다.
  • Composition API는 옵션(data, methods, ...)을 선언하는 대신 가져온 함수(ref, onMounted, ...)를 사용하여 Vue 컴포넌트를 작성할 수 있는 API 세트

장점

  • 코드 조각을 함께 그룹화
  • 코드를 매우 쉽게 재사용 할 수 있다.
<template>
	<div>
		<button v-on:click="increment">Counter: {{ counter }}</button>
	</div>
</template>

<script>
import { onMounted, ref } from 'vue';
export default {
	setup() {
		const counter = ref(0);
		const increment = () => counter.value++;
		onMounted(() => {
			console.log('컴포넌트가 마운트 되었습니다!');
		});
		return {
			counter,
			increment,
		};
	},
};
</script>

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

참조

Composition API FAQ | Vue.js

Composition API

Composition API는 옵션(data, methos, ...)을 선언하는 대신 가져온 함수(ref, onMounted, ...)를 사용하여 Vue 컴포넌트를 작성할 수 있는 API 세트를 말합니다.

  • 반응형 API (Reactivity API)

예를 들어 ref(), reactive()와 같은 API를 사용하여 reactive state(반응 상태), computed state(계산된 상태), watchers(감시자)와 같은 것들을 만들 수 있습니다.

예를 들어 onMounted(), onUnmounted()와 같은 API를 사용하여 프로그래밍 방식으로 컴포넌트 라이프사이클에 접근할 수 있습니다.

쉽게 말해서 라이프사이클 특정 시점에 이러한 함수로 코드를 삽입할 수 있습니다.

  • 종속성 주입 (Dependency Injection)

예를 들어 provide()inject()는 Reactivity API를 사용하는 동안 Vue의 의존성 주입 시스템을 활용할 수 있게 해줍니다

<template>
  <div>
    <h2>반응형 메세지</h2>
    <p>{{ reactiveMessage }}</p>
    <button v-on:click="addReactiveMessage">Add Message</button>
    <h2>일반 메시지</h2>
    <p>{{ normalMessage }}</p>
    <button v-on:click="addNormalMessage">Add Message</button>
  </div>
</template>

<script>
import { isRef, onBeforeMount, onMounted, ref } from 'vue'

export default {
  setup () {
    console.log('Setup');
    const reactiveMessage = ref('Hello Reactive Message');
    const addReactiveMessage = () => {
      reactiveMessage.value += '!';
    }

    //console.log(isRef(reactiveMessage)); //반응형 데이터인지 true

    let normalMessage = "Hello Normal Message";
    const addNormalMessage = () =>{
      normalMessage.value += '!';
    }
    //console.log(isRef(normalMessage)); //반응형 데이터인지 false
    
    onMounted(()=>{
      console.log("onMounted");
    })

    onBeforeMount(()=>{
      console.log("onBeforeMounted");
    })
    
    return {
      reactiveMessage,
      normalMessage,
      addReactiveMessage,
      addNormalMessage
    }
  }
}
</script>

<style lang="scss" scoped>

</style>

Setup

  • setup() 함수는 Composition API 사용을 위한 진입점
  • 컴포넌트 인스턴스가 생성되기 전에 실행

    notion image

기본 사용

<template>
  <div>
    {{ counter }}
  </div>
  <p>
    {{message}}
  </p>
  <button v-on:click="increment">Click</button>
</template>

<script>
import { ref } from 'vue'

export default {
  setup () {
    const counter = ref(0);
    const message = ref('Hello vue3');
    const increment = () =>{
      counter.value++;
    }
    return {
      counter,
      message,
      increment
    }
  }
}
</script>

<style lang="scss" scoped>

</style>

Setup의 매개변수

  • 첫 번째 매개변수 props

    • 반응형 객체
  • 두 번째 매개변수 context

    • setup 함수 내에서 유용하게 사용할 수 있는 속성을 가진 컨텍스트 객체

템플릿 문법

<template>
  <div>
    <!--
      텍스트 보간법으로 데이터 바인딩
    -->
    <h2>텍스트 보간법</h2>
    <p>{{message}}</p>
    <!-- v-once : 데이터가 갱신되어도 반응되지 않도록 -->
    <p v-once>{{message}}</p>
    <button v-on:click="message = message + '!' ">Click</button>
    <br/>
    <!-- v-html -->
    <h2>v-html</h2>
    <p>{{rawHtml}}</p>
    <!-- 실제 html 출력 -->
    <p v-html="rawHtml"></p>
    <br/>

    <h2>속성 바인딩</h2>
    <!-- v-bind는 :로 단축할 수 있음 -->
    <div v-bind:title="dynamicTitle">마우스 올려</div>
    <input type="text" value="홍길동" :disabled="isInputDisabled">
    <!-- 다중 속성 바인딩 -->
    <input v-bind="attrs">

    <!-- vue 에서는 모든 데이터 바인딩 내에서 js 표현식 가능 -->
    <h2>자바스크립트</h2>
    {{ message.split('').reverse().join('')}}
  </div>
</template>

<script>
import { ref } from 'vue'

export default {
  setup () {
    const message = ref('안녕하세요');
    const rawHtml = ref('<strong>안녕하세요</strong>');
    const dynamicTitle = ref("안녕하세요!!!@@");
    const isInputDisabled = ref(true);
    const attrs = ref({
      type : "password",
      value : "12345",
      disabled : false,
    })

    return {
      message,
      rawHtml,
      dynamicTitle,
      isInputDisabled,
      attrs,
    }
  }
}
</script>

<style lang="scss" scoped>

</style>

반응형 기초

Reactive

  • 자바스크립트 객체에서 반응형 상태를 생성하기 위해서는 reactive() 함수를 사용
  • 반환된 상태는 반응형 객체
<template>
  <div>
    <button v-on:click="increment">click {{state.count}}</button>
    <button v-on:click="increment">deepclick {{state.deep.count}}</button>
  </div>
</template>

<script>
import { reactive } from 'vue'

export default {
  setup () {
    const state = reactive({
      count : 0,
      deep : {
        count:0
      }
    });
    
    const increment = ()=>{
      state.count++;
      state.deep.count++;
    }

    return {
      state,
      increment
    }
  }
}
</script>

<style lang="scss" scoped>

</style>

ref

  • reactive()는 객체타입에만 동작 따라서 기본타입 (number,string boolean)을 반응형으로 만들기 위해서는 ref()사용
  • ref()메서는 mutable 객체를 반환 이 객체안에는 value라는 하나의 속성만 포함
  • 템플릿에서 사용할 때는 .value 는 필요없음
  • ref가 반응형 객체의 속성으로 접근할 때, 자동적으로 내부 값으로 벗겨내서, 일반적인 속성과 마찬가지로 동작
  • 반응형 객체와 달리 ref가 반응형 배열 또는 Map과 같은 기본 컬렉션 타입의 요소로 접근될 때 수행되는 래핑 해제가 없다
<template>
  <div>
    <p>{{message.value}}</p>
    <!-- value 안써줘도됨 -->
    <p>{{refMessage}}</p>
    <button v-on:click="addMessage">add click</button>
  </div>
</template>

<script>
import { reactive, ref } from 'vue'

export default {
  setup () {
    // 반응형으로 동작하지 않는다.
    // 객체나 배열과 같이 레퍼런스 객체여야함
    // => 해결 ref함수

    //let message = reactive('Hello Vue');
    //    console.log(message);
   // console.log(typeof message); //string

    let message = reactive({
      value : 'Hello Vue',
    });

    let refMessage = ref('hello vue3');
    const addMessage = () =>{
      message.value += '!';
      refMessage.value += '!';
    }
    return {
      message,
      addMessage,
      refMessage
    }
  }
}
</script>

<style lang="scss" scoped>

</style>
<template>
  <div>

  </div>
</template>

<script>
import { reactive, ref} from 'vue';

export default {
  setup () {
    // ref를 객체에서 사용
    let count = ref(0);
    const state = reactive({
      count
    });
    count.value++;
   count.value++;
    //언랩핑
  // console.log(state.count);

  //ref를 array에서사용
    //언랩핑 되지않
  const message = ref('Hello');
  const arr = reactive([message]);
  console.log(arr[0].value);
    return {}
  }
}
</script>

<style lang="scss" scoped>

</style>

반응형 상태 구조 분해하기

  • toRefs, toRef를 사용하면 반응형 객체의 속성과 동기화 됩니다. 그래서 원본 속성을 변경하면 ref 객체가 업데이트되고 그 반대의 경우도 마찬가지
<template>
  <div>
    <p>author : {{author}}</p>
    <p>title : {{title}}</p>
  </div>
</template>

<script>
import { reactive, toRef, toRefs } from 'vue'

export default {
  setup () {
    const book = reactive({
      author: 'Vue Team',
      year: '2020',
      title: 'Vue 3 Guide',
      description: '당신은 이 책을 지금 바로 읽습니다 ;)',
      price: '무료'
    });

    //구조 분해 할당은 반응성을 읽어버리게됨
    // => toRefs
    //const {author,title} = book;
    //console.log(typeof author);

    //반응성을 잃지 않고 가져오기
    //toRefs
    // const {author,title} = toRefs(book)
    // console.log(typeof author);

    //toRef
    const author = toRef(book,'author');
    const title = toRef(book,'title');

    return {author,title,book}
  }
}
</script>

<style lang="scss" scoped>

</style>

readonly

  • 때때로 반응형 객체(ref나 reactive)의 변화를 추적하기 원하지만, 또한 특정 부분에서는 변화를 막기 위해서 사용
<template>
  <div>

  </div>
</template>

<script>
import { reactive, readonly } from 'vue'

export default {
  setup () {
    const original = reactive({
      count : 0,
    });
    const copy = readonly(original);
    
    original.count++;
    copy.count++;
    console.log(original.count);
     console.log(copy.count);

    return {}
  }
}
</script>

<style lang="scss" scoped>

</style>
profile
초보 개발자의 성장기💻

0개의 댓글