Vue

Vue

wintertreey 2024. 8. 6. 08:36

Vue

React에 비해 가볍고 빠르게 개발이 필요한 경우 선호.

최신 릴리즈로 시작한 프레임워크(2014년).

Virtual Dom 활용으로 양방향 바인딩 처리 등 가능.(proxy를 이용하여 변경된부분만 반영한다. like React)

 

 

MVVM 패턴이란? 

마크업 언어나 GUI 코드를 비지니스 로직 또는 백엔드 로직과 분리하여 개발하는 소프트웨어 아키텍처 패턴을 말한다.

어플리케이션 로직과 UI를 분리하기 위해 설계된 패턴으로, UI를 가지는 응용 프로그램을 위한 아키텍처 패턴.

 

특징

MVVM 패턴은 MVC 패턴과는 다르게 커맨드와 데이터 바인딩을 가지고 있다.
뷰와 모델 사이의 양방향 데이터 바인딩을 지원한다.

UI를 별도의 코드 수정 없이 재사용할 수 있다.
단위 테스트등의 작업이 쉽다.

 

 

MVVM은 Model-View-View-Model의 줄임말로 각각 다음의 역할을 한다. 

View
  - 유저 인터페이스
  - HTML/CSS/XML/YAML 등으로 작성
ViewModel
  - 상태와 연산(명령)
  - View의 실제 논리 및 데이터 흐름을 담당
  - 상태 데이터를 변경하면 즉시 View에 반영
Model
  - 도메인 특화 데이터

 

MVVM 패턴의 주요 장점은 코드의 재사용성을 높이고, 테스트가 용이하며, 코드의 유지보수성을 향상시킨다는 점이다.

View와 비즈니스 로직을 명확하게 분리함으로써 개발자가 더 깨끗하고 관리하기 쉬운 코드를 작성할 수 있도록 도와준다.

 

 

 


 

새로운 폴더 생성.

 

 

확장 프로그램 추가설치

 

 

Live Server로 바로 웹띄우는 방법

Live Server 적용 예

 

서버 뜸

파일을 저장하면 바로 화면에 뜬다.

 


Vue 기본 문법 및 형태

 

보간법(Interpolation)

Vue.js는 Vue 인스턴스의 데이터를 DOM에 바인딩할 수 있는 html 기반 템플릿 문법을 제공한다. 이 데이터 바인딩을 위한 템플릿 문법 안에 텍스트보간(Mustache) / HTML보간(v-html) / Attribute보간(v-bind) 등이 있으며, 이들 보간법 중 몇가지에 디렉티브(v-)가 사용되는 것이다.


기본 문자열 - Mustache (이중 중괄호) {{}}

Mustache(머스타쉬-수염) 구문을 사용하여 데이터를 바인딩하는 기본적인 텍스트 보간이다.

 

그 이외에 텍스트보간 'v-text', HTML보간 'v-html', Attribute보간 'v-bind'이 있다.

 

 

CDN을 사용하여 라이브러리를 로딩할경우, 두 가지 경우가 있다. 

jquery를 이용하거나 vue를 이용하거나. 

 

1. 우선 jquery를 확인해보자

 

 

출력결과

 

2. vue3 라이브러리를 사용하면 다음과같다.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <!-- vue3 라이브러리 로딩: CDN-->
     <script src="https://unpkg.com/vue@3"></script>
  </head>
  <body>
    월요일 아침<br>
    jQuery 출력결과: <span id="msg"></span>
    <hr>
    vue 출력 1:
    <span id="app1">{{msg}}</span> <!--MVVM패턴의 view-->
    <script>
        let hi = {msg:'뷰세계 방문~'}; //데이터객체정의. MVVM패턴에서 Model
        Vue.createApp({ //MVVM 패턴에서 ViewModel
            // Vue.createApp()에 의해 생성된 객체를 어플리케이션 인스턴스라 함.
            data(){
                return hi;
            }
        }).mount('#app1') // id= "app1" 요소에 마운트(DOM요소에 연결. 즉 렌더링한다는뜻)
    </script>
  </body>
