Vue instance:

뷰로 화면을 개발하기 위해 필수적으로 생성해야 하는 기본 단위이다.

아래는 뷰 인스턴스를 생성하는 방법 중 하나이다.

new Vue({
	el: '태그이름',
	data: {
    	something: '어떤 것'
    }
})

<div id="태그이름">
	{{something}}
</div>

인스턴스 안에 el 속성을 통해 뷰 인스턴스가 그려질 지점을 지정하게 된다.

data 속성에 화면에 보여질 데이터를 정의한다.

그 결과 html 태그에 텍스트를 보여줄 수 있게 된다.

 


CDN 방식:

웹 애플리케이션에 js framework나 라이브러리를 바로 사용할 수 있는 호스팅 서비스

(Vue Cli만 사용해 보았었는데 CDN도 마찬가지로 Vue의 기능을 모두 사용할 수 있다고 한다. CDN 방식의 경우는 빌드 등을 할 필요 없이 파일만 클릭하면 html 파일이 띄워 졌다.)

그래서 CDN은 결국 서버에 보내는 request이고, 브라우저는 한 시점에 제한된 개수(5~6개??)의 request를 요청할 수 있기 때문에 CDN으로 가져오면 request가 하나 늘어나는 것이나 다름 없으므로 url로 부터 리소스를 가져올 것이 많은 경우에는 결과적으로 페이지를 볼 수 있을 때까지 조금 더 기다리게 된다고 한다.

 

다른 이유로는

script 태그로 참조하여 사용하는 방법으로는 SPA(Single Page Application) 앱을 개발할 수 없기 때문에 대부분 Vue CLI 도구를 이용

Vue CLI를 이용해 개발하면 .vue 파일로 분리된 단일 파일 컴포넌트 단위로 컴포넌트 중심의 개발을 합니다. 개발된 컴포넌트를 조합하여 UI를 구성한다. 개발된 코드는 webpack에 의해서 빌드 및 번들링된 후 배포버전의 html, css, js 파일을 생성한다. (하나의 html 파일로 만듦)

⇒ 스크립트 태그로 참조하는 방식은 이게 불가능함

 

 

HTML id vs class?

id는 한 페이지에 하나의 style/css로 하나의 태그만 사용할 수 있다. 따라서 로고, 상단 메뉴, 하단 정보와 같은 스타일을 정의할 때 사용한다. el 지정을 할 때 .app 이런 식으로 정의해야 함

class는 한 페이지에 반복적으로 사용 되는 스타일을 정의할 수 있다. el 지정을 할 때 #app으로 정의한다.

반복적으로 사용 되는 스타일에는 class, 그 내부에 세부 스타일에는 id를 사용하면 효과적이다.

⇒ 객체를 굳이 지정하지 않은 경우에는 id를 써 주지 않도록 함!!!

* 브라우저가 id는 매우 빠르게 접근이 가능하게 별도로 관리 한다. class나 tag의 경우 css query 방식을 이용한다.

 

추가적으로 태그 등에 신경쓰도록 하자 - 시멘틱 웹

velog.io/@kimu2370/%EC%8B%9C%EB%A7%A8%ED%8B%B1-%EB%A7%88%ED%81%AC%EC%97%85

 

Semantic Web

about semantic web

velog.io

클래스 선택자는 글자색/글자 굵기 등 나중에 다른 곳에도 적용할 수 있는 스타일을 지정하고, ID 선택자는 웹 문서 안에서 요소의 배치 방법을 지정할 때 자주 사용한다.

http://www.nextree.co.kr/p8468/: 선택자 관련 내용


Vue에서 바인딩

Vue 인스턴스가 생성될 때 data 객체에 있는 모든 속성이 Vue의 반응형 시스템에 추가된다. 즉, 각 속성 값이 변경될 때 뷰가 반응해서 새로운 값과 일치하도록 업데이트된다.

데이터가 변경되면 화면은 다시 렌더링 되는데, data에 있는 속성들은 인스턴스가 생성될 때 존재한 것들만 반응형이다. 즉, 나중에 데이터를 추가된 데이터가 변경되면 화면이 갱신되지 않는다.

  • vue에서는 바인딩 methods를 이벤트와 바인딩 할 때 @를 사용한다!!
    • @는 v-on: 과 같은 역할을 한다. 그래서 클릭 이벤트를 바인딩 하고싶다면 @click을 사용하면 된다.
  • computed를 사용하는 방법
    • computed는 옵저버 패턴으로 동작한다. (watch도 마찬가지)
    • computed를 사용해서도 동일한 동작을 하도록 만들 수 있다.

