그날 그날

김승우·2021년 3월 3일
0

TIL

목록 보기
68/68

😎 2021.03.03

1. '/browse/movie?with_genres=12&page=1' 경로에서 라우터 링크를 통해서 '/browse/movie'로 이동했을 때,

데이터를 호출하지 않았다.

이유 : 최초 '/browse/movie'로 이동하면, MoviePage 컴포넌트가 생성되고, created() 훅에 있는 fetchData 함수가 실행되어서 데이터를 가져온다.
하지만, 라우터 링크를 클릭해서 다시 기존 경로로 이동하면, 컴포넌트가 생성되어 있으므로 created 훅이 실행되지 않고, 데이터를 로드하지 않는다.

해결책 : watch에서 route의 변화를 감지하는 방법이 있다.

2. router.push, router.replace의 결과가 실패할 경우 .catch() 문을 통해서 에러를 감지할 수 있다.

참고 링크 : https://router.vuejs.org/guide/advanced/navigation-failures.html#detecting-navigation-failures

3. vue props 속성에 여러개의 type 설정하기

: https://stackoverflow.com/questions/53608244/how-to-add-multiple-data-types-for-vuejs-props

props: {
type: [Number, String, Array]
}

4. hasOwnProperty를 쓰는 이유

참고 링크 : https://mygumi.tistory.com/330
: 프로토타입이 아닌 해당 객체 자체가 가지고 있는 속성을 가지고 판단한다.


😎 2021.03.08

1. 객체의 속성 제거하기

: delete 연산자를 사용해서 제거한다.
: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/delete

const person = {
	name: 'sam',
  	age: 12,
}

// age 속성 제거
delete person.age;

😜 2021.03.12

✨✨ 이벤트 버블링과 캡쳐링

: https://ko.javascript.info/bubbling-and-capturing

✨✨ label을 클릭할 경우 연결되어 있는 input에 클릭 이벤트가 발생한다!

=> input에 click 이벤트 핸들러를 적용하면 label을 클릭할때 발생한 클릭이벤트를 핸들링 할 수 있다.

✨✨ window.history

1. history.replaceState();

2. history.pushState();

3. vue $data 보존(히스토리 보존) 구현 방법

=> history.replaceState(this.$data, null, 현재 경로)를 이용해서 history.state에 현재 데이터들을 받고,

페이지를 로드했을때 state가 있는지 검사, 있으면 $data에 state안에있는 데이터를 합쳐준다.

=> 따라서 history가 있다면, API를 호출하지 않고, 이전에 있는 데이터를 그대로 보존할 수 있도록 created 훅에서 분기처리가 필요하다.

URL 이동

// URL 이동
goURL(url) {
	window.location.href = url;
},

✨✨ IR 기법

: https://nuli.navercorp.com/community/article/1132804

: https://www.boostcourse.org/web344/lecture/47663?isDesc=false

: https://haneunbi.github.io/2020/06/01/css-ir/

.blind {
    /* 레이아웃에 영향을 끼치지 않도록 */
    position: absolute;

    /* 스크린 리더가 읽을 수 있도록 */
    width: 1px;
    height: 1px;

    /* 눈에 보이는 부분을 제거 */
    clip: rect(0 0 0 0);
    margin: -1px;
    overflow: hidden;
}

.visually-hidden { 
    border: 0;
    padding: 0;
    margin: 0;
    position: absolute !important;
    height: 1px; 
    width: 1px;
    overflow: hidden;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
    clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
    clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
    white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}

.sr-only {
    position: absolute; /* position: absolute/fixed 에서만 clip 속성 작동 */
    margin: -1px; /* 부트스트랩에선 안씀 */
    width: 1px;
    height: 1px;
    padding: 0;
    border: 0;
    white-space: nowrap;
    overflow: hidden; /* overflow: visible 이면 clip 속성 작동 안됨 */
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%); /* H5BP에선 안씀 */
}

a 태그 안에 button 태그를 넣을 수 있나?

: 없다!
: https://stackoverflow.com/questions/6393827/can-i-nest-a-button-element-inside-an-a-using-html5

counter-increment: list-number;

