5월 3주차- Vue.js

변승훈·2022년 5월 20일
0

※ 과제로 인하여 한 번에 정리해서 올립니다.

CDN을 이용한 Vue.js 써보기

<script src="https://unpkg.com/vue@next"></script>head 태그에 적어주면 vue 기능을 활욜할 수 있다.

기본적인 세팅

  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://unpkg.com/vue@next"></script>
  <script defer src="./main.js"></script>
</head>
<body>
  <div id="app">
  </div>
</body>
</html>
  • main.js
// 여러개를 만들 것을 전제한 컴포넌트(component)
const App = {
};
Vue.createApp(App).mount('#app');

1. Data

data속성은 반응성을 가지는 데이터들을 정의하는 용도이다.

★ data는 반응형 데이터이거나 반응성을 가진 데이터, 함수여야 한다.
반응성을 가졌기에 데이터가 바뀌면 화면이 자동으로 바뀐다.

데이터 바인딩의 가장 기본 형태는 Mustache구문(이중 중괄호, {{ }})을 사용한 텍스트 보간이며 화면에 문자열을 출력하는 간단한 경우에 쓰인다.

  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://unpkg.com/vue@next"></script>
  <script defer src="./main.js"></script>
</head>
<body>
  <div id="app">
    <input value="title" />
    <h2>
      {{ title }}
    </h2>
</body>
</html>
  • main.js
// 여러개를 만들 것을 전제한 컴포넌트(component)
const App = {
  data() {
  	return {
    	title: 'Hello~'
    }
  }
};
Vue.createApp(App).mount('#app');

출력 결과

2. 디렉티브

우리말로 표현하면 지시문이라고 할 수 있다. 보통 v-을 사용하여 표현한다.

  1. v-bind
    bind란 vue.js의 데이터를 직접 연결하겠다는 뜻이다.
    데이터는 기본적으로 요소 방향으로만(단방향) 흘러 들어가며 bind도 이에 해당한다.
    v-bind 대신 : 만 사용해도 된다.

위의 코드를 이용해서 bind를 사용해보면 다음과 같다.

<div id="app">
  <input v-bind:value="title" />
  <!-- <input :value="title" /> -->
</div>
// 여러개를 만들 것을 전제한 컴포넌트(component)
const App = {
  //(반응형) 데이터들을 작성
  //(반응성을 가진 데이터 = 반응형 데이터 = 데이터의 반응성 => 데이터가 바뀌면 화면이 자동으로 바뀌는 것)
  data() {
  	return {
    	title: 'Hello~'
    }
  }
};
Vue.createApp(App).mount('#app');

  1. v-on
    javascript에서의 addEvenListener와 같다.
    v-on대신 @만 사용해도 된다!
    컴포넌트에 methods를 추가하여 이벤트를 만들 수 있다!
    예를 들어 click이벤트로 위의 내용을 바꾸는 메소드를 적용해보자!
<div id="app">
  <input :value="title" />
  <button v-on:click="changeTitle">change!</button>
  <!--- <button @click="changeTitle">change!</button> -->
</div>
const App = {
  // 반응형 데이터 || 반응성을 가진 데이터, 함수여야 한다.
  data() {
    return {
      title:'Hello~', 
    }
  },
  methods: {
    changeTitle() {
      this.title = 'change!'
    }
  }
};

Vue.createApp(App).mount('#app');


출력 시 다음과 같은 화면이 나타나며, change! 버튼을 누르게 되면

다음과 같이 안의 title의 값이 change!로 변하게 된다!

  1. v-model
    데이터는 기본적으로 요소 방향으로만(단방향) 흘러 들어간다!
    화면을 입력한 데이터를 통해서 실제 반응형 데이터를 갱신해 주는 것을 양방향 데이터 바인딩이라한다.
    양방향 데이터 바인딩을 하려면 v-model을 사용하면 된다!

아래의 예시를 살펴보자!

<div id="app">
  <input v-model="title" />
  {{title}}
</div>
// 컴포넌트
const App = {
  // 반응형 데이터 || 반응성을 가진 데이터, 함수여야 한다.
  data() {
    return {
      title:'Hello~', 
    }
  },
  methods: {
    changeTitle() {
      this.title = 'change!'
    }
  }
};

Vue.createApp(App).mount('#app');


처음 출력시 위의 사진처럼 나오게 된다. input안의 value값을 변경해 주면 아래의 사진과 같이 이중 중괄호를 붙힌 데이터도 value의 값과 똑같이 실시간으로 변하는 것을 확인할 수 있다.

3. 리스트 렌더링

v-for: 배열을 기반으로 한 리스트를 for반복문을 통해 렌더링을 한다!

  <div id="app">
    <ul>
      <li v-for="item in items">
        {{ item.message }}
      </li>
    </ul>
  </div>
const App = {
  data() {
    return {
      items: [
        { message: 'Foo' },
        { message: 'Bar' }
      ]
    }
  }
};