데이터 변동이 없는 상태에서 computed는 이전의 계산된 값을 캐시 해 두었다가 함수 호출 시 다시 쓰게 된다. methods는 사용될 때마다 함수의 계산을 다시 하게 된다.

그래서 만약 데이터가 자주 변동되지 않는다면, computed가 좋다고 할 수 있고, 데이터가 수시로 업데이트 된다면 계속해서 캐시를 저장하는 computed보다는 methods가 더 좋을 수 있다고 한다.

 

결론(?)

  • computed: template 내부에 선언된 computed중에서 해당 함수와 연결된 값이 바뀔 때만 해당 함수 만을 실행한다.
  • methods -그런거 모르겠고 template내부에 선언된 methods중에서 update 라이프 사이클이 동작한(=아무 변수나 바뀐)다면 화면에 붙어 있는 함수를 모두 실행한다.

1. 파라미터를 받아서 호출 해야할 때 - data를 사용하지 않는다면 computed로는 아예 불가능하다.

2. 함수 안에서 다른 값을 바꿔 줘야 할 때 - computed에서는 다른 값을 바꾸는 것은 정책 위반이다. (불가능한건 아니지만) 이 경우는 methods를 사용한다.

 

 

## computed와 watch의 차이

어떻게 사용하느냐에 따라 watch가 computed의 역할까지도 할 수 있다.

  • watch : 반응형 콜백

    Vue 인스턴스의 특정 프로퍼티가 변경될때 지정한 콜백함수가 실행되는 기능이다.

    data에 선언되어 있는 값이 watch 안에도 그대로 선언이 될 수 있다. 이렇게 watch는 기존에 Vue 인스턴스 내에 선언된 값의 변화를 감시하는 역할을 하기 때문에 Vue 인스턴스 내에 선언된 값을 그대로 다시 사용하게 된다.

  • computed : 반응형 getter

    computed의 Property가 정의될때 내부적으로는 Object.defineProperty를 통해 정의되며, 이때 익명함수가 getter로 설정된다.

    1. 함수가 아니라 일반 객체처럼 사용할 수 있고,
    2. 호출될때만 계산이 이루어지며,
    3. 계산결과가 캐싱되는 특성이 있다. 값이 변해도 캐싱 때매 변경된 값을 인지하지 못하는 단점이 있다.

    ⇒ getter의 특성(methods와 차이가 있다.).

⇒ computed가 새 프로퍼티를 생성하고 그것의 getter 로 익명함수를 설정되는 것과는 달리, watch는 아무 프로퍼티도 생성하지 않고 익명함수는 단순히 콜백함수로의 역할을 한다.

⇒ computed는 이미 정의된 계산 식에 따라 결과 값을 반환할 때 사용되며, watch는 어떤 특정 조건에서 함수를 실행시키기 위한 트리거 로서 사용할 수 있다.

 

 

참고 object watch 할 때, 내부 값이 변했는지 여부

    timeUnit: {
     handler(val){
       this.inputValue = val.value;
     },
     deep: true

 


v-if vs v-show, v-for

v-if는 v-show와 같이 특정 html 요소를 보이거나 감추는 역할을 한다. 두 디렉티브의 차이는 DOM을 만드는지 여부에 달려 있는데, v-if는 아예 DOM 요소를 만들어내지 않고, v-show는 DOM 요소를 만들되 display:none 효과를 가져온다.

즉, v-if는 조건에 따라 컴포넌트가 실제로 제거되고 생성되고,

반면에 v-show 는 단순히 css 의 display 속성만 변경된다

  • v-for과 v-if 같이 사용 시 v-for이 더 높은 우선순위를 가진다.
  • Vue의 v-for 동작 방식
    • 렌더링 된 엘리먼트 목록을 갱신할 때 기본적으로 in-place patch 전략을 사용한다. 이 것은 데이터 항목의 순서가 변경된 경우, 항목의 순서와 일치하도록 DOM 요소를 이동하는 대신 Vue가 각 요소를 적절한 위치에 패치하고 해당 인덱스에서 렌더링할 내용을 반영하는지 확인하는 것이다.
    • (여기서는 필요 없겠지만??) Vue에서 개별 DOM 노드들을 추적하고 기존 엘리먼트를 재사용/재정렬하기 위해서는 v-for의 각 항목들에 고유한 key 속성을 제공해야 한다. key속성은 v-bind를 사용하여 동적 값에 바인딩 한다.
    • 반복되는 DOM 내용이 단순한 경우나 의도적인 성능 향상을 위해 기본 동작에 의존하지 않는 경우를 제외하면, 가능하면 언제나 v-for에 key를 추가하는 것이 좋다고 한다. (key 값은 primitive 속성인 것을 사용하도록)
  • 편의를 위해서, v-bind를 생략 할 수 있다. 그냥 콜론 뒤에 속성의 이름만 넣어 주면 됨

    • 예) v-bind:key ⇒ :key

 