</html>

 

  데이터 바인딩 기본 형태는 Mustache(텍스토보간) 구문을 사용한다.

 

    <hr>
    vue 출력2: 
    <div id="app2">
        {{message1}}&nbsp;{{message2}}&nbsp;{{message3}}
    </div>
    <script> // vue3는 vue2와 달리 생성자가 아니라 createApp 함수를 이용해 어플리케이션을 인스턴스함.
      const {createApp} = Vue;
     createApp({
        data(){
            return{
                message1: '안녕 뚜비야',
                message2: '반가워' + '텔레토비동산은 여전하니?',
                message3: Math.random() * 9
            }
        }
     }).mount('#app2')
    </script>
  </body>

 

 


라이프 사이클 관련 메소드 확인

메소드 내에서 실행되는 custom logic을 cycle hook이라고 한다.

  beforeCreate() { //초기화 담당
        console.log('beforeCreate: 인스턴스가 생성되고나서 가장 처음으로 실행')
       }, 
       created() { //화면에 반응성 주입
        console.log('created: 아직 화면 요소에 인스턴스가 부착되기 전 ')
       },
       mounted() { //속성값대입
        console.log('mounted: 지정한 화면 요소에 인스턴스가 부착되고 난 후 호출')
       },
       beforeUpdate() { //인스턴스의 데이터변경
        console.log('beforeUpdate: 지정한 화면 요소에 인스턴스가 부착되고 난 후에 인스턴스 속성들이 화면에 치환')
       },
       updated(){
        console.log('updated: beforeUpdate가 끝나고 화면에 다시 그리고 나면 실행')
       },
       methods: {
        updateMessage(){
            this.message1="hello";
            this.message2="good";
            this.message3= Math.random() *90;
        }
       }
     }).mount('#app2')
    </script>

 

 

메세지변경 버튼 클릭 전 후


컴포넌트 사용 범위 ex2

전역 컴포넌트 : 여러 컴포넌트에서 유효

지역 컴포넌트: 특정 컴포넌트에서 유효

    <div id="appBasic">
        <hello></hello> <!--hello컴포넌트 사용-->
    </div>
    <div id="appBasic2">
        <world style="color: pink"></world> <!--world컴포넌트 사용-->
        <world style="color: olive"></world>
    </div>

    <script>
        const { createApp } = Vue; //첫번째 vue application instance

        const appBasic = createApp({});

        // XXX.component('컴포넌트명', 옵션)
        appBasic.component('hello', { //hello 컴포넌트를 전역으로 선언
            template: "<h1>{{title}}</h1>", //컴포넌트의 템플릿을 정의. html, css 등의 마크업을 정의
            data(){
                return{
                    title: '안녕하세요' //컴포넌트의 local data를 정의
                }
            }
        });
        appBasic.mount('#appBasic')

        const appBasic2 = createApp({}); //두번째 vue application instance

        appBasic2.component('world', {
            template: "<h3>{{title}}<button @click='changeTitle'>타이틀교체</button></h3> ",
            //컴포넌트 템플릿과 이벤트 포함
            data(){
                return{
                    title: '무더운여름'//컴포넌트의 local data를 정의
                }
            },
            methods: {
                changeTitle(){
                    this.title= "설경이보고싶어요"; //버튼별로 this.title 수행
                }
            },
        });
        appBasic2.mount('#appBasic2')
        </script>

 

<hello> 컴포넌트는 글자만,

<world> 컴포넌트는 이벤트버튼을 포함했다.

코드를 통해  vue의 기본 문법틀을 확인할 수 있다.

 

버튼을 누르면 글자내용이 바뀐다. 

 

 

 

글자출력순서를 통해 전역, 지역 컴포넌트 등록과 그 문법을 확인 할 수 있다.

 <hr color="skyblue" size="10px">
        <div id="app">
            <div>컴포넌트 등록1</div>
            <my-global-componet></my-global-componet>
            <my-local-componet></my-local-componet>
        </div>
        <hr>
        <div id="app2">
            <div>컴포넌트 등록2</div>
            <my-global-componet></my-global-componet>
            <my-local-componet></my-local-componet>
        </div>
        <hr>
        <div id="app3">
            <div>컴포넌트 등록3</div>
            <my-global-componet></my-global-componet>
            <my-local-componet></my-local-componet>

        </div>
