
👉 md 에서 npm create vue@latest 이후 나오는것들 다 No하기 -> 새로 생성한 v1에서 code . 하면 vscode로 바로 접속 -> vscode terminal에서 npm install
👉 cmd에서 npm create vite@latest -> 항상하는것처럼 하되 바닐라가 아닌 vue로 진행 -> vscode의 터미널에서 npm install
-> npm install --save bootstrap
-> npm install --save @popperjs/core
📌 Web Page : 웹 브라우저를 통해 사용자에게 보여지는 문서
👉 정적인 콘텐츠 : HTML로 작성된 정적문서로 사용자와의 상호작용 X
👉 짧은 라이프 사이클 : 웹 페이지는 사용자가 요청할 때마다 새로 생성 및 갱신되며, 상태유지 X
👉 웹 페이지는 개인 블로그, 기업 소개페이지등 사용자와의 상호작용이 제한
📌 Web Application : 웹 브라우저를 통해 제공되는 응용프로그램.
👉 특정 업무 수행 : 사용자가 특정 작업을 수행할 수 있도록 설계. (이메일클라이언트, 온라인쇼핑몰)
👉 고유의 메모리 사용 : 웹 어플리케이션은 서버에서 실행되어 서버의 메모리와 자원을 사용하여 상태 유지 및 데이터베이스와 상호작용
👉 라이프사이클 존재 : 웹 어플리케이션은 상태를 유지하고 관리하는 라이프사이클을 갖는다. (세션, 데이터처리, 요청과 응답 사이의 상태관리등)
👉 Gmail, Google Docs(문서작성도구)등 상태를 유지하며 복잡한 데이터 처리를 수행함.
👉 주로 텍스트를 표시할 때 사용, HTML태그를 포함하지 않는 순수한 텍스트
👉 XSS의 위험을 방지할 수 있음. html 태그를 포함하여 출력하게 된다면 html태그가 반영되지 않은 값을 출력하므로.
👉 데이터 바인딩을 통해 텍스트 내용을 동적으로 업데이트.
👉 {}와 마찬가지로 HTML태그가 포함되더라도 HTML로 랜더링 되지 않음
👉 HTML태그가 실제 HTML로 렌더링됨.
👉 XSS공격에 취약할 수 있음
<script setup>
let str = '<h1>demo</h1>'
let str1 = "demo"
</script>
<template>
<div>
<h2 v-text="str"></h2> // <h1>demo</h1>
<h2 v-text="str1"></h2> // demo
<h2>----------</h2>
<h2>{{str}}</h2> // <h1>demo</h1>
<h2>{{ str1 }}</h2> // demo
<h2>----------</h2>
<h2 v-html="str"></h2> //(h2반영된) demo
<h2 v-text="str1"></h2> // demo
</div>
</template>