v-for는 v-if 보다 더 높은 우선순위를 가지고 있기 때문에 두 디렉티브를 같이 사용하는 방법은 추천하지 않는다고 한다. 일반적으로 두 디렉티브를 같이 쓰고 싶을 경우는 조건부 필터링을 하고싶을 때 이다. 굳이 v-if을 사용하고싶다면 아래 두 방법을 사용하면 된다.

//1. 상위나 하위에 n
<ul v-if="shouldShowUsers">
  <li
    v-for="user in users"
    :key="user.id"
  >
    {{ user.name }}
  <li>
</ul>

Webpack

대규모 응용 프로그램 같은 경우에는 js모듈이 많기 때문에 대부분 module bundler 라는 것을 이용한다고 한다. 모듈 번들러는 웹 애플리케이션을 구성하는 자원(HTML, CSS, Javscript, Images 등)을 모두 각각의 모듈로 보고 이를 조합해서 병합된 하나의 결과물을 만드는 도구를 의미함... NPM으로 vue를 땡겨서 webpack 같은 걸로 관리하게 되는데, Vue CLI로 가져오게 되면 이런 것 크게 신경 쓸 것 없이 미리 다 세팅이 되어 있다고 함. 그리고 개발 시에 핫 리로드, lint-on-save 이런 기능도 설정이 되어 있다고 한다. 이게 뭔지는 나중에 알아보고... webpack 같은 모듈 번들러만 쓰는 경우에는 특별히 세팅 하지 않으면 빌드 후에 app.js 와 같이 모든 js가 하나의 파일로 묶이는데 이게 용량이 금방 늘어 난다고 한다. (chunk로 split 해주지 않으면)

웹팩은 entry로 설정된 시작점에서 의존성을 가진 모든 파일을 압축하여 output 지점에 하나의 자바스크립트 파일을 만들어 준다. 이때, 자바스크립트가 아닌 파일은 loaders를 이용하여 자바스크립트에서 이용가능한 모듈로 만들어 주며, plugins를 이용하여 번들된 자바스크립트를 난독화하거나 특정 텍스트를 추출하는 역할을 합니다. mode는 웹팩의 사용 목적에 따라 설정을 지정하는 역할을 합니다.

 

+추가)

웹팩은 모든 파일을 모듈로 바라본다. 자바스크립트로 만든 모듈 뿐만아니라 스타일시트, 이미지, 폰트까지도 전부 모듈로 보기 때문에 import 구문을 사용하면 자바스크립트 코드 안으로 가져올 수 있다.

이것이 가능한 이유는 웹팩의 로더 덕분이다. 로더는 타입스크립트 같은 다른 언어를 자바스크립트 문법으로 변환해 주거나 이미지를 data URL 형식의 문자열로 변환한다. 뿐만아니라 CSS 파일을 자바스크립트에서 직접 로딩할수 있도록 해준다.

 

  • 자바스크립트의 변수 유효 범위는 기본적으로 전역 범위를 갖는다...
  • 그래서 복잡한 애플리케이션을 개발할 때에는 모듈화가 필요하고 이를 위해 웹팩을 사용한다.
  • https://babeljs.io/docs/en/learn#modules: ES modules 문법
  • 웹팩은 기본적으로 필요한 자원은 미리 로딩 하는게 아니라 그 때 그 때 요청하자 → Lazy Loading

 

c.f. webpack-dev-server (서버 구성은 Node.js 환경 위에 Express 서버 프레임워크가 올라간 형태)