Vue.createApp(App).mount('#app');


객체의 속성을 반복할 수도 있으며 키에 대한 두 번째 전달 인자 및 인덱스까지 출력이 가능하다.

<div id="app">
  <ul>
    <li v-for="value in object">
      {{ value }}
    </li>
  </ul>
  <div v-for="(value, name) in object">
    {{ name }}: {{ value }}
  </div>
  <div v-for="(value, name, index) in object">
  	{{ index }}. {{ name }}: {{ value }}
  </div>
</div>
const App = {
  data() {
    return {
      object: {
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2016-04-10'
      }
    }
  }
};

Vue.createApp(App).mount('#app');

4. 조건부 렌더링

  1. v-if, v-else-if, v-else
    조건에 따른 렌더링을 위의 3개를 통해서 사용이 가능하다!
    javascript에서 써 왔던 if, else 구문을 생각하면 된다!
    간단하게 어떻게 사용하는지만 예시로 적겠다.
<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  Not A/B/C
</div>
  1. v-show
    항상 렌더링은 하지만 화면에서 보이거나 보이지 않게 제어하는 역할을 한다.
<h1 v-show="ok">Hello!</h1>

5. Computed와 watch

  1. computed
    computed는 계산된 데이터를 넣어준다.
    일반적인 methods를 사용하면 해당 메소드를 호출할 때 마다 계속 실행이 되고 계산한다.
    이를 computed를 사용하면 단 한 번만 계산된 데이터를 뿌린다. 몇 번을 출력해도 한 번만 동작을 하게 되는데 이를 캐싱이라고 한다.
    computed는 기본 적으로 getter이지만 setter도 사용할 수 있다.
  <div id="app">
    <h1>{{title}}</h1>
    <h2>{{reversedMsgComputed}}</h2>
    <h2>{{reversedMsgComputed}}</h2>
    <h2>{{reversedMsgComputed}}</h2>
    <h3>{{reverseMsgMethod()}}</h3>
    <h3>{{reverseMsgMethod()}}</h3>
    <h3>{{reverseMsgMethod()}}</h3>
    
  </div>
const App = {
  data() {
    return {
      title:'Hello~', 
    }
  },
  computed: {
    reversedMsgComputed() {
      return this.title.split('').reverse().join('')
    }
  },
  methods: {
    reverseMsgMethod() {
      return this.title.split('').reverse().join('')
    }
  }
};

Vue.createApp(App).mount('#app');

  1. watch
    반응형 데이터들을 감시하는 옵션이다.
    값이 바뀌면 어떠한 로직을 처리해 달라 라고 할 수 있다.
<template>
  <h1 @click="changeMessage">
    {{ msg }}
  </h1>
  <h1>{{ reversedMessage }}</h1>
