Vue.js
- Node.js에서 파생된 형태이며, reAct.js와 함께 많이 사용되고 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Node.js :
- CSR : Client Side Randering
1. angular.js : 현재 많이 사용X
2. reAct.js : 현재 많이 사용 (라이브러리)
3. Vue.js : 현재 많이 사용 (프레임워크 : 규칙대로 하면 알아서 돌려줌)
CSR의 문제점 : Google 검색 결과로 안 나타난다.
CSR의 문제점을 보완하기 위해 SSR이 등장
- SSR : Server Side Randering
1. reAct.js에서 SSR에 적용하기 위해 Next.js를 발표
2. Vue.js에서는 Nuxt.js를 발표
Next.js와 Nuxt.js에서 express.js를 이용하여 DB로 직접 연결하기 때문에 기존의 Spring Framework의 역할을 대체함
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<body>
<div id="example">
<p></p>
</div>
<script src="https://unpokg.com/vue"></script>
<script>
new Vue({ // vue를 쓰겠다
el : '#example' // example이라는 아이디에 해당하는 태그를 관리하겠다.
data : {hellow : 'Hellow World!'}
// example 아이디를 가진 태그안의 hellow의 값은 Hellow World!이다,
// 태그 밖의 hellow에는 Hellow World!가 찍히지 않는다
})
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
- 가상 DOM을 활용한다
- 반응적이고 조합 가능한 컴포넌트를 제공한다
- 코어 라이브러리에만 집중하고 있고 라우팅 및 전역 상태를 관리하는 컴패니언 라이브러리가 있다
가상 DOM을 활용한다
xPath라고 하는 경로가 있는데,
hellow의 경우 xPath가 html - body - div[0] - p[0]이 해당된다.
가상DOM은 이러한 vue와 관련된 변수의 경로를 관리하는 것이다.
1
2
3
4
5
6
7
8
CDN NPM
Vuex O O Vue 문법 해석 / 실행
Vue CLI X O Command Line Interface
Vue 문법 해석 / 실행
Vue Router X O URL 관리 등록 / 수정 / 삭제 / History 관리
1
2
3
4
5
6
Vuetify
전자정부프레임워크가 스프링프레임워크를 기반으로 만들어진 프레임워크인 것 처럼 Vuetify는 Vue(프레임워크)를 기반으로 만들어진 프레임워크이다.
그외 framework
Quasar
Bootstrap Vue
🔸Life Cycle
vue.js 2.x 버전
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
🔸beforeCreate : Vue 인스턴스가 초기화 된 직후 발생. 아무것도 접근하지 못하는 상태 var app = new Vue({ el: '#app', data() { return { msg: 'hello'; } }, beforeCreate(function() { console.log(this.msg); // undefined }) }) 🔸created : Vue 인스턴스가 완전히 만들어지고, data, method, computed, watch 등에 접근 가능. DOM에는 추가되지 않음 data에 직접 접근이 가능하므로, 컴포넌트 초기에 외부에서 받아온 값들로 data를 생성하거나 이벤트 리스터를 선언하기 가장 적절 created(function(){...}) 🔸berforeMount : DOM에 부착하기 직전에 호출되는 훅. 템플릿이 있는지 없는지 확인한 후 템플릿을 랜더링한 상태이다. berforeMount(function(){...}) 🔸mounted : 가장 많이 사용되는 훅 가상 DOM의 내용이 실제 DOM에 부착되고 난 후 실행. this.$el을 비롯한 data, method, computed, watch 등 모든 요소에 접근 가능
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
부모와 자식 컴포넌트 간의 mounted 훅 순서는 위와 같은데, 부모 mounted 훅은 자식 mounted 훅 다음에 일어난다. 하지만 자식 컴포넌트가 비동기로 데이터를 받아오는 경우 부모의 mounted 훅이 모든 자식의 mounted 훅을 보장하지는 않는다. 이때, this.$nextTrick을 이용하면 모든 화면의 랜더링 된 이후 실행되므로 mount 상태를 보장하게 된다. (this.$nextTick(function(){...})) 🔸beforeUpdate : 컴포넌트에서 사용되는 data의 값이 변해서, DOM에도 그 변화를 적용시켜야 할 때 호출 변할 값을 이용해 가상 DOM을 랜더링하기 전이지만, 이 값을 이용해 작업할 수는 있다. 여기서 값들을 추가적으로 변화시키더라도 랜더링을 추가로 호출하지는 않는다. 🔸updated : 가상 DOM을 랜더링하고 실제 DOM이 변경된 이후에 호출, 즉 변경된 data가 DOM에 적용된 상태 변경된 값들을 DOM을 이용해 접근하고 싶다면, updated 훅이 가장 적절 주의점은 이 훅에서 data를 변경하면 무한루프를 일으킬 수 있으므로 data 변경은 금지 this.$nextTick(function(){...}) 을 이용해 DOM의 모든 화면이 업데이트 된 이후의 상태를 보장할 수 있다 🔸beforeDestroy : 인스턴스가 해체되기 직전에 호출 해체 이전이므로 아직은 인스턴스가 완전히 작동 중. 이 단계에서 이벤트 리스너 해제 같은 일들을 처리 🔸destroyed : 인스턴스가 해체되고 난 직후에 호출 더이상 인스턴스 속성에 접근 불가능, 하위 인스턴스 역시 삭제됨
vue.js 3.x 버전
용어 및 속성
1 2 3 4 5 6
🔸v-model 지정된 특정 Tag의 value를 Vue 변수에 집어 넣을 때 <input type="text" class="inputTxt p100" name="inputtext" id="inputtext" v-model="inputtext" @input="inputkey" /> Tag value < > 변수(양방향) Vue.js Tag value > 변수(단방향) reAct.js
1 2 3 4 5 6 7 8 9 10 11
🔸v-bind 태그의 속성을 작성하고 적용할 때 data : { vstyle:"width:400", vid:"sid", vname:"sname" } 작성 <input type="text" v-bild:style="vstyle" v-bind:id="vid" v-bind:name="vname"/> 간편식 <input type="text" :style="vstyle" :id="vid" :name="vname"/> 반영된 결과 <input type="text" style="width:400" id="sid" name="sname"/>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
🔸v-on 이벤트를 걸어줄 때 사용 만약 자바스크립에 같은 이름의 함수가 있더라도, 자바스크립트의 함수를 호출하지 않는다 v-on : 이벤트명="(Vue Method)" @이벤트명="(Vue Method)" methods:{ selimg:function(event){ var image = event.target; if(image.files[0]){ alert(window.URL.createObjectURL(image.files[0])); vuevar.inputtext="asdfghj"; this.imgpath = window.URL.createObjectURL(image.files[0]); } } } 작성 <input type="file" id="filesel" name="filesel" v-on:change="selimg" /> 간편식 <input type="file" id="filesel" name="filesel" @change="selimg" /> 🔸이벤트를 발생시킬 때, method명만을 적거나 또는 $event를 명시하여 매개변수로 넘겨주어야 event 발생, 매개변수가 생략되면 기본값으로 이벤트로 넘긴다. 하지만 method명()로 한다면, 매개변수를 안보내겠다는 명시적 의미 (@input="test" == @input="test($event)") != @input="test()"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
🔸v-if v-else v-else-if v-if는 html에 Tag를 넣고 빼고 한다 data : { vshow : true, } <input type="text" v-if="vshow" id="aa"/> <input type="text" v-else id="bb"/> vshow = false; -> id가 aa인 태그 자체가 사라져 버리고, id가 bb인 태그가 나타나게 된다 🔸다중조건 AND : && OR : || ()도 사용 가능
1 2 3 4 5 6 7 8 9 10
🔸v-show 태그가 사라지는게 아니라 보이고 안보이고를 만들어 준다 data : { vshow : true, } <input type="text" v-show="vshow" id="aa"/> vshow = false; -> <input type="text" style="display:none" id="aa"/>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
🔸v-html, v-text data : { inval : "<input id='id1' />, } 작성 <div v-html="inval"> 결과 <div> <input id='id1'/> </div> 작성 <td v-text="inval"></td> 결과 <td> <input id='id1' /> => 문자열이 찍힌다. 태그X </td>
1 2 3 4 5
🔸v-for 반복문 CDN방식과 NPM 방식에서 차이를 보인다 NPM에서는 v-bind로 고유키를 지정해줘야 한다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
🔸prop 본인이 태그를 만든다고 생각하면 된다 -- 전역 컴포넌트 Vue.component('my-component',{ template : '<div>전역 컴포넌트</div>' }); Vue.component 를 만들거에요 my-component라는 이름(==태그명)으로 만들거에요 => 결과 <my-component></my-component> 로 작성해 놓으면 그 안에 <div>전역 컴포넌트</div>로 만들어짐 -- 지역 컴포넌트 new Vue({ el : '#vueprop1', }); vueprop2 = new Vue({ el : '#vueprop2', components:{ 'my-component-child':{ props:['msg'], template : '<div>지역 컴포넌트 </div>' }, } }); #vueprop1 인 태그를 vue로 관리할건데, 그안에 components를 만들거야, 즉 여기서만 사용하는 사용자 정의 태그야 🔸컴포넌트의 어려운 점은 vue 객체와 컴포넌트의 동작이 따로 돌아가기 때문에 서로 연결고리가 없어, 데이터 조작에서 어려움이 있다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
prop은 단방향으로 내려가는 바인딩 형태이다. 따라서, 부모 컴포넌트가 업데이트 될 때마다 자식 요소의 모든 prop들이 최신 값으로 새로고침 된다. 자식 컴포넌트 안에서 prop의 값의 수정을 시도하는 경우 경고를 표시하게 된다 1. prop은 초기값만 전달하고, 자식 컴포넌트는 그 초기값을 로컬 데이터 속성으로 활용하고 싶은 경우 -> 로컬 데이터 속성을 따로 선언하고 그 속성의 초기값으로써 prop을 사용한다 props : ['initialCounter'], data : function(){ return { counter : this.initialCounter } } 2. 전달된 prop의 형태를 바꿔야 하는 경우 -> computed 속성을 사용하는 것이 좋다 props : ['size'], computed : { normalizedSize : function(){ return this.size.trim().toLowerCase() } } ==> 자바스크립트 오브젝트나 배열을 prop으로 전달하는 경우, 객체를 복사하는 것이 아니라 참조하게 된다. 전달받은 오브젝트나 배열을 수정하게 되는 경우, 자식 요소가 부모 요소의 상태를 **변경하게 되는 것** 이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
prop의 유효성 검사 컴포넌트는 prop의 유효성 검사를 위해 요구사항을 특정할 수 있다. Vue.component('my-component', { props : { // 기본타입체크 (Null 이나 'undefineded는 모든 타입을 허용) propA : Number, // 여러 타입 허용 propB : [Number, String], // 필수 문자열 propC : { type : String, required : true }, // 기본값이 있는 숫자 propD : { type : Number, default : 100 }, // 기본값이 있는 오브젝트 propE : { type : Object, // 오브젝트나 배열은 꼭 기본값을 반환하는 팩토리 함수의 형태로 사용 되어야 한다 default : function(){ return { message : 'hello' } }, } // 커스텀 유효성 검사 함수 propF : { vallidator : function(value){ // 값이 항상 아래 세 개의 문자열 중 하나여야 한다. return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } } }) prop의 유효성 검사는 컴포넌트 인스턴스가 생성되기 전에 일어난다는 것을 기억하자!! 즉, 인스턴스의 값(e.g. `data`, `computed`, 등등)은 `default` 나 `validator` 함수 안에 사용될 수 없다 type의 종류 String, Number, Boolean, Array, Object, Data, Function, Symbol 그리고 커스텀 생성자가 사용될 수 있다. instanceof를 통해 확인이 이루어진다. function Person (firstName, lastName) { this.firstName = firstName this.lastName = lastName } Vue.component('blog-post', { props : { author : Person } }) author prop이 new Person 으로 생성된 값인지 확인할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
prop이 아닌 속성은 컴포넌트에 전달되긴 하지만 대응되는 prop이 정의되지 않는다. 명확하게 정의된 prop을 통해서 자식 컴포넌트에 정보를 전달하는 것이 권장되지만, 컴포넌트 라이브러리를 만드는 경우 어떤 맥락에서 사용될지 알 수 없기 때문에 이러한 경우에는 컴포넌트는 임의의 속성값을 받아와 컴포넌트의 루트 엘리먼트에 추가해 줄 수 있다 ex) data-data-picker 속성이 필요한 부트스트랩의 서드파티 컴포넌트인 bootstrap-data-input을 사용하는 상황을 가정해 보자. 이 경우, 아래와 같이 컴포넌트 인스턴스에 속성을 추가해 줄 수 있다. <bootstrap-data-input data-data-picker="activated"></bootstrap-data-input> data-data-picker="activated" 속성은 bootstrap-data-input의 루트 엘리먼트에 자동으로 추가된다 기존 속성의 대체 및 병합 아래의 코드가 bootstrap-date-input의 템플릿이라고 하자 <input type = "date" class="form-control"> 날짜 선택 프로그인의 테마를 설정하기 위해서는 아래와 같이 특정 클래스를 작성해줘야 한다. <bootstrap-date-input data-date-picker="activated" class="date-picker-theme-dark"></bootstrap-date-input> 이 경우, 두 개의 각각 다른 값이 class에 선언되어 있다. form-control : 컴포넌트 템플릿으로부터 부여 date-picker-theme-dark : 컴포넌트의 부모로부터 전달받아 부여 대부분 속성의 경우, 전달받은 속성이 기존의 속성을 대체한다. type="text"를 type="date"가 선언된 컴포넌트에 전달할 경우에 속성이 대체 된다. 하지만, class와 style 속성의 경우에는 대체가 아니라 합쳐져서 적용된다. 컴포넌트의 루트 엘리먼트가 상속된 속성을 갖지 않기를 원하는 경우, 컴포넌트에 inheritAttrs: false 옵션을 줄 수 있다. Vue.component('my-component', { inheritAttrs: false, ... }) 이는 컴포넌트에 전달된 속성의 이름과 값을 가지고 있는 인스턴스 속성인 $attrs와 조합하면 유용하게 사용할 수 있다. { required : true, placeholder : 'Enter your username' } inheritAttrs: false 와 $attrs를 이용하면 수동으로 전달할 속성을 선택할 수 있으며, 이는 스타일 규칙 중 base components를 지키는 방법이다 Vue.component('base-input', { inheritAttrs : false, props : ['label', 'value'], template : `<laber> <input v-bind="$attrs" v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > </label>` }) => <base-input v-model="username" required placeholder="Enter your username" ></base-input>
1 2 3 4 5 6
🔸Computed 메소드와 동작방식은 같지만, computed는 캐쉬를 이용한다. 메소드는 호출될 때마다 새로 시행되는 느낌이라면, computed는 캐쉬를 이용하기 때문에 초기화 하지 않고, Computed안에 처리된 데이터가 계속 유지되어 다음 계산에도 사용된다. * 실무에서는 잘 사용하지 않는다
1 2
🔸watch 지정된 변수가 바귀었을 때 실행시켜주는 메소드
1 2 3 4 5 6 7 8 9 10 11
🔸template 태그 더미 태그라고 보면 된다. html에 적용이 되지 않는 태그. vue 문법을 적용하고 싶은데 html에 반영하기는 원하지 않을 때 사용한다. v-for와 template, v-model을 이용하면, 예를들어 사용자의 selectBox의 선택에 따라 v-model에 의해서 변수 값이 변화되고, 이것을 이용하여 사용자의 선택에 따라 변수의 값을 변화시킬 수 있다. ex) 주문에서 선택에 따라 추가되는 경우 다른 예시로는 option 설정을 v-for로 돌리되, 항목을 DB에서 불러온 리스트로 세팅을 한다고 한다면, DB에서 불러온 항목의 값으로 option 창을 만들 수 있게 된다
구성
1) Java + JSP or Vue의 CDN방식
- 브라우저 → JSP(화면) → Java, Tomcat → Mybatis이용 → DB 접속
- ajax사용하여 비동기 사용
2) Vue.js NPM 방식 (CSR)
- 브라우저 → Vue.js(화면) → Node.js의 서버 → Java, Tomcat → Mybatis이용 → DB 접속
- ajax 대신에 axios를 사용하게 된다
3) Nuxt.js NPM 방식 (SSR)
- 브라우저 → Nuxt.js(화면) → Express.js → DB 접속
- 화면에서 랜더링을 통해 동적인 사이트를 만들어줌