단일 파일 컴포넌트 기반의 프레임워크다.
웹의 view를 구성하는 요소인 HTML, CSS, JavaScript 코드를 .vue 확장자를 가진 하나의 파일에 모두 정의하는 방식으로 적당한 규모의 프로젝트에서 관리의 생산성을 높이고, 협업이 쉬운 것으로 알려져 있다.
뷰 인스턴스(Instance)는 뷰로 화면을 개발하기 위해 필수적으로 생성해야하는 기본 단위이며 new Vue()를 사용하여 뷰 객체를 생성한다.
React에 비해 가볍고 빠르게 개발이 필요한 경우 선호
컴포넌트 기반의 웹 프로그래밍 가능
선언적 렌더링 (HTML 확장), JS상태 변경을 virtual Dom으로 효율적 관리가 가능
Vue로 결과 출력:
<div id="app">
{{message1}} <br>
{{message2}} <br>
{{message3}} <br>7
</div>
<script>
let aa = new Vue({
el:"#app",
data:{
message1:"Hello world!",
message2:"안녕" + "반가워",
message3:Math.random() * 9
}
});
console.log(aa);
</script>
기본적으로 위의 코드처럼 new Vue
를 통해 인스턴스를 생성하고 안에 el, data등 옵션을 넣어 인스턴스를 생성하고 화면을 컨트롤 할 수 있다.
<script>
beforeCreate:function(){ //초기화 담당
console.log("beforeCreate")
},
created:function(){ //반응성
console.log("created")
},
mounted:function(){ //속성설정
console.log("mounted")
},
beforeUpdate:function(){
console.log("beforeUpdate")
},
updated:function(){
console.log("updated")
}
</script>
기본
Vue.component("태그명",옵션)
컴포넌트를 구성하여 사용자 정의 태그를 사용한다.
<div id="appBasic">
<hello></hello>
</div>
<script>
Vue.component("hello",{
template:'<h1>{{title}}</h1>', //template: 화면에 표시할 마크업요소를 정의
data:function(){
return{
title:"컴포넌트 txt"
}
}
});
new Vue({
el:"#appBasic"
})
</script>
컴포넌트는 꼭 해당 Vue객체 위에서 만들어야한다.
컴포넌트 - 이벤트관련
<div id="appBasic2">
<world></world>
</div>
<script>
Vue.component("world",{
template:'<h2>{{title}} <button @click="changeTitle">타이틀 변경</button></h2> ',
methods:{
changeTitle:function(){this.title = "변경된 타이틀"}
},
data:function(){
return{
title:"컴포넌트 txt2"
}
}
});
new Vue({
el:"#appBasic2"
})
</script>
버튼 클릭시 텍스트 변경처리.
마크업에서 click이벤트로 만든 메소드에 대한 구현은 methods
에서 구현했다.
Vue.compoent()
로 등록한다.
플러그인이나 라이브러리 형태로 전역으로 사용해야 하는 컴포넌트만 이렇게 작성한다.
여러 인스턴스에서 공통으로 사용 가능하다.
Vue.component('컴포넌트 이름 ',{
컴포넌트 내용
})
compoents
로 등록한다.
복수형
보통은 컴포넌트를 여러개를 등록하기 때문에 components
로 작성한다.
지역 컴포넌트는 하단에 어떤 것이 등록 되는지 알 수 있다.
특정 인스턴스 내부에서만 사용 가능하다.
new Vue({
components:{ // 지역컴포넌트
'컴포넌트 이름': 컴포넌트 내용
}
})
예제
<div id="app">
<div>컴포넌트 등록1</div>
<global-component></global-component><!-- 전역 컴포넌트 표시 -->
<local-component></local-component><!-- 지역 컴포넌트 표시 -->
</div>
<div id="app2">
<div>컴포넌트 등록2</div>
<global-component></global-component>
<local-component></local-component>
</div>
<div id="app3">
<div>컴포넌트 등록3</div>
<global-component></global-component>
<local-component></local-component>
</div>
<script>
//global-component는 여러 인스턴스에서 공통으로 사용 가능
// 전역 컴포넌트 등록 - 강결합
Vue.component("global-component", {
template: "<b>전역 컴포넌트 등록!</b>",
});
new Vue({
el: "#app",
});
// 지역 컴포넌트 등록 - 약결합
let cmp = {
template: "<p>지역 컴포넌트 등록~~~~</p>",
};
new Vue({
el: "#app",
components: {
"local-component": cmp,
},
});
new Vue({
el: "#app2",
});
new Vue({
el: "#app3",
});
</script>
전역으로 등록한 컴포넌트는 다른 Vue객체에서도 적용된것을 확인 할 수 있다.
<body>
<hr>
<div id ="app">
<a href = "{{link}}">링크(에러발생함.)</a>
<a v-bind:href = "link">링크1</a>
<a :href = "link">링크2</a><!-- v- bind생략가능. -->
<h2 v-text="say"></h2>
<h2 v-once>data 속성 1 : {{say}}</h2>
<h3>함수 호출 결과: {{sayFunc()}}</h3>
</div>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
link:'http://daum.net',
say: "안녕하세요",
aLinkToNaver: "<a href='https://naver.com'>가자 네이버로</a>",
name: 'tom',
},
methods:{
sayFunc:function(){
this.say = "반가워요"
return this.say
}
}
})
</script>
v-once
디렉티브는 HTML코드로 출력이 된 이후에 어떤 후처리가 있더라도 처음에 출력한 값을 유지시킬 때 사용된다.v-text / v-html 차이점
<span v-text="aLinkToNaver"></span>
<span v-html="aLinkToNaver"></span>
Directive text가 온전한 html 구문일때 사용할 수 있다.
양방향 데이터 binding (v-model)
<input type="text" v-model:value="name" >{{name}}
v-model:value
에 의해 Vue객체의 {{name}}
이 실시간으로 변화한다.v-model:value이 없다면 단방향 처리로 {{name}} 이 변경되지않는다.
하지만 이 단방향 input태그를 핸들러와 메소드로 v-model
처럼 똑같이 직접 구현할 수도 있다.
단방향 input2: <input type="text" :value='name' @input="changeName">{{name}}
<script>
methods:{
changeName(e){
this.name = e.target.value
}
}
</script>
a={{a}} b={{b}} <br>
a 값 입력 : <input type="text" v-model="a">
<script>
computed:{ //계산된 프로퍼티 : 함수처럼 작동
b:function(){
return parseFloat(this.a) + 1 //계산
}
}
</script>
계산된 프로퍼티 computed
로 인해 b는 단순한 변수가 아닌 함수가 된다.
js에서 +는 문자열로써 더하기 때문에 입력값에 함수 리턴값에 parseFloat를 적용하여 실수로써 계산했다.
만약 리턴에 parseFloat를 적용하지 않는다면 대체 방법으로 <input>
에서
v-model.number
로 적용시킬 수 있다.
<script>
a 값 입력 (number적용) : <input type="text" v-model.number="a">
computed:{
b:function(){
return this.a + 1 //문자열더하기
}
}
</script>
if
<h2 v-if="a > 5">a가 5보다 크다.</h2>
<h2 v-if="a == 5">a는 5다.</h2>
<h2 v-else>a는 5를 제외한 수이다.</h2> <br>
Vue객체의 ar값을 조건 판단 후 해당 태그내용을 출력하거나 하지않는다.
for
반복문 for
<ul>
<li v-for="todo in todos">{{todo.text}}</li>
</ul>
<ul>
<li v-for="(todo,index) in todos">{{index+1}}/{{todo.text}}</li>
</ul>
<script>
new Vue({
el: "#app",
data: {
todos:[
{text:'아침먹고'},
{text:'점심먹고'},
{text:'집에가기'}
]
},
</script>
v-for=사용할 이름 in 출력할 배열
형태로 사용한다.https://doozi316.github.io/vuejs/2020/10/28/Vue7/
<p v-if="season">여름이 좋아</p>
<p v-else>겨울이 좋아</p>
<button v-on:click="season = !season">출력 결과 변경</button>
<template v-if="season">
<p>옷 입기가 편하다</p>
<p>해충이 많다.</p>
</template>
<template v-else>
<p>다양한 옷 스타일</p>
<p>해충이 없다.</p>
</template>
<!--v-show-->
<span v-show="season">
<p><b>옷 입기가 편하다</b></p>
</span>
<template v-show="season">
<p><b>옷 입기가 편하다2</b></p>
</template>
v-show
로는 template 엘리먼트 내용이 사라지지 않는다.v-if
를 사용하는 것이 적절하다.클릭수로 버튼 비활성화 하기
<p v-if="count === 10">{{count}}번 클릭. 버튼 비활성화</p>
<p v-else-if="count => 1">현재 클릭 수 : {{count}}번</p>
<p v-else>버튼을 클릭하시오</p>
<button v-bind:disabled="count===10" v-on:click="addFunc">증가</button>
<script>
new Vue({
el: "#app",
data: {
season: false,
myVisible: false,
count: 0,
},
methods: {
// addFunc:function(){
addFunc() {
this.count++;
},
},
});
</script>
checkbox로 if연습
<label><input type="checkbox" v-model="myVisible" />체크박스 확인</label>
<div v-if="myVisible">check On</div>
<div v-else>check Off</div>
(Vue객체는 위와 공유한다.)
반복렌더링 위한 v-for
<h3>갈증 날때</h3>
<ul>
<li v-for="li in list">{{li}}</li>
</ul>
<h3>문득 가보고 싶은 곳</h3>
<ol>
<li v-for="city in objArray">{{city.name}}은 {{city.taketime}}</li>
</ol>
<br />
<h3>구구단 7단</h3>
<ul>
<li v-for="n in 9">7 * {{n}} = {{n*7}}</li>
</ul>
<script>
new Vue({
el: "#app2",
data: {
list: ["아메리카노", "콜라", "사이다", "소맥"], //array
objArray: [
{ name: "강릉", taketime: "3시간" },
{ name: "부산", taketime: "6시간" },
{ name: "춘천", taketime: "2시간" },
],
myArr: ["일", "이", "삼", "사", "오"],
numArr:[1,2,3,4,5]
},
});
</script>
자료 추가 삽입 삭제 메소드 (splice)
<button @click="addList">자료추가(맨뒤)</button>
<button @click="addListIndex(3)">자료추가(선택)</button>
<button @click="changeList(2)">자료변경</button>
<button @click="delList(1)">자료삭제</button>
<script>
new Vue({
el: "#app2",
methods: {
addList: function () {
this.myArr.push("추가"); //맨뒤에 추가됨
},
addListIndex: function (arg) {
this.myArr.splice(arg, 0, "삽입"); //splice(지정위치,0,"자료")
},
changeList(arg) {
this.myArr.splice(arg, 1, "수정");
},
delList(arg) {
this.myArr.splice(arg, 1);
},
},
});
</script>
splice()
을 리스트에 유용하게 썼다.