localhost의 8080 포트로 개발서버를 실행하게 된다. 브라우저로 http://localhost:8080 요청을 보내면, HTML, JavaScript, CSS 를 응답으로 받고 자바스크립트가 index.html 의 <div id="app"></div> 부분에 vue 컴포넌트를 동적으로 그려 준다.

웹팩 데브 서버로 빌드한 결과물은 메모리에 저장되고 파일로 생성하지는 않기 때문에 컴퓨터 내부적으로는 접근할 수 있지만 사람이 직접 눈으로 보고 파일을 조작할 순 없다. ⇒ 괜히 dist 폴더에 뭐가 안생기는지 찾았네...

암튼 그래서 컴퓨터 구조 관점에서 파일 입/출력보다 메모리 입출력이 더 빠르고 컴퓨터 자원이 덜 소모된다.


NPM 지역 설치 - dev 환경

# 개발용 라이브러리와 배포용 라이브러리 구분하기

npm install jquery --save-dev

// 결과 //
// package.json
{
  "devDependencies": {
    "jquery": "^3.4.1"
  }
}

배포용 라이브러리는 npm run build로 빌드를 하면 최종 애플리케이션 코드 안에 포함된다. 반대로 설치 옵션에 -D를 주었다면 해당 라이브러리는 빌드 하고 배포할 때 애플리케이션 코드에서 빠지게 된다.

배포할 때는 빠져도 좋은 라이브러리의 예시

  • webpack : 빌드 도구
  • eslint : 코드 문법 검사 도구
  • imagemin : 이미지 압축 도구
// npm custom 명령어
"scripts": {
  "dev": "node server.js",
  "build": "webpack --mode=none",
}

이렇게 정의해두면 npm run dev 할 경우 node server.js 이 실행된다.

커스텀 명령어에는 실행 옵션 같은것도 추가해서 정의해 둘 수 있음

 


new Vue vs export default?

vue 파일에서 const 변수 = new Vue 이런식으로 인스턴스를 정의 했을 땐 안되었는데..

모든 vue 파일에서 export default 으로 정의하니까 됐다.

두 방식의 가장 큰 차이점은 export default는 ES6의 modules 구문이라는 점이다.

기존의 ES5 방식은 변수에 컴포넌트 내용을 넣어 인스턴스 안에서 참조하는 방식이고,

같은 파일 내에 변수를 선언했기 때문에 그냥 일반 js 값을 참조하듯 참조할 수 있다.

export default는 다른 파일의 있는 내용을 참조 해 오기 위한 방식이다.

1. new Vue

new Vue({
    el: '#app',
    data () {
      return {}
    }
)}

usually a sub-root root instance of the rest of the application. This breaks the root element declared in the html document

→ 즉, 아래와 같은 형태가 된다.

<html>
  ...
  <body>
    <div id="app"></div>
  </body>
</html>

 

2. export default

export default {
    name: 'my-component',
    data () {
      return {}
    }
}

⇒ 결론

Whenever you work on the.vue file, you use the export default {} syntax

but if not, if you are using Vue in a regular HTML file

  • main.js doesn't matter whether you create a root instance from the HTML document itself or an external file (i.e. an external file)
  • .vue Files always export default { ... }use syntax.

refs 속성

$refs 속성을 이용해 DOM에 접근이 가능하다

즉, JavaScript에서 자식 요소에 직접 접근할 때 사용한다. 이 경우, ref 속성을 이용해 자식 요소에 레퍼런스 ID를 할당하여 해결한다.

주의할 점은 $refs는 랜더링 된 후 값이 채워진다. 또한 $refs는 반응형이 아니라고 함.(즉, $refs가 변경 되어도 watch, computed 등으로 감지 하지 못함) 그렇기 때문에 template에서나 computed에서 $refs를 사용할 수 없다.

 

  • vue에서 포커스 주는 법
    • 포커스 될 input 태그에 ref 값을 설정하고 원하는 methods 에 this.$refs.설정값.focus() 입력

v-model

Vue에서 양방향 바인딩을 가능하게 한다.

  • 데이터 바인딩이란 VueJs의 binding expressions을 사용하여 script와 DOM간의 데이터를 주고받는 과정을 의미
  • 단방향 바인딩은 데이터를 화면에 출력
  • 양방향 바인딩은 화면에서 입력을 받아 데이터로 다시 전달하는 과정이 추가되어, 양쪽 방향 모두 바인딩 되는 것을 의미한다.

주의할 점