let str = null
<template v-if="str">
<h2>aaaa</h2>
</template>
<template v-else="str">
<h2>bbb</h2>
</template>
👉 해당 코드는 h2가 적용된 bbb가 출력이 된다.
{{str ? '<h2>aaa</h2>' : '<h2>bbb</h2>'}}
👉 해당코드는 h2가 적용되지 않은 <h2.>bbb</h2.> 값이 출력된다.
<template>
<div>
<div class="a" v-for="(e,i) in [1,2,3,4,5]":key=i>
{{e}}
</div>
</div>
</template>
👉 e는 배열의 각 요소를 나타내는데, 여기서는 [1,2,3,4,5] 배열의 각 요소가 e에 저장됨.
👉 i는 배열의 인덱스를 나타냄
👉 key는 각 항목에 고유한 식별자를 제공, vue가 효율적으로 변경 사항을 추적할 수 있음.
👉 출력 값은 1 2 3 4 5
<template>
<div class="a" v-for="item in arr" :key="item.pno">
{{ item.price }}
</div>
</template>
<script setup>
const arr = [
{pno:1, pname:'P1',price:3000},
{pno:2, pname:'P2',price:4000},
{pno:3, pname:'P3',price:5000},
{pno:4, pname:'P4',price:6000},
]
</script>
<style lang="scss" scoped>
</style>
👉 생성된 배열을 for문으로 출력이 가능하다.
👉 v-if는 dom파일(html tag)을 만들지 않는다
👉 v-show파일을 dom파일을 만들지만 화면에는 보이지 않는다.
<template>
<div class="a" v-for="({pno,pname,price,sale}) in saleProducts" :key="pno" >
<h2>{{ pname }}</h2>
<p>{{ price }}</p>
</div>
</template>
<script setup>
import { computed } from 'vue';
const arr = [
{pno:1, pname:'P1',price:3000, sale: true},
{pno:2, pname:'P2',price:4000, sale: false},
{pno:3, pname:'P3',price:5000, sale: true},
{pno:4, pname:'P4',price:6000, sale: false},
]
const saleProducts = computed( () => arr.filter(p => p.sale == true))
</script>
<style lang="scss" scoped>
</style>
👉 sale이 false인 코드는 출력하지 않고싶을때 해당 코드를 사용한다.
👉 computed는 반응형 데이터 파생 값을 계산할때 사용되는데, 쉽게 말하여 의존하는 데이터가 변경된다면 자동으로 업데이트 된다.
👉 해당 예제에서 arr을 ref로 만들어 반응형인 모델로 만든다음 출력을 반응형으로 하기위해 computed를 사용하면 computed의 효율이 있지만 현재는 반응형으로 만든것이 아니기 때문에 computed를 굳이 사용할 필요는 없어보임
👉 처음에는 기존의 데이터를 저장해뒀다가 해당 값에 변경이 있다면 변경한 값을 출력하고, 변경한 값이 바뀌지 않으면 그대로 출력된다.
<template>
<div class="row g-3" >
<div class="col-md-6 col-lg-4 col-xl-3" v-for="({pno,pname,price,sale}) in arr.filter(p => p.sale == true)" :key="pno" >
<h2>{{ pname }}</h2>
<p>{{ price }}</p>
</div>
</div>
</template>
<script setup>
const arr = [
{pno:1, pname:'P1',price:3000, sale: true},
{pno:2, pname:'P2',price:4000, sale: false},
{pno:3, pname:'P3',price:5000, sale: true},
{pno:4, pname:'P4',price:6000, sale: false},
]
</script>
<style lang="scss" scoped>
</style>
👉 computed를 사용하지 않고 v-for문의 in값 내부에 filter를 사용하여 출력이 가능하다.
👉 해당 코드가 더 쉬움.
👉 여기서 p값은 arr의 각 속성
👉 단일값이나 객체를 감싸는 객체를 반환하는 반응형으로 만들기위해 사용함.
👉 Vue에서는 JS가 중심이되고, HTML은 자동으로 갱신 처리된다. 고로 반응형이라는 개념을 도입하기 때문에 ref / reactive를 사용한다.
<template>
<div>
<div>
<h1>counter1{{ counter.num }}</h1> // 여기서는 value 사용 x
<h1>counter2{{ counter.nums }}</h1>
</div>
<div>
<button @click="plus">plus</button>
<button @click="minus">minus</button>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const counter = ref({ num: 10, nums: [] });
const plus = () => {
counter.value.num++;
counter.value.nums.push('A');
};
const minus = () => {
counter.value.num--;
counter.value.nums.push('B');
};
</script>
<style lang="scss" scoped>
/* 여기에 스타일 작성 */
</style>
👉 @click은 vue의 이벤트 바인딩 디렉티브로 @click="plus"는 버튼이 클릭될때 plus함수를 호출하라는 의미
👉 ref로 감싼 값은 counter 객체로 counter.value를 통해 객체에 접근한다.
👉 ref로 생성된 값은 value라는 속성에 저장되므로 counter.value.num과 같이 value를 넣어줘야함
<template>
<div>
<h1>{{count}}</h1>
<h1>{{message}}</h1>
<button @click="countf">count</button> //count에 대한 이벤트 (버튼누르면 countf 메소드 실행)
<button @click="messagef">message</button> //message에 대한 이벤트
</div>
</template>
<script setup>
import { ref } from 'vue'; //ref import
const count = ref(0) //count를 ref로 감싸고 초기값 0
const message = ref('hi') //message를 ref로 감싸고 초기값 hi
const countf = () => { //countf실행시에 count.value값이 1증가
count.value++;
}
const messagef = () =>{ // messagef실행시에 message.value값이 'update' 로 변경
message.value='update';
}
</script>
<style lang="scss" scoped>
/* 여기에 스타일 작성 */
</style>
👉 ref와 비슷하지만 주로 객체와 배열같은 복잡한 데이터 구조를 다룰때 사용한다.
<template>
<div>
<div>
<h1>counter1{{ counter.num }}</h1>
<h1>counter2{{ counter.nums }}</h1>
</div>
<div>
<button @click="plus">plus</button>
<button @click="minus">minus</button>
</div>
</div>
</template>
<script setup>
import { reactive } from 'vue';
const counter = reactive({ num: 10, nums: [] });
const plus = () => {
counter.num++;
counter.nums.push('A');
};
const minus = () => {
counter.num--;
counter.nums.push('B');
};
</script>
<style lang="scss" scoped>
/* 여기에 스타일 작성 */
</style>
👉 ref와 거의 비슷하지만 value를 사용하지 않는다.