</template>
<script>
  export default {
    data() {
      return {
        msg: 'Hello Watch?'
      }
    },
    computed: {
       reversedMessage() {
         return this.msg.split('').reverse().join('')
      }
    },
    watch: {  
      // 감시하는 데이터들이 변경되는 것을 감지할 때 실행된다.
      // 데이터들의 변경사항들을 감시하는 옵션이다.
      
      // 1. 매개변수 이용 X
      msg() {
        // 변경이 일어났을 때 console.log를 출력
      	console.log('msg: ', this.msg)
        
      // 2. 매개변수를 이용 O
      msg(v) {
        console.log('msg: ', v)
      },
      // 계산된 데이터도 감시할 수 있다.
      reversedMessage() {
        console.log('reversedMessage: ', this.reversedMessage)
      }
    },
    methods: {
      // click시 msg를 'Good!'으로 변경시키는 메소드
      changeMessage() {
        this.msg = 'Good!'
      }
    }
  }
</script>

6. 클래스와 스타일 바인딩

클래스(HTML)속성과 style을 바인딩 한다.

  1. HTML 클래스 바인딩
    active의 키 값에 isActive라는 반응형 데이터가 truthy, falsy를 따져서 active를 붙일 것인가를 결정한다.
<button :class="{ active: isActive }" @click="clickEvent">Click!</button>
button.active { 
	background-color: red;
}

다음과 같은 코드가 있을 때 clickEvent에서 truthy를 반환하면 버튼의 색이 빨간색이 될 것이다.

  1. 인라인 style 바인딩
    style을 직접 바인딩을 할 수 있다.
    css속성의 이름은 dashcase를 쓰지만 javascript의 key이므로 카멜케이스로 작성을 한다. 카멜케이스는 자동적으로 dashcase로 변환시켜준다.
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

7. 이벤트 핸들링

@click="methodName"과 같이 등록해서 사용을 해주면 된다.
1. 인라인 메소드 핸들러
메소드 이름을 직접 바인딩 하는 대신에 인라인 javascript구문에 메소드를 사용할 수도 있다.

<div>
  <button @:click="say('hi')">Say hi</button>
  <button @:click="say('what')">Say what</button>
</div>
const App = {
  methods: {
   say: function (message) {
      console.log(message)
    }
  }
};

Vue.createApp(App).mount('#app');
  1. 이벤트 수식어
    점으로 사용할 수 있으며 다음과 같다.
<!-- 클릭 이벤트 전파가 중단됩니다 -->
<a v-on:click.stop="doThis"></a>

<!-- 제출 이벤트가 페이지를 다시 로드 하지 않습니다 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 수식어는 체이닝 가능합니다 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 단순히 수식어만 사용할 수 있습니다 -->
<form v-on:submit.prevent></form>

<!-- 이벤트 리스너를 추가할 때 캡처모드를 사용합니다 -->
<!-- 즉, 내부 엘리먼트를 대상으로 하는 이벤트가 해당 엘리먼트에서 처리되기 전에 여기서 처리합니다. -->
<div v-on:click.capture="doThis">...</div>

<!-- event.target이 엘리먼트 자체인 경우에만 트리거를 처리합니다 -->
<!-- 자식 엘리먼트에서는 안됩니다 -->
<div v-on:click.self="doThat">...</div>
  1. 키 수식어
    키 코드를 확인해야 하는 경우 사용하면 된다.
<input v-on:keyup.enter="submit">
<input v-on:keyup.page-down="onPageDown">

8. 폼 입력 바인딩

v-model디렉티브를 사용하여 대화영 요소들(input, textarea, select)을 양방향 데이터 바인딩으로 생성할 수 있다.

  1. 양방향 데이터 바인딩
    v-model을 이용한 양방향 데이터 바인딩이다.
    아래의 예시에서는 methods를 사용한 양방향 데이터 바인딩과 v-model을 사용한 양방향 데이터를 보여주는 예시이다.
  • .lazy: lazy를 붙히면 enter나 tab같은 걸로 체크를 해야 바뀌게 된다.
  • $: 시멘틱(의미만부여)한, 내부에서 관리된 것, 그때 그때 의미가 다르다.
  • Proxy: 참조형데이터(객체..)의 변경사항이 있는지, 읽으려고 하는지(조회)를 가로채서 getter,setter 로 사용한다. vue에서는 proxy로 값의 변경 유무에 따라 화면의 변경 유무를 정한다. 자세한 내용은 mdn을 참조하자.
<div id="app">
    <!-- v-bind : , v-on @ , v-model -->
    <input :value="title" @input="changeInput" />
    <input :value="title" @input="title = $event.target.value" />
    <input v-model="title" />
    <h1>{{ title }}</h1>

    <input :value="title" @change="title = $event.target.value" />
    <input v-model.lazy="title" />
    <h1>{{ title }}</h1>
  </div>
const App = {
  data() {  // 1. data를 함수로 사용하지 않으면 재사용할 때 데이터가 꼬인다
    return {
      // 2. 팩토리함수: 참조형 데이터를 반환하는 함수
      // 4. 데이터는 단방향 데이터 바인딩이다. 메소드를 통해 양방향 해줘야 한다.
      title: 'Hello~',
    }
  },
  methods: {
    changeInput(event) {
      console.log(event.target.value)
      this.title = event.target.value
    }
  }
}

// 3. component는 재사용을 전제로 한다.
Vue
  .createApp(App)
  .mount('#app')
  1. checkbox, radio

type을 checkbox, radio로 설정하여 사용한다.

  • checkbox: v-model="checked"로 작성해주고 checked가 true, false에 따라 체크의 유, 무로 만들어 준다.
  • radio: 택 1이므로 name속성을 똑같이 여러개를 만든 후 value의 값을 다르게 설정한 뒤 v-model="radio"를 해주면 된다.
<div id="app">
    <!-- checkbox, radio -->
    <input type="checkbox" v-model="checked" />
    <input type="radio" name="Hun" value="H1" v-model="radio" />
    <input type="radio" name="Hun" value="H2" v-model="radio" />
    <h2>{{ radio }}</h2>
    
    <input v-model="title" />
    <input v-model.number="title" />
    <h1>{{ typeof title }}</h1>
    
    <input v-model.trim="title" />
    <h1>{{ title }}</h1>


  </div>
const App = {
  data() { 
    return {
      title: 'Hello~',
      checked: true,
      radio: '',
    }
  }
}
Vue
  .createApp(App)
  .mount('#app')
  1. number, trim
  • number: v-model.number을 사용하여 숫자를 입력하면 파싱하여 자동으로 형변환을 해준다.
  • trim: v-model.trim을 사용하여 공백을 제거해준다.
<div id="app">
    <input v-model="title" />
    <input v-model.number="title" />
    <h1>{{ typeof title }}</h1>
    
    <input v-model.trim="title" />
    <h1>{{ title }}</h1>


  </div>
const App = {
  data() { 
    return {
      title: 'Hello~',
    }
  }
}
Vue
  .createApp(App)
  .mount('#app')
profile
잘 할 수 있는 개발자가 되기 위하여

0개의 댓글