v-model은 value, checked, selected와 같은 어트리뷰트들을 깔끔히 무시하고, 오로지 vue 인스턴스의 data 속성을 유일하게 보기 떄문에, 초기값 설정을 꼭 해줘야 한다.

 

## v-bind vs v-model

input 엘리먼트에 v-model을 사용하여 Vue 인스턴스의 데이터를 바인딩하면 입력한 내용에 대해 모델 바인딩 바로 되지만, v-bind를 사용했을 경우 그렇지 못하기 때문에 $event.target.value를 사용하여 값을 가져와 oninput 이벤트에 데이터 값을 변경해준다.

 


=== vs ==

input이 null인지 확인하기 위해 ==를 사용했는데, ===를 쓰도록 하자...

또한, input이 비어 있는지 확인하기 위해서는 null 뿐만 아니라 ''와도 비교해야 한다.

  • == : Equality, 동등 연산자로, 피 연산자가 서로 다른 타입 이면 타입을 강제로 변환하여 비교한다.

0 == ''     //true
0 == '0'     //true
1 == true     //true
false == '0'    //true
null == undefined    //true
false == null    //false
false == undefined    //false
  • === : Identity, 일치 연산자로, 형 변환을 하지 않고 두 피 연산자를 더 정확하게 비교한다.

0 === ''     //false
0 === false    //false
1 === true     //false
NaN === NaN     //false
null === undefined     //false

 


mixin

다중 상속이나 재사용을 위해 구현한 인터페이스

믹스인을 통해 다른 컴포넌트들은 캡슐화된 기능을 사용할 수 있다. 결과적으로 같은 동작이지만, 서로 다른 실행을 통해 처리된다.

거의 기능을 선언하는 부분으로, js문법을 통해서 만들었다. (abstract class같은 느낌)

→ 혼자서는 암것도 못하고 다른 컴포넌트에게 mixin되서 사용된다.

 

- 동일한 이름의 함수가 선언될 때

var mixin = {
  methods: {
    foo: function () {
      console.log('foo')
    },
    conflicting: function () {
      console.log('from mixin')
    }
  }
}

var vm = new Vue({
  mixins: [mixin],
  methods: {
    bar: function () {
      console.log('bar')
    },
    conflicting: function () { 
      // => 오버라이딩(?)처럼 되어서 vm.conflicting을 할 경우 vm에서 정의된 함수가 호출된다.
      console.log('from self')
    }
  }
})

mixin은 편리하지만 mixin을 사용한 vue파일에 공통적으로 추가 됩니다. 이렇게 되면 동일한 코드가 반복되서 사용되는 문제가 있습니다. 만약 상수값을 공통적으로 사용하려고 mixin안에 담는다면 동일한 코드가 반복될것입니다. 그리고 내용의 크기가 크다면 더 좋지못한 영향을 끼치게 될것입니다. 상수를 효율적으로 처리하기위해선 상수를 관리하는 vueX를 사용하기를 권고합니다.

 


Javascript 변수 종류

  • var: es6 이전의 변수 선언 방식, 매우 유연한 방식으로 변수를 선언할 수 있는 방법이다.
    • 단점: 넘 유연해서 같은 변수를 두번 선언 해도, 잘 동작한다.
  • let: es6 이후에 추가됨, 값을 재정의 가능, scoped, 같은 변수를 두 번 선언하는 것은 불가
  • const: es6 이후에 추가됨, 상수 표현, scoped

⇒ var 보다는 let, const로 명확하게 표현하도록 하자!

 


axios

  • axios는 통신할 때만 쓰는 줄 알았는데, 데이터를 읽을 때도 쓸 수 있다는 걸 알았다. ⇒ 통신맞다.. webpack dev 서버를 쓰느라...
  • response 자체는 아래와 같이 생겼다. data 말고도 다양한 필드가 존재함 ⇒ 내부 폴더에 저장되어 있는 파일을 그냥 읽는 식이 아니고, dev server를 이용하여 get으로 가져온 것
  • 엄청 옛날에는... connection을 한 번 열릴 때마다 thread를 하나씩 만들어서 처리 했다고 한다. CPU가 여러 개의 쓰레드를 처리 하려면 컨택스트 스위칭이 일어나게 되는데, 이 컨택스트 스위칭이 일어나게 되면 속도 저하가 일어난다.
  • 이후에는 task 기반이라는 것이 나오는데, thread가 아닌 태스크라는 논리적인 단위를 만들어서 각 단위를 쓰레드마다 주게 된다. 이 방법은 쓰레드를 바꾸지 않기 때문에 컨택스트 스위칭 비용이 발생하지 않게 된다. ⇒ async/await 가 task 기반으로 돌아가는 것임
    • 즉, axync, await가 쓰레드를 만드는 것 보다는 속도 성능이 좋다.
    • 그치만 async도 오버헤드가 있긴 함...