자바 서버 구동시 : port already in use error 해결하기

: https://stackoverflow.com/questions/34253779/tomcat-server-error-port-8080-already-in-use

jQuery.load(path, function) => html 파일을 가져오고, callback을 실행시킨다.

✨✨✨✨✨✨✨ tryCatch, throw new Error를 이용한 에러 캐치 방법!

// 매장 리스트 조회
async fetchStoreList() {
   try {
      // this.fetches.storeList = false;

      const response = await this.$store.dispatch("network/request", {
         method: "post",
         url: '/store/shop/getShopList',
         data: {
            areaType: '',
            searchText: '',
            page: '',
            limit: '',
         },
      });

      const _data = response.data;

      if(response.code == CODE.SUCCESS) {
         console.log(response, _data, 'fetchStoreList');
      } else {
         // throw를 통해 에러를 발생시킴
         throw new Error(response.message);
      }
   }
   catch(ex) {
      console.error("fetchAvailableStores error...", ex.message); // response.message가 나온다!
   } finally {
      // this.fetches.storeList = true;
   }
}

참고 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Control_flow_and_error_handling
=> try...catch 문법 중첩하기 탭 확인!!!

✨✨ throw로 객체 던지는 방법 => catch 에서 잡을 수 있음!

throw {
  code: response.code, 
  message: response.message, 
  data: response.data
}

에러 처리

  1. API 호출 함수 안에서 > API 결과 => 원하는 결과가 아닐 경우 => throw로 에러 강제 발생

=> 해당 함수의 catch 문에서 다시 에러를 throw

  1. 함수를 호출하는 곳에서 > tryCatch를 통해 에러 감지

=> catch문에서 에러를 캐치

=> throw 한 객체에서 원하는 데이터를 뽑아내서 에러 핸들링!

=> 얼럿을 띄운다거나.. 로그를 찍는다던가..

=> 에러 핸들링 함수에 해당 에러 객체를 전달하는것이 효과적! switch case문!!

vue true-value, false-value

: https://server0.tistory.com/57


😜 2021.03.14

switch case 문

Vue 컴포넌트에게 props 객체 형태로 한번에 전달하기

참고 링크: https://kr.vuejs.org/v2/guide/components-props.html#%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8%EC%9D%98-%EC%86%8D%EC%84%B1-Properties-%EC%A0%84%EB%8B%AC

Vue 컴포넌트 재사용

참고 링크: https://jeonghwan-kim.github.io/2018/05/12/extended-component.html

Event.isTrusted

: https://developer.mozilla.org/ko/docs/Web/API/Event/isTrusted
: 사용자에 의해 발생했는지 여부 체크
: 사용자에 의해 발생했으면 true, 아니면 false;


😜 2021.03.15

1. Vue input radio v-model에 대한 이해

참고 링크: https://stackoverflow.com/questions/34865348/vuejs-set-a-radio-button-checked-if-statement-is-true/34865436

  1. v-model과 vue 인스턴스의 data가 같으면 checked된 상태로 나타난다.
  2. v-model로 연결된 뷰 컴포넌트 프로퍼티는 input의 value값을 갖게된다.

2. javascript get viewport width and height

참고 링크: https://stackoverflow.com/questions/1248081/how-to-get-the-browser-viewport-dimensions

const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)

😜 2021.03.16

1. Vuex Store 인스턴스에 모듈 등록하기

Vue.use(Vuex);


const requireModule = require.context(
    ".",
    true,
    /^((?!\.unit\.).)*.index\.js$/
);

const rootModule = { modules: {} };