<script>
    //전역 컴포넌트를 등록하는 공용 컴포넌트를 정의
    const myGlobalComponet = {
        template:"<b>전역 컴포넌트 등록</b>",
    }

    const app = Vue.createApp({
        components:{
            'my-global-componet': myGlobalComponet, //전역 컴포넌트 등록
            'my-local-componet': { //지역 컴포넌트 등록
                template: "<br><i>지역 컴포넌트 등록</i></br>"
            },
        },
    });
    app.mount('#app')

    const app2 = Vue.createApp({
        components:{
            'my-global-componet': myGlobalComponet, //전역 컴포넌트 등록
            'my-local-componet': { //지역 컴포넌트 등록
                template: "<br><i>지역 컴포넌트 등록2</i></br>"
            },
        },
    });
    app2.mount('#app2')

    const app3 = Vue.createApp({
        components:{
            'my-global-componet': myGlobalComponet, //전역 컴포넌트 등록
            'my-local-componet': { //지역 컴포넌트 등록
                template: "<br><i>지역 컴포넌트 등록3</i></br>"
            },
        },
    });
    app3.mount('#app3')
</script>

 

 

 


빌트인 디렉티브

디렉티브는 v-접두사가 있는 특수 속성이다. 그대로 직역하면 '지시'를 뜻한다.
즉, 디렉티브는 기능상에서 중요한 역할인 컴포넌트(또는 DOM요소)에게 "~~~하게 작동할 것"을 지시해주는 지시문을 말한다.

 

링크로 이동, 이미지 읽기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/vue@3"></script>
</head>
<body>
  <div id="app">
    <a href="{{link}}">링크(에러.연결안됨)</a><br>
    <!--directive 사용: 동적으로 href 속성을 vue인스턴스의 link 데이터 속성과 연결-->
    <a v-bind:href="link">다음으로연결</a><br>
    <a :href="link">다음으로연결</a><br>
    <img v-bind:src="imageSrc" alt="동적 이미지"/><br>
  </div>

  <script>
    const {createApp} = Vue;

    createApp({
        data(){
            return{
                link:'https://cafe.daum.net/flowlife',
                imageSrc:'googlebird.png',
            }
        },
    })
  </script>
</body>
</html>

 

{{}} mustache는 a태그에서 효과가 없다. 디렉티브를 사용해서 다음카페로 동적이동을 수행했다.

  <a href="{{link}}">링크(에러.연결안됨)</a><br>
    <!--directive 사용: 동적으로 href 속성을 vue인스턴스의 link 데이터 속성과 연결-->
    <a v-bind:href="link">다음으로연결</a><br>
 <a :href="link">다음으로연결</a><br>

 

이때 v-bind는 생략해도 무방하다.

 

 

출력물

 

 

텍스트읽기

link와 달리 {{}} mustache를 써도 결과는 잘 출력된다.

 

  <div id="app">
    <h2 v-text='speakoutloud'></h2>
    <h2>data속성값1: {{speakoutloud}}</h2>
    <h2 v-once='speakoutloud'>data속성값2: {{speakoutloud}}</h2>
    <h3>함수 호출 결과: {{solFunc()}}</h3>

  </div>

 

<script>
    const {createApp} = Vue;

    createApp({
        data(){
            return{
                speakoutloud: '집이좋다구요!!!!!',
            }
        },
        methods: {
          solFunc(){
            this.speakoutloud='엄청습합니다';
            return this.speakoutloud;
          },
        },
    }).mount('#app')
  </script>

 

v-text 는 여러번 수행가능.

v-once는 한번만 수행가능.

따라서 once인 속성값2는 변하지 않앗음을 확인 할 수 있다.

 

 

 

innerText, innerHtml

