레이블이 vue인 게시물을 표시합니다. 모든 게시물 표시
레이블이 vue인 게시물을 표시합니다. 모든 게시물 표시

vuex local storage 갱신

# vuex store 를 다음과이 read/write 하는데, 데이터 구조를 변경했다.
# vuex store 사용 예
# store.js
state : {
  # before
  # mydata : 1
  # after
  mydata : {
     val1: "ysoftman",
     val2: 123,
  }
  mutations: {
    changeMyData(state, playload) {
      state.mydata.val1 = payload.val1;
      state.mydata.val2 = payload.val2;
    },
}

# abc.vue
import { eventBus } from "@/main";
methods: { 
 setMydata() {
   this.$store.commit("changeMyData", {
     val1: this.data.aaa,
     val2: this.data.bbb,
   });
   eventBus.$emit("setMydata", this.data);
 }
}

# 로컬 테스트에는 변경된 데이터 구조로 read/write 해서 문제가 없었는데,
# 실제 패키징 후 배포된 서버에서는 기존 데이터 구조로 남아 있어 문제가 발생했다.
chrome -> devtools -> application -> storage -> local storage
https://ysoftman.com -> key -> vuex -> value {"mydata": 1}

https://ysoftman.com -> clear 로 데이터를 모두 삭제후 사용하면 된다.

vue axios 모든 요청에 헤더,파라메터 추가하기

# 프로젝트내 모든 axios 요청 또는 응답에 공통으로 추가할 데이터(파라메터가,헤더)가 있는 경우
# 각 axios 구문 마다 일일히 추가하는 대신 axios intercepter 를 활용할 수 있다.
# 공통 파라메터 값이 vuetify store 에 저장된 경우
# vue 인스턴스 내부에서 axios.interceptors 를 명시해놓아야 한다.

# 얘시
# src/store.js 가 있고
# src/rouster/index.js 에 다음과 같이 추가한다.

import { store } from '@/store';

// axios 모든 요청 보내기전에 수행
// Add a request interceptor
axios.interceptors.request.use(function (config) {
  // Do something before request is sent
  if (config.params == null) {
    config.params = {};
  }
  config.params['ysoftman1'] = store.state.mydata.value;
  config.headers['fruit1'] = "lemon";
  config.headers['fruit2'] = "apple";
  console.log("----- config:", config);
  return config;
}, function (error) {
  // Do something with request error
  return Promise.reject(error);
});

// axios 모든 응답 리턴전에 수행
// Add a response interceptor
axios.interceptors.response.use(function (response) {
  // Any status code that lie within the range of 2xx cause this function to trigger
  // Do something with response data
  return response;
}, function (error) {
  // Any status codes that falls outside the range of 2xx cause this function to trigger
  // Do something with response error
  return Promise.reject(error);
});


vue local devserver proxy

# 예시
# 현재 로컬 서버 http://localhost:8080
# 요청 서버 http://my.ysoftman.com:443

# 로컬에서 vue 개발시, 도메인이 다른 호스트 요청시 발생하는
# cors(Cross-origin resource sharing) 에러 해결을 위해
# vue.config.js (webpack) proxy 를 설정한다.
 
module.exports = {
  // 로컬 개발시(이 파일 수정시 npm run serve 로 다시 시작해야함)
  devServer: {
    https: true,
    // /api 로 시작하는 경로 요청을 target 으로 요청
    proxy: {
      '^/api': {
        target: 'https://my.ysoftman.com:443',
        changeOrigin: true,
      },
    disableHostCheck: true,
  },
};

# 위와 같이 프록시 설정하면, cors 이슈도 없고, 쿠키등의 헤더도 잘 전달된다.

# 주의사항
# xmlhttprequest, axios 등으로 요청 호스트명을 빼서 로컬 호스트로 요청해야 한다.
# 그래야 위 (로컬서버에 대한) 프록시 처리가 된다.


#####


# 만약 호스트명이 필요한 실제 서비스 환경과 로컬 develop 개발 환경 구분이 필요한 경우
# host 변수을 두고 다음과 같이 process.env.NODE_ENV 에 따라 '' 로 설정해 처리하자.

let host = "http://my.ysoftman.com:443"
if (process.env.NODE_ENV != null && process.env.NODE_ENV == 'development')
{
  return '';
}


vuetify upgrading from 1.x to 2.x

# vuetify 1.x -> 2.x 업그레이드 작업
# vuetify 최신버전(2.x) 및 sass 설치 : package.json 자동 변경
npm install --save vuetify@latest sass

# main.js 에서 vuetify 생성을 다음과 같이 변경
Vue.use(Vuetify);
const opts = {
  icons: {
    iconfont: 'md' || 'mdi'
  },
  theme: {
    themes: {
      light: {
        primary: '#01884e'
      }
    }
  }
};
new Vue({
  vuetify: new Vuetify(opts),
  // 기존 설정들...
});


##### 


# activator 는 다음과 같이 사용해야 한다.
<template v-slot:activator="{ on }">
    <v-btn v-on="on">...</v-btn>
</template>

# v-data-table 내의 aaa 필드값 재정의 하라면
# v-data-table 의 :headers 내의 value 이름이 
# :items 의 item내 필드명과 같아야 자동 렌더링이 된다.
# item 오브젝트를 destructuring 해서 aaa 필드인 경우 처리된다.
<template v-slot:item.aaa="{ item }"></template>

# v-list-group 에서 activator 는 자동으로 전달된다.
<v-list-item slot="activator"> -> <v-list-item>
<v-toolbar-title slot="activator">  -> <v-toolbar-title>


#####


# v-data-table 내에서 expanded row(아이템 아래에 확장 화면) 버튼 커스터마이징
# header 에 "data-table-expand" 이름의 값을 추가하고
headers : [
{
  text: "추가 정보",
  value: "data-table-expand",
}]
# v-data-table 내에서 다음과 같이 슬롯으로 expanded 관련 정보를 받아 처리한다.
<template v-slot:item.data-table-expand="{ item, isExpanded, expand }">
  <v-btn icon color="warning" @click="expand(true)" v-if="!isExpanded">expand</v-btn>
  <v-btn icon color="warning" @click="expand(false)" v-if="isExpanded">close</v-btn>
</template>


#####


# 컴포넌트들 이름 변경
<v-content> -> <v-main>
<v-toolbar app> -> <v-toolbar> # app 은 v-app-bar 컴포넌트를 사용해야 한다.
<v-toolbar-side-icon> -> <v-app-bar-nav-icon>
<v-list-tile> -> <v-list-item>
<v-list-tile-avatar> -> <v-list-item-avatar>
<v-list-tile-content> -> <v-list-item-content>
<v-list-tile-title> -> <v-list-item-title>
<v-list-tile-sub-title> -> <v-list-item-subtitle>
<v-data-table :rows-per-page-items> -> <v-data-table :footer-props="{'items-per-page-options':[-1]}"

# 이 밖에도 deprecated 되거나 사용방법등이 변경되는 경우 새로 UI를 구성해야 할 수 도 있다.
# 기타 자세한 내용 참고

set-cookie was blocked 에러

vue+go 로컬 개발시 서버 응답으로 다음과 같이 쿠키 설정 헤더값을 받았다.
set-cookie: jwt=xxxxx; Expires=Wed, 18 Nov 2020 08:12:17 GMT

그런데 쿠키가 설정되지 않는다.
크롬 개발자 도구 cookies 항목을 보면 다음과 같이 secure 부분에 알림 아이콘이 표시되고


마우스 오버하면 tooltip 메시지를 확인 할 수 있다.

This Set-Cookie was blocked because it was not sent over a secure connection and would have overwritten a
cookie with the Secure attribute.

이미 https://localhost 로 jwt 값이 있는게 원인이었다.

쿠키는 도메인에 따라 설정되지만 https 연결로 secure 속성을 가진다.
localhost 라는 도메인으로 jwt 쿠키가 있어 덮어쓰기를 시도하는데,
https 라 secure 하지 않는 http 연결에서의 set-cookie 는 허용되지 않는다.

해결방법1
기존 https://localhost 의 jwt 쿠키를 삭제

해결방법2
다른 쿠키명 사용
"github.com/dgrijalva/jwt-go" 를 사용해 쿠키명은 다르게 해도 된다.
("github.com/go-chi/jwtauth" 는 jwt 라는 쿠키명은 하드코딩되어 있다.)

# 참고

vue component 등록시 이름 에러

# vue 에서 컴포넌트 등록하기
# AppleLemonList 컴포넌트를 등록해서 사용하는 경우

# AppleLemonList.vue
export default {
  name: "applelemon-list",  // 사실 name 필드는 사용되지 않는다.
  components: {},
...


# MyComponent.vue
<template>
  <v-container fluid>
    <v-card>
      <component :is="currentComponent"></component>
    </v-card>
  </v-container>
</template>

import AppleLemonList from "@/components/AppleLemonList";

export default {
  name: "mycomponent",    // 사실 name 필드는 사용되지 않는다.
  components: {
    AppleLemonList
  },
  computed: {
    currentTabComponent: function() {
      return "applelemon-list"; // apple-lemon-list 이름을 사용해야 한다.
    }
  },
...


# 위 코드는 다음과 같은 에러가 발생한다.
vue.esm.js?efeb:628 [Vue warn]: Unknown custom element: <applelemon-list> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

# 원인 및 해결방법
# 우선 컴포넌트 이름은 kebab(케밥케이스)와 pascal(파스칼케이스)를 사용할 수 있는데
# 컴포넌트를 파스칼로 정했을때는 케밥, 파스칼로 호출할 수 있다.
# 케밥 이름 사용시 - 은 파스칼의 소문자->대문자로 바뀌는 부분에 명시해야 된다.
# 파일 이름 자체가 컴포넌트 이름이 되어 
# AppleLemonList.vue 는 AppleLemonList 파스칼 케이스가 컴포넌트 이름이 된다.
# 그리고 위의 컴포넌트 name 필드값은 사용되지 않는다.
# 결국 다음과 같이 케밥 이름을 사용해야 된다.
return "apple-lemon-list";


# 참고로 다음과 같이 로컬 컴포넌트 이름을 별도로 정해서 사용할 수도 있다.
export default {
  components: {
    'aaa-bbb-ccc' : AppleLemonList
  },
...



vuetify v-data-table server pagination 사용시 client side sort 문제

# vuetify 2.x v-data-table 를 
# server pagination(서버에서 특정 단위로 데이터를 주는 경우)로 사용했는데,
# 클라에서는 받은 데이터 내에서 sort(정렬)가 동작 하지 않는다.
# :server-items-length(전체 데이터 개수, 몇개의 페이지로 표시해야 할지 알기 위해 필요하다.)
# 속성을 제거하면 정렬 기능이 동작했다.

# stackoverflow 에 나와 같은 문제를 겪는 사람이 있었다.


# vuetify 입장은 server pagination 은 
# 서버에서 현재 페이지에 해당하는 일부 데이터만 받고
# 이 일부 데이터를 정렬 하는것은 쓸모 없다고 한다.

# 그래도 적은 일부 데이터 내에서라도 정렬 기능은 필요해 보이는데, 지원이 아쉽다.

vue https local test

# vue 로컬 테스트시
npm run serve

# webpack 설정으로 https, http2 기능을 사용해 띄울 수 있다.
https://webpack.js.org/configuration/dev-server/#devserverhttps
https://webpack.js.org/configuration/dev-server/#devserverhttp2
# http2 는 node 버전 10 부터 사용할 수 없고, express framework 에서 쓸 수 있다.
# vue.config.js 에 설정하면
module.exports = {
  //...
  devServer: {
    http2: true,
    https: true,

# http2, https 로 테스트 할 수 있다.
  App running at:
  - Local:   https://localhost:8080/

vuetify sidebar 사용시 횡스크롤 문제

# vuetify 로
# 위쪽은 v-toolbar 를 위치시키고
# 왼쪽에 v-navigation-drawer(sidebar)를 위치시키고
# 오른쪽에 v-data-table 을 위치하도록 구성했다.
# v-data-table 의 컬럼 개수가 많아
# 브라우저의 폭을 줄일때 맨 오른쪽 부분이 보이지 않는 문제가 발생했다.
# 원래 v-data-table 자체에서 횡스크롤이 가능하고
# 브라우저 폭이 일정 크기 아래로 줄어 들면
# breakpoint 로직이 작동해 아래쪽으로 컬럼이 적절하게 보여진다.
# 하지만 v-data-table 에서도 sidebar 폭만큼 오른쪽 더 스크롤 되지 않는다.
# 원인은 div 의 overflow css 속성이 안돼 발생한것으로
# scroll 또는 auto 로 명시해야 화면 횡스크롤이 된다.(이걸 몰라 계속 삽질ㅠ)
vi app.vue
<style>
/* toolbar, sidebar 는 고정하고 오른쪽 영역에서 화면 횡스크롤 하기 위한 css */
.top-view {
  position: fixed; /* 스크롤 해도 위치 고정 */
  width: 100%; /* 전체 너비 채우기 */
  z-index: 99; /* 같은 위치에 여러 엘리먼트가 위치할때 이 값이 클수록 앞쪽(위로 덮는)으로 온다. vuetify default z-index : 5 */
}
.body-view {
  display: flex; /* 모든 요소를 한줄에 표시 */
  margin-top: 50px; /* top-view 높이 감안해서 50px 만큼 아래에 위치 */
}
.left-view {
  display: flex; /* 모든 요소를 한줄에 표시 */
  position: fixed; /* 스크롤 해도 위치 고정 */
  height: 100%; /* sidebar 높이를 전체 채우기 */
}
.right-view {
  width: 100%; /* 오른쪽 영역의 폭을 전체 채우기 */
  overflow: auto; /* 또는 scroll 값, 횡스크롤 가능하도록 */
  margin-left: 100px; /* sidebar 폭 감안해서 100px 만큼 오른쪽에 위치 */
}
</style>
<template>
  <v-app>
    <div class="top-view>
      <ysoftmanToolbar />
    </div>
    <div class="body-view">
      <div class="left-view">
        <ysoftmanNavigation />
      </div>
      <div class="right-view">
        <ysoftmanDatatable />
      </div>
    </div>
  </v-app>
</template>

<script>
import ysoftmanToolbar from '@/components/ysoftmanToolbar';
import ysoftmanNavigation from '@/components/ysoftmanNavigation';
import ysoftmanDataTable from '@/components/ysoftmanDataTable';
export default {
  name: 'App',
  components: {
    ysoftmanToolbar,
    ysoftmanNavigation,
    ysoftmanDataTable,
  },
  data() {
    return {};
  },
};
</script>

vue object data 에 새 필드 추가시 변경 감지

# vue 는 data() 명시된 데이터들은 변경 감지(추적)해 자동으로 업데이트 한다.
# 아래와 같이 오브젝트 데이터의 경우 신규 필드를 추가시 일반 할당 연산을 사용하면
# 감지가 안돼 &set 을 사용해야 한다.
data() {
  ysoftmanObj : {
     a : '',
     b : 0,
  },
},

...

methods: {
  updateysoftmanObj() {
     // 신규 c 필드 추가시 set 을 사용해야 업데이트 된다.
     //this.ysoftmanObj.c = 'ysoftman',
     this.$set(ysoftmanObj, 'c', 'ysoftman');
  }
},

# 참고 https://vuejs.org/v2/guide/reactivity.html#For-Objects

vue list 에 추가하기

# v-data-table 템플릿에 데이터를 표시하고자 할때
# 참고 https://vuetifyjs.com/en/components/data-tables
<template>
<v-data-table :headers="headers" :items="items" :items-per-page="5" class="elevation-1"></v-data-table>
</template>

# 다음과 같이 item 리스트에 값을 추가할때 push 를 사용해야 한다.
export default {
  name: "ysoftman-list",
  data() {
    return {
      item: []
    }
  },
  methods: {
    getMyData() {
      axios
        .get("/api/mydata", {
          params: {
            id: "999"
          }
        })
        .then(response => {
          // this.items = response.data || [];
          // response.data = {"id":"a123", "field1": "aaa"}
          // 값은 추가되지만 v-data-table 에 표시되지 않는다.   
          // this.items[0] = response.data
          // push 를 사용하면 json 데이터의 getter setter 등의 함수도 같이 생성되어, v-data-table 에서 사용된다.
          // 참고 https://vuejsdevelopers.com/2017/03/05/vue-js-reactivity/
          this.items.push(response.data)
          console.log(this.items.length, this.items[0]);
        })
        .catch(error => {})
    },
  },
  // 컴포넌트가 마운트 될때
  mounted() {
    this.getMyData();
  }
}