requireModule.keys().forEach(fileName => {

    if (fileName === "./index.js") return;


    const modulePath = fileName
        .replace(/^\.\//, "")
        .replace(/\.\w+$/, "")
        .split(/\//)[0];


    rootModule.modules[modulePath] = requireModule(fileName).default;
});


export default new Vuex.Store({
    modules: {
        ...rootModule.modules,

    },

2. 폼 데이터 만들어서 axios data 속성에 전달하기

=> ✨ axios 게시판으로 옮기기

const form = new FormData();

form.append('id', 'id');
form.append('password', 'password');


const convert = await axios({ 
    method: 'post', 
    url: '',
    headers: { 'content-type': 'application/x-www-form-urlencoded' },
    data : form

});

3. Vuex를 바인딩하는 4가지 방법

=> ✨ Vue 게시판으로 옮기기
: https://kdydesign.github.io/2019/04/06/vuejs-vuex-helper/

4. Vue lay-out 만드는 아이디어? Slot의 활용

=> ✨ Vue 게시판으로 옮기기

<template>
    <main>
        <header-component></header-component>
        <lnb-component></lnb-component>
        <gnb-component></gnb-component>
        <section class="content">
            <slot name="content"></slot>
        </section>
        <footer-component></footer-component>
    </main>
</template>

//some.vue
<template>
    <div>
        <lay-out>
            <tmeplate slot="content">
            </template>
        </lay-out>
    </div>
</template>

5. Node.contains(node)

: https://developer.mozilla.org/ko/docs/Web/API/Node/contains
: 노드가 특정 노드를 포함하고 있는지 여부를 판단
(return true/false)

6. Vue 사용자 지정 디렉티브를 이용한 모달 바깥 클릭 이벤트

=> ✨ Vue 게시판으로 옮기기

- 참고한 소스

: https://stackoverflow.com/questions/36170425/detect-click-outside-element

Vue.directive('click-outside', {
  bind: function (el, binding, vnode) {
    el.clickOutsideEvent = function (event) {
      // here I check that click was outside the el and his children
      if (!(el == event.target || el.contains(event.target))) {
        // and if it did, call method provided in attribute value
        vnode.context[binding.expression](event);
      }
    };
    document.body.addEventListener('click', el.clickOutsideEvent)
  },
  unbind: function (el) {
    document.body.removeEventListener('click', el.clickOutsideEvent)
  },
});

- 내가 구현한 방식

<div v-click-outside="onClickOutSide"></div>
// directives
directives: {
    'click-outside': {
        bind: function (el, binding, vnode) {
            el.clickOutsideEvent = function (event) {
                if (!(el == event.target || el.contains(event.target))) {
                    vnode.context[binding.expression](event);
                }
            };

            // 바인드되고 그 다음 사이클에 적용!
            // https://developer.mozilla.org/ko/docs/Web/API/Window/requestAnimationFrame
            // * requestAnimationFrame()을 사용하지 않았을 경우에는 달력 컴포넌트가 생기는 즉시 클릭 이벤트가 발생해서 모달이 닫혀버렸다.
            window.requestAnimationFrame(() => {
                document.body.addEventListener('click', el.clickOutsideEvent);
            });
        },
        unbind: function (el) {
            document.body.removeEventListener('click', el.clickOutsideEvent);
        },
    }
}

😎 2021.03.17

✨(JS) 페이지에서 필수적으로 부르는 API 호출이 끝났는지 여부를 체크, 플래그 변수를 통해 판단.

: isPageLoaded라는 변수를 초기값을 false로 세팅한다.
페이지에서 필수적으로 호출하는 API가 모두 로드되면, isPageLoaded의 값을 true로 변경한다.
특정 함수에서 이 값이 false인지를 체크해서 동작을 제어한다.


😎 2021.03.19

focus된 엘리먼트 찾기

: document.activeElement
: https://stackoverflow.com/questions/497094/how-do-i-find-out-which-dom-element-has-the-focus

정규식

// 이미지 prefix 교체
replaceGoodsImageUrl(url = '', size = 'default') {
    if( !url ) return '';
    let resultUrl = '';

    // 숫자3개 + _, 숫자2개 + _로 시작하는 문자열 검사
    const regex = /(^\d{3}\_|^\d{2}\_)/;
    const image_sizes = {
        small: '75_',
        default: '216_',
        middle: '320_',
    };

    const prefix = image_sizes[size];

    // 찾은 사이즈가 있을 경우
    if( prefix ) {
        if( regex.test(url) ) {
        // prefix 있을 경우
            resultUrl = url.replace(regex, prefix);
        } else {
            // 없을 경우
            resultUrl = prefix + url;
        }
    } 
    else {
        // 없을 경우

        if( regex.test(url) ) {
        // prefix 있을 경우
            resultUrl = url.replace(regex, '');
        } else {
            // 없을 경우
            resultUrl = url;
        }
    }

    return resultUrl;
},

beforeunload

: https://developer.mozilla.org/ko/docs/Web/API/Window/beforeunload_event

countdown without setInterval

: https://gist.github.com/VassilisPallas/edc38a3e9489042e86c413241c0d9819


2021.03.27

정규식 test 메소드

: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test

return true/false

String.replace();

: 특정 문자열을 변환한 새로운 문자열을 반환한다.

Vue $refs

  1. 배열인 경우 : v-for안에서 사용했을 경우

  2. 단일 데이터인 경우 : 그 외의 케이스

Vue <keep-alive>와 <component>

: 이거 되게 신기

Event Emitter

: https://betterprogramming.pub/how-to-create-your-own-event-emitter-in-javascript-fbd5db2447c4

이벤트 등록 및 사용 방식..

addEventListener(name, cb) {
    if(this.#has.call(this.#events, name)) this.#events[name].push(cb);
    else this.#events[name] = [cb];
}

eventCall(name) {
    switch(name) {
        case "timer":
            if(this.#has.call(this.#events, name)) {
                for(let cb of this.#events[name]) {
                    /**
                     * @callback fbTimerTimerCallback
                     * @param {number} timestamp
                     */
                    cb(this.timestamp);
                }
            }
        break;
        case "completed":
            if(this.#has.call(this.#events, name)) {
                for(let cb of this.#events[name]) {
                    /**
                     * @callback fbTimerCompletedCallback
                     * @param {boolean} isCompleted
                     */
                    cb(true);
                }
            }
        break;
    }
}

😊 2021.03.29

1. Create Custom Event Emitter

링크 : https://betterprogramming.pub/how-to-create-your-own-event-emitter-in-javascript-fbd5db2447c4

2. Try Catch와 에러 핸들링

링크 : https://ko.javascript.info/try-catch

3. 상태관리

링크 : https://joshua1988.github.io/vue-camp/vuex/concept.html#%EB%B7%B0%EC%97%91%EC%8A%A4-%EC%86%8C%EA%B0%9C

3.1 Vuex 모듈에 있는 getters 사용하기

    return this.$store.getters["모듈명/getters 속성 명"];

4. 카카오 지도API

공식 문서 : https://apis.map.kakao.com/web/documentation/#Marker
samples: https://apis.map.kakao.com/web/sample/basicMap/

4.1 kakao.maps.load(callback) => 스크립트가 동적으로 로드된 후에 실행되도록
참고 : https://navydoc.tistory.com/21

4.2 확대 축소 이벤트
: https://apis.map.kakao.com/web/sample/addMapZoomChangedEvent/

4.3 오버레이

4.4 지도/스카이뷰
: https://apis.map.kakao.com/web/sample/addMapControl/

4.5 마커 클릭 시 인포윈도우 예제
: https://apis.map.kakao.com/web/sample/addMarkerClickEvent/

  • 카카오 지도 API를 하면서
    : 카카오 map을 생성하기 위해서 container를 넘겨야 하는데, ref로 지정한 엘리먼트를 찾지 못해서 에러가 발생.
    : mounted훅 혹은 v-if로 조건이 걸려있는 경우 해당 영역이 완전히 렌더링된 이후에 실행해야함.

  • 스크립트를 동적으로 불러올 경우
    : Promise를 이용해서 비동기 처리를 할 수 있다.

5. API 전용 스크립트 파일, 스토어를 이용한 공통 저장소, 컴포넌트에서는 스토어의 모듈을 불러오고 그 모듈안에있는 액션을 이용해서 데이터를 요청함.


😊 2021.03.31

(HTML) 1. figure 태그 안에서 a태그를 사용할 수 있다.

: https://stackoverflow.com/questions/28669852/can-a-figure-tag-contain-an-anchor-tag-wrapping-the-image

profile
사람들에게 좋은 경험을 선사하고 싶은 주니어 프론트엔드 개발자

0개의 댓글