⇒ 결과적으로는 웹 서버에 처리해 줄 수 있는 thread pool에 있는 task수와 request 수가 비슷하면 뭘 쓰든 성능이 비슷하다.

그런데, 만약 request 수가 많아지게 되면, async를 쓰게 되면 request를 실행하다가 잠깐 멈추고 다른 request를 실행하는 형식으로 왔다 갔다 동작하게 된다. (1개의 job이 빨리 끝나는 것은 아니지만, 모든 사람의 job이 모두 느리게 끝나진 않는다)

⇒ 그래서 웹 프론트에서 동기 방식을 쓰면 페이지가 안뜨는 건가 보다...

async를 안 해주게 되면, 뒤에 온 request는 앞에 온 request가 끝날 때까지 기다려야 한다. 그럼 이 처리를 할 때 어떤 것이 문제가 생겨서 걸리는 시간이 길어지게 된다면? 뒤에 기다리는 작업은 time out이 발생할 수 있다. ⇒ scalability가 중요하니까 쓰는거임

 

  • async/await, promise는 non-blocking 방식이다.
  • async/await는 비동기 코드의 겉모습과 동작을 좀 더 동기 코드와 유사하게 만들어준다. 이것이 async/await의 가장 큰 장점이다.

 

  • 콜백 함수: 어떤 이벤트가 발생한 후, 수행될 함수로, 아래는 주의할 점이다.
    • 콜백함수는 클로저이다.
      • 클로저는... 이미 생명 주기가 끝난 외부 함수의 변수를 참조하는 함수를 뜻한다. js는 함수형 언어이기 때문에 아래 코드와 같이 inner() 함수의 유효 범위(scope) 밖에서, 즉 outer() 내부에 존재하고 inner() 함수 외부에 존재하는 변수, 함수에 접근할 수 없지만, JS에서는 클로저를 통해 접근할 수 있으며 또한 값을 변경할 수도 있다.
function outer(){
	var x = 10;
	function inner(){
		x++; // 밖에 있는 x에 접근 가능
		console.log(x)
	};
	return inner;
}

 

  • 콜백함수 사용 시 this 객체에 유의해야 한다.
    • this는 뭐냐면... js의 경우 함수 호출 방식에 의해 this에 바인딩할 어떤 객체가 동적으로 결정된다. 다시 말해, 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정되는 것이 아니고, 함수를 호출할 때 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정된다.
    • 즉, 함수가 불러지기 위해 필요한?(접근해야 하는??) 대상이 this가 된다.
var person = {
    name: "victolee",
    email: "asdf@example.com",
    birth: "0225",
    foo : function(){
        console.log(this) // this == person 객체
    }
}
/*객체가 메서드를 호출할 경우, 메서드를 호출한 객체가 this이다.*/
person.foo() // foo() 함수를 실행하기 위해서는 person 객체의 foo 프로퍼티를 참조해야
// 즉, foo() 함수를 호출한 것은 person 객체이므로, this는 person 객체를 가르킵니다.
var x = 10;
function foo(){
    this.x = 20;
    x = 30;

    console.log(x);
    console.log(this.x);
    console.log(window.x);
}
/*일반 함수인 경우, 브라우저 상에서 window가 this이다.*/
foo() // 어떤 객체가 호출한 것이 아니기 때문에, this는 특정 객체를 가르키고 있지 않음
// 일반 함수일 경우에는 window 객체를 this로 갖고 있습니다.
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script
    src="https://code.jquery.com/jquery-3.2.1.min.js"
    integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
    crossorigin="anonymous"></script>
</head>
<body>
<button class="btn" value="foo">버튼</button>
</body>

<script>
		/*이벤트가 발생한 경우, 이벤트를 발생한 객체가 this이다.*/
    $(".btn").click(function(){ // 버튼 클릭 시 click 이벤트가 실행된다.
        console.log(this) // 이벤트가 발생했을 때는 이벤트가 발생한 객체가 this
    })