양방향 데이터바인딩, computed, 형변환 

    <div>
    <span v-text="aLinkNaver">문자열그대로출력(innerText)</span><br>
    <span v-html="aLinkNaver">문자열그대로출력(innerHtml)</span><br>
     <!-- 양방향 데이터 바인딩: v-model은 v-bind + v-on --->
     이름은 <input type="text" v-model="name"/> {{name}} <br>
     이름은 <input type="text" v-bind:value="name" v-on:input="changeName"/> {{name}} <br>
     이름은 <input type="text" :value="name" @input="changeName"/> {{name}} <br>
      <!--계산된 프로퍼티 관련-->
    a={{a}}, b={{b}}<br/>
    a값 입력: <input type="text" v-model="a"/><!--문자열-->
    <br>입력된 a: {{a}} (타입: {{typeof a}})</br>
     a값 입력: <input type="text" v-model.number="a"/> <!--문자열>숫자로 형변환-->
    </div>
    
    <script>
    const {createApp} = Vue;

    createApp({
        data(){
            return{
                aLinkNaver:'<a href="https://naver.com">가자 네이버로</a>',
                name:'3팀',
                a: '1', //문자열데이터
                nai: 23, //숫자데이터
            }
        },
        methods: {
          changeName(e){
            this.name = e.target.value;
 			},
        },
        computed:{ 
          b(){
            return this.a +1;
          }
        }
    }).mount('#app')
  </script>

 

computed properties:

함수처럼 작동. 차이는 계산된 프로퍼티가 의존하는 요소가 변경되면 반응

 

양방향으로 데이터가 출력된다. 어느칸에다 적어도 모두 반영이 된다.

 

첫번째 a 입력칸은 string처리를 해뒀다. 

그래서  해당칸에 15를 입력하면 b는 그 값을 문자열로 받아들여 151로 출력된다.

 

두번째 a 입력칸은 number처리를 해줬다. 

해당 칸에 5를 입력하면 숫자 +1로 계산하여  출력한다.

 

 

제어문: 조건판단문, 반복문 for

  제어문 : 조건판단문, 반복문<br>
    <h2 v-if="nai > 20">nai가 20초과</h2>
    <h2 v-else-if="nai===20">nai가 딱 20</h2>
    <h2 v-else>nai가 20미만</h2>
    제어문: 반복문for <br/>
    <h3>오늘 할일</h3>
      <ol>
        <li v-for="(todo, index) in todos" :key="index">{{todo.txt}}</li>
      </ol>
      <ul>
        <li v-for="(todo, index) in todos" :key="index">{{index+1}}) {{todo.txt}}</li>
      </ul>
  </div>

<script>
    const {createApp} = Vue;

    createApp({
        data(){
            return{
                todos: [
                  {txt:'아침먹고'},
                  {txt:'점심먹고'},
                  {txt:'집에가기'}
                ]
            }
        },

 

 

 

 

 

 


 

https://cafe.daum.net/flowlife/QbpR/77

 

MVVM pattern?

What is MVVM?마크업 언어나 GUI 코드를 비지니스 로직 또는 백엔드 로직과 분리하여 개발하는 소프트웨어 아키텍처 패턴을 말한다. - MVVM 패턴은 MVC 패턴과는 다르게 커맨드와 데이터 바인딩을 가

cafe.daum.net

https://velog.io/@roong-ra/VueJS-2.-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%AC%B8%EB%B2%95-%EB%B3%B4%EA%B0%84%EB%B2%95Interpolation%EC%9C%BC%EB%A1%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B0%94%EC%9D%B8%EB%94%A9%ED%95%98%EA%B8%B0

 

VueJS 2. 템플릿 문법 - 보간법(Interpolation)으로 데이터 바인딩하기

Vue.js는 Vue 인스턴스의 데이터를 DOM에 바인딩할 수 있는 html 기반 템플릿 문법을 제공한다. 이 데이터 바인딩을 위한 템플릿 문법 안에 텍스트보간(Mustache) / HTML보간(v-html) / Attribute보간(v-bind) 등

velog.io

https://cafe.daum.net/flowlife/QbpR/64

 

Vue

- React에 비해 가볍고 빠르게 개발이 필요한 경우 선호- 최신 릴리즈로 시작한 프레임워크(2014년)- Virtual Dom 활용으로 양방향 바인딩 처리 등 가능 Single File ComponentVue는 단일 파일 컴포넌트 기반

cafe.daum.net

 

https://velog.io/@falling_star3/Vue.js-%EB%94%94%EB%A0%89%ED%8B%B0%EB%B8%8CDirectives%EB%9E%80

 

[Vue.js] 디렉티브(Directives)란?

📌 디렉티브(Directives)란? >**디렉티브는 v-접두사가 있는 특수 속성이다. 그대로 직역하면 '지시'를 뜻한다. 즉, 디렉티브는 기능상에서 중요한 역할인 컴포넌트(또는 DOM요소)에게 " Vue는 여러가

velog.io