</script>
</html>

 

  • js는 this를 명시적으로 바인딩할 수 있는 apply, call, bind 메소드 를 제공한다... 이건 또 뭐냐면
    • vue.js, 즉 DOM에 한해서는 함수를 호출한 객체, 이벤트가 발생한 객체가 아니면 대부분의 this는 기본 값인 window가 된다. 명시적 바인딩 함수는 this를 조작 할 수 있는 메서드로서, 원하는 객체를 this로 할당하고 싶을 때 사용한다.
    • call()과 apply() 메서드의 차이
      • 함수를 호출할 때 this를 바꿔주는 기능은 같지만 매개변수로 인자들을 넘겨줌 → call
      • 배열을 넘겨 줌 → apply
var person = {
    name: "victolee",
    email: "asdf@example.com",
    birth: "0225",
    foo : function(val1, val2, val3){
        console.log(val1 + val2 + val3);
        console.log(this);
    }
}

person.foo.call(window, 3,6,9); // foo의 this 객체를 person에서 window로 변경
// 이렇게 되면 call() 메서드를 호출할 때 첫 번째 인자로 window 객체를 전달했으므로 this는 window 객체로 변경됨

배열 변수 렌더링?

boolean 배열로 변수를 정의하고 있을 경우, arr 요소 중에 boolean의 값을 바꿨을 경우, 재 렌더링을 하지 않아서 force update를 해 주었다.

이렇게 된 이유는 Vue는 data에 arr이 변경 되었을 경우에만 감지를 할 수 있는데, arr 안에 있는 bool의 값을 변경했기 때문에 arr의 주소 값은 변경 없이 그대로 이기 때문이다.

data에 바인딩 되어있는 속성의 주소 값이 변경 되어야만 Vue는 변화를 감지하고 re-rendering을 하게 된다..

 

bool의 값을 변경했을 때 다시 렌더링을 하고 싶다면 아래와 같은 방법을 쓸 수 있다.

let list = [...this.arr];
list.splice(0, 1, {first: 1, bool: false});
this.arr = list;

위와 같이 할 경우 arr에 새로운 배열이 할당되어 arr이 가리키는 주소 값이 변경되므로 Vue는 변화를 감지하여 re-rendering을 하게 된다.

 

또는 아예 객체로 만들어버린다.

 


vuex

  • vuex: Vue.js의 상태 관리 라이브러리로 애플리케이션의 모든 컴포넌트에 대한 중앙 집중식 저 역할을 하며 의도적인 방법으로 상태를 변경 및 관리할 수 있다. Vuex는 기존 Flux의 아키텍처를 따라가고 있다. Vue.js에서도 react의 Redux를 사용할 수 있지만 Vue.js는 Vuex와의 호환이 좋을 뿐만 아니라 더 직관적으로 개발할 수 있다.

  • flux 패턴: https://www.huskyhoochu.com/flux-architecture/

  • vuex의 구조

    • state

      Vue 컴포넌트에서 data같은 개념으로, 원본 소스의 역할을 하며, View와 직접적으로 연결되어있는 Model이다. 이 state는 직접적인 변경은 불가능하고 mutation을 통해서만 변경이 가능하다. mutation을 통해 state가 변경이 일어나면 반응적으로 View가 업데이트된다.

    • mutations

      Mutation은 state를 변경하는 유일한 방법이고 이벤트와 유사하다. mutation은 함수로 구현되며 첫 번째 인자는 state를 받을 수 있으며, 두 번째 인자는 payload를 받을 수 있다. 여기서 payload는 여러 필드를 포함할 수 있는 객체 형태도 가능하다. 이 mutation은 일반적으로(Helper를 쓰지 않는 경우)는 직접 호출을 할 수 없으며, commit을 통해서만 호출할 수 있다.

      대부분 실무에서는 mutations에서는 API를 통해 전달받은 데이터의 가공하여 state를 설정하는 데 많이 사용된다고 한다.

      store.commit('setData', payload)
    • action

      Action은 mutation과 비슷하지만 mutation과는 달리 비동기 작업이 가능하다. 또한 mutation에 대한 commit이 가능하여 action에서도 mutation을 통해 state를 변경할 수 있다. action에서는 첫 번째 인자를 context 인자로 받을 수 있으며 이 context에는 state, commit, dispatch, rootstate와 같은 속성들을 포함한다. 두 번째 인자는 mutation과 동일하게 payload로 받을 수 있다.

      commit을 통해 mutation을 호출했다면 Action은 dispatch를 통해서 호출한다. context의 속성을 보면 dispatch가 있는 것으로 보아 action에서는 서로 다른 action을 호출할 수 있다는 것을 볼 수 있다.

      실무에서 actions은 Axios를 통한 API 호출과 그 결과에 대해서 반환(return)을 하거나 mutation으로 commit하여 상태를 변경하는 용도로 사용된다고 한다.

      store.dispatch('setData', payload)
    • getters

      Getters는 쉽게 Vue 컴포넌트에서 Computed로 볼 수 있다. 말로 풀자면 계산된 속성인데 getter의 결과는 종속성에 따라 캐시 되고 일부 종속성이 변경된 경우에만 다시 재계산된다. 즉, 특정 state에 대해 어떠한 연산을 하고 그 결과를 View에 바인딩할 수 있으며, state의 변경 여부에 따라 getter는 재계산이 되고 View 역시 업데이트를 일으킨다. 이때 state는 원본 데이터로서 변경이 일어나지 않는다.

      실무에서도 state의 연산 처리가 필요한 내용에 대해 getter를 사용하지만 getters의 경우 대용량 처리 시에 퍼포먼스와 연관이 되어있으므로 조심해야 한다. 대용량 처리에 관련해서는[Vue.JS] 대용량 데이터의 처리 방법과 성능 최적화 방법 (Vue.js Performance) 를 참고하자.


한글 바인딩 문제

인풋 창에서 한글입력 시 이벤트가 한템포 늦게 동작하는 경우가 발생한다. 한글이 2byte로 되어있기 때문에

이런문제가 생기는데 제대로 업데이트되기 위해서는 v-model대신 input directive를 사용하라고 명시되어 있다.

<input type="email" v-model="userId" />
<!-- 위 코드를 아래처럼 바꾸도록 한다. -->
<input class="user-email" type="email" @input="userId = $event.target.value" />

이벤트 버블링

이벤트 버블링은 하나의 div속에 여러 이벤트가 겹겹이 있을 경우에 일어난다. 나의 경우에서는 가장 위에 있는 div focus, blur 만 호출되지만, click의 경우에는 click이 호출 되고 나서 focus/blur가 또 호출된다.

즉, 의도하지 않더라고 안에서 부터 밖까지 차례대로 호출되게 된다. 이를 막기 위해서는 .self 를 통해 자신이 만든 이벤트가 아니라면 실행되지 않도록 할 수 있다.

  • 이것을 바꾼 뒤에도 focus때문에 click이 진행되지 않는 문제점이 있었다. 이를 해결하기 위해서는
  1. focusout에 timeout
  2. event의 순서를 변경
  3. 마우스의 위치 이벤트 이용
  4. click 대신 mousedown을 쓰는 방법이 있었다.

컴포넌트간 통신 방법

  • Vue에서 데이터를 전달하는 방식

    https://question0.tistory.com/20 참고

    1. this.$root 혹은 this.$parent 를 이용: 제일 쉬운 방법이지만 프로젝트가 작고 상관없으나 프로젝트가 커지게 되면 이를 이용한 수정을 했을 때, 이벤트 추적이 힘들어질 수 있을 수 있다.
    2. v-bind 와 props, v-on 이벤트와 $emit 를 이용: 인과 관계가 명확하게 되므로 프로젝트가 커지더라도 이벤트의 추적이 용이해진다.
      • v-bind + props : 상위 컴포넌트에서 하위 컴포넌트로의 데이터 전달
      • v-on + $emit : 하위 컴포넌트에서 상위 컴포넌트로 데이터 전달
    3. v-model 를 이용
      • 상위 컴포넌트에서 하위 컴포넌트를 설정할때 속성이 v-model 하나로 축소
      • 하위 컴포넌트에서 model 속성 객체를 추가하여 설정
    4. EventBus 를 이용: 가장 일반적인 방법인 줄 알았는데, 자주 사용하게 되면 나중에 이벤트를 추적 관리하기 힘들어 진다고 함
    5. vuex store으로 공통 객체 이용: vuex 를 이용하는 방법은 글로벌한 공통 상태 값을 관리하기에 적합하지만 한정된 컴포넌트 간의 통신에는 부적합하다.

 

+ Recent posts