SlideShare a Scribd company logo
1 of 83
Vue.js 기초 실습
한국폴리텍대학 스마트금융과
도입
source : https://www.appsdevpro.com/blog/vue-vs-react/
MVVM (Model, View, ViewModel)
View Model
View Model
DOM Listener
Data Binding
Javascript Object
준비물
IDE : VS Code 또는 ATOM, 기타
- VS Code : Volar extension 설치
크롬 : 개발자 도구와 Vue.js Extenstion (필요시)
Node.js (Install Node.js version 16.0 or higher)
Hello World
Vue 애플리케이션 만들기
https://ko.vuejs.org/guide/quick-start.html#creating-a-vue-application
index.html  main.js  App.vue
CDN에서 Vue 사용
https://codepen.io/vuejs-examples/pen/eYQpQEG
Vue = Component
App.vue
HelloWorld.vue
TheWelcome.vue
WelcomeItem.vue
WelcomeItem.vue
WelcomeItem.vue
WelcomeItem.vue
WelcomeItem.vue
Counter 예제 (1/3)
Counter 예제 (2/3)
Counter 예제 (3/3)
템플릿 문법 : v-bind
템플릿 문법 : Boolean 속성
템플릿 문법 : 여러 속성 바인딩
템플릿 문법 : JavaScript 표현식 사용
반응형 기초 : 반응형 상태 선언
Composition API에서 반응형 상태를 선언하는 권장 방법은 ref() 함수를 사용하는 것입니다:
컴포넌트가 처음 렌더링될 때, Vue는 렌더링 과정에서 사용된 모든 ref를 추적합니다. 나중에 ref가 변경되면, 이를 추적하는 컴포넌트
에 대해 재렌더링을 트리거합니다.
https://ko.vuejs.org/guide/essentials/reactivity-fundamentals.html#ref
반응형 기초 : reactive
 ref와 reactive 차이 알아보기
계산된 속성(computed)
계산된 속성(computed)
<script setup>
import { reactive, computed } from 'vue'
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery',
'Vue 5 - The Mystery',
'Vue 6 - The Mystery',
'Vue 7 - The Mystery'
]
})
// 계산된 ref
const publishedBooksMessage = computed(() => {
return author.books.length > 3 ? 'Yes' : 'No'
})
const funcBtn = (()=>{
author.books.pop()
})
</script>
<template>
<p>책을 많이 가지고 있다:</p>
<span>{{ publishedBooksMessage }}</span>
<p></p>
<button @click="funcBtn">버튼</button>
</template>
클래스와 스타일 바인딩
조건부 렌더링
리스트 렌더링
추가 실습 : https://ko.vuejs.org/guide/essentials/list.html
이벤트 핸들링
입력 바인딩
추가 실습 : https://ko.vuejs.org/guide/essentials/forms.html
라이프싸이클
Component 실습
실습 환경 구성
npm install -g @vue/cli
vue create vue-project2
cd vue-project2
npm run serve
컴포넌트
image: https://ko.vuejs.org/guide/essentials/component-basics.html
컴포넌트
App.vue
HelloWorld.vue
App.vue
HelloWorld.vue
컴포넌트 : props (1/3)
App.vue
HelloWorld.vue
App.vue
HelloWorld.vue
컴포넌트 : props (2/3)
부모 컴포넌트에서 버튼 클릭시,
부모 컴포넌트의 count 값을 자식 컴포넌트에 전달하고,
전달받은 값을 자식 컴포넌트 화면에 출력한다.
컴포넌트 : props (3/3)
App.vue
HelloWorld.vue
컴포넌트 : emit event (1/2)
App.vue
HelloWorld.vue
컴포넌트 : emit event (2/2)
1. Child Component에 버튼 추가하고, 버튼 클릭시 상위 컴포넌트에 메시지 전달
컴포넌트 : Slot
https://ko.vuejs.org/guide/essentials/component-basics.html#content-distribution-with-slots
Router
Router
Router
Kopo 라는 메뉴 만들고, 해당 메뉴 클릭시 Kopo 컴포넌트 호출하게 코드 추가하기
Axios
axios 설치 및 import
vue2 style 준비 (전역 설정)
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import axios from 'axios'
// createApp(App).use(router).mount('#app')
const app = createApp(App)
app.config.globalProperties.axios=axios
app.use(router).mount('#app')
main.js
vue2 style (사용)
사용하고자 하는 컴포넌트에서...
HelloWorld.vue
export default {
name: 'HelloWorld',
methods: {
testAxios() {
this.axios.
get('https://api.coindesk.com/v1/bpi/currentprice.json').
then(response => (console.log(response)))
},
btnclicked(){
this.testAxios();
}
}
}
vue3 style 준비 (전역 설정)
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import axios from 'axios'
// createApp(App).use(router).mount('#app')
const app = createApp(App)
app.provide('$axios', axios);
app.use(router).mount('#app')
main.js
vue3 style (사용)
사용하고자 하는 컴포넌트에서...
import { inject } from 'vue'
setup(props, ctx) {
const axios = inject('$axios');
function sendmymessage () {
ctx.emit('send-message',childmsg)
axios.
get('https://api.coindesk.com/v1/bpi/currentprice.json').
then(response => (console.log(response)))
}
return{
sendmymessage
}
}
HelloWorld.vue
CORS 관찰
CORS 관찰
만약에?
아마도, backend 응답 헤더에 아래와 같은 속성이 없을 수도?
CORS 조치
Vue 개발을 위한 조치 => Production 환경에서는 BackEnd 에서 조치가 필요
function sendmymessage () {
axios.
get('/v1/bpi/currentprice.json').
then(response => (console.log(response)))
const params = {
name: "morpheus",
job: "leader",
};
axios.post("/api/users",params,{}
).then((res)=>{
//성공했을경우
console.log("성공",res)
}).catch((res)=>{
//실패했을경우
console.error("실패",res)
})
}
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
proxy: {
'/v1': {
target: "https://api.coindesk.com",
changeOrigin: true
},
'/api': {
target: "https://reqres.in",
changeOrigin: true
}
}
}
})
vue.config.js
async await
Do you know 콜백지옥?
btnclicked(){
this.testAxios();
this.testAsync();
},
async testAsync() {
const resultValue = await this.requestPost();
this.requestGet(resultValue);
},
requestGet(arg) {
console.log(`[START] axios Get,
Call Back From Previos Axios Post = ${arg} `);
this.axios
.get(`https://reqres.in/api/users?/page=1`, {})
.then((res) => {
console.log("[END] axios Get ");
this.getData = res.data;
})
.catch((res) => {
console.error(res);
});
},
requestPost() {
const params = {
name: "morpheus",
job: "leader",
};
console.log("[START] axios Post");
return this.axios
.post(`https://reqres.in/api/users`, params, {})
.then((res) => {
console.log("[END] axios Post");
this.postData = res.data;
return "Success";
})
.catch((res) => {
console.error(res);
return "Failure";
});
},
},
Pinia
Pinia
Vue의 상태 관리 모듈
npm install pinia --save
https://pinia.vuejs.org/introduction.html
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import axios from 'axios'
import { createPinia } from 'pinia'
const app = createApp(App)
const pinia = createPinia()
app.config.globalProperties.axios=axios
app.provide('$axios', axios);
app.use(pinia)
app.use(router).mount('#app')
Pinia
폴더와 파일 생성
import { ref } from 'vue'
import { defineStore } from "pinia"
export const useCounterStore = defineStore('counter', () => {
const count = ref(1)
function increment() {
count.value++
console.log("increment called")
}
return { count, increment }
})
counter.js
Pinia
HelloWorld.vue
Pinia
HelloWorld.vue
실습
실습
https://github.com/wonyongHwang/vue3-todo.git
https://github.com/wonyongHwang/simple-todo-list.git
- localStorage 저장
- backend  database 저장
조별 실습 과제
Vue Project
- 화면 정의
- R&R, WBS, ...
설치
https://www.creative-tim.com/product/vue-material-kit
App.vue
router > index.js
로그인 예제 (준비)
setup() {
const myemail = ref('a@a.com')
const mypwd = ref('1234')
const refmyemail = ref(null);
function func_signin() {
console.log("sign in ",myemail,mypwd)
console.log(refmyemail._value.value)
}
onMounted(() => {
setMaterialInput();
})
return{
myemail,
mypwd,
func_signin,
refmyemail
}
},
로그인 예제 (v-model)
<div class="card-body">
<!-- submit.prevent added by hwy -->
<form role="form" class="text-start" @submit.prevent>
<!-- code modified by hwy -->
<div class="input-group input-group-outline my-3">
<input v-model="myemail" id="email" class="form-control form-control-md" type="email" ref="refmyemail"/>
</div>
<div class="input-group input-group-outline my-3">
<input v-model="mypwd" id="password" class="form-control form-control-md" type="password"/>
</div>
<div class="text-center">
<MaterialButton
class="my-4 mb-2"
variant="gradient"
color="success"
@click="func_signin"
fullWidth
>Sign in</MaterialButton>
</div>
로그인 예제 (결과확인)
로그인 예제 (ref 살펴보기)
setup() {
const refmyemail = ref(null);
function func_signin() {
console.log(refmyemail._value.value)
}
return{
func_signin,
refmyemail
}
<div class="input-group input-group-outline my-3">
<input v-model="myemail" id="email" class="form-control form-control-md"
type="email" ref="refmyemail"/>
</div>
로그인 예제 (axios 및 router 적용)
import { ref, inject } from 'vue'
import { useRouter } from 'vue-router'
setup() {
const $client = inject("$axios");
const router = useRouter()
async function func_signin() {
const resp = await $client.get("/api/delayHello");
if(resp.status == 200){
router.push('/')
}else{
}
}
rest call 정상 응답시 최상위 경로로 이동
 로그인 관련 Backend에서 응답 받은 정보의 저장 및 관리는?
분석
컴포넌트 배치 확인
그리드 시스템(부트스트랩)
https://getbootstrap.kr/docs/5.0/layout/grid/
PresentationView.vue
분석
분석
분석
PresentationView.vue
분석
PresentationView.vue
PresentationCounter.vue
DefaultCounterCard.vue
진행 방향
컴포넌트 구성도 작성
기획 & 화면 정의, R&R, WBS (교수와 협의)
* axios, pinia, mitt 등 활용
형상관리(Git)
빌드 및 실서버 배포
mitt
컴포넌트간 이벤트 전달
Vue2 : EventBus
Vue3 : mitt
npm install --save mitt
main.js
이벤트 발송
AboutView.vue
이벤트 수신
PresentationView.vue
결과 확인
AboutView.vue를 호출  이벤트 발송 (mount)  이벤트 수신
mock
준비
npm install axios-mock-adapter --save
npm install axios --save
main.js
mock 코드 준비
import MockAdapter from "axios-mock-adapter";
function parseQueryString(url) {
const queryString = url.replace(/.*?/, "");
const result = {};
if (queryString === url || !queryString) {
return result;
}
const urlParams = new URLSearchParams(queryString);
urlParams.forEach((val, key) => {
if (Object.prototype.hasOwnProperty.call(result, key)) {
result[key] = [result[key], val];
} else {
result[key] = val;
}
});
return result;
}
export default {
mocked(axiosClient) {
const mock = new MockAdapter(axiosClient, { onNoMatch: "passthrough" });
mock.onGet("/api/hello").reply(200, { hello: "world" });
mock.onGet(//api/hello2?.*/).reply((config) => {
const params = parseQueryString(config.url);
return [200, { config, params }];
});
mock.onPost("/api/formPost").reply((config) => {
//const formData = config.data;
const name = config.data.get("name");
return [200, { config, name: name }];
});
mock.onPost("/api/postJson").reply((config) => {
const data = JSON.parse(config.data);
return [200, { data }];
});
mock.onGet("/api/delayHello").reply((config) => {
const delay = 5000;
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([200, { hello: "world" }]);
}, delay);
});
});
}
};
mock.js
테스트
// mock
import { inject, reactive } from "vue";
const $client = inject("$axios");
const myModel = reactive({});
const btnClick1 = async () => {
const resp = await $client.get("/api/hello");
myModel.respCode = resp.status;
myModel.respBody = resp.data;
};
const btnClick2 = async () => {
const resp = await $client.get("https://httpbin.org/get");
//const resp = await $client.get("https://ifconfig.io/all.json");
myModel.respCode = resp.status;
myModel.respBody = resp.data;
};
const btnClick3 = async () => {
const resp = await $client.get("/api/hello2?name=taro"); // &name=taro
myModel.respCode = resp.status;
myModel.respBody = resp.data;
console.log(resp.data)
};
const postFormData = async () => {
const formData = new FormData();
formData.append("name", "taro");
formData.append("flag1", "true");
const resp = await $client.post("/api/formPost", formData, {});
myModel.respCode = resp.status;
myModel.respBody = resp.data;
};
<template>
<div class="container position-sticky z-index-sticky top-0">
<div class="row">
<!-- <div class="col-12">
<NavbarDefault :sticky="true" />
</div> -->
<button @click="btnClick1">Call API(Mock)</button>
<button @click="btnClick2">Call API</button>
<button @click="btnClick3">Call (Hello2)</button>
<button @click="postFormData">Call (postFormData)</button>
<button @click="postJson">Call (postJson)</button>
<button @click="delayHello">delayHello</button>
</div>
<div>
<dl>
<dt>code</dt>
<dd>{{ myModel.respCode }}</dd>
<dt>body</dt>
<dd>
<pre>{{ myModel.respBody }}</pre>
</dd>
</dl>
</div>
</div>
PresentationView.vue
테스트
source : https://github.com/ctimmerm/axios-mock-adapter
테스트
mock.js
빌드 및 배포
node
npm run build
copy dist folder to server directory
app.js
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const cors = require('cors');
const app = express();
var request = require('request');
app.use(bodyParser.json()); // json을 parse하도록 함
app.use(cors());
app.use(express.static("."));
// configuration =========================
app.set('port', process.env.PORT || 8030);
app.use( '/', express.static( path.join(__dirname, './dist') ));
app.get('/', function (req,res) {
res.sendFile(path.join(__dirname, './dist', 'index.html'));
});
app.listen(app.get('port'), () => {
console.log('Express server listening on port ' + app.get('port'));
});
npm install express
npm install cors
npm install request
node app.js
forever - nodeJS의 무중단 관리도구
○ forever 설치
npm install forever -g
○ forever 시작
forever start app.js
○ forever 종료
forever stop app.js (또는 forever list에서 확인한 pid)
○ forever 목록
forever list

More Related Content

Similar to Vue.js 기초 실습.pptx

자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기Jeado Ko
 
Android 기초강좌 애플리캐이션 구조
Android 기초강좌 애플리캐이션 구조Android 기초강좌 애플리캐이션 구조
Android 기초강좌 애플리캐이션 구조Sangon Lee
 
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012Daum DNA
 
[D2 오픈세미나]3.web view hybridapp
[D2 오픈세미나]3.web view hybridapp[D2 오픈세미나]3.web view hybridapp
[D2 오픈세미나]3.web view hybridappNAVER D2
 
Internship backend
Internship backendInternship backend
Internship backendYein Sim
 
Angular 2 rc5 조사
Angular 2 rc5 조사Angular 2 rc5 조사
Angular 2 rc5 조사Rjs Ryu
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSCirculus
 
챗봇 시작해보기
챗봇 시작해보기챗봇 시작해보기
챗봇 시작해보기성일 한
 
Progressive Web Apps
Progressive Web AppsProgressive Web Apps
Progressive Web Appsjungkees
 
3D 모델러 ADDIN 개발과정 요약
3D 모델러 ADDIN 개발과정 요약3D 모델러 ADDIN 개발과정 요약
3D 모델러 ADDIN 개발과정 요약Tae wook kang
 
React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기NAVER SHOPPING
 
Node.js and react
Node.js and reactNode.js and react
Node.js and reactHyungKuIm
 
Vue 뽀개기 1장 환경설정 및 spa설정
Vue 뽀개기 1장 환경설정 및 spa설정Vue 뽀개기 1장 환경설정 및 spa설정
Vue 뽀개기 1장 환경설정 및 spa설정leejungwang
 
[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발NAVER D2
 
[Osx dev] server essential lesson 10. configuring os x server to provide de...
[Osx dev] server essential   lesson 10. configuring os x server to provide de...[Osx dev] server essential   lesson 10. configuring os x server to provide de...
[Osx dev] server essential lesson 10. configuring os x server to provide de...EungShik (Henry) Kim
 
React 실무활용 이야기
React 실무활용 이야기React 실무활용 이야기
React 실무활용 이야기철민 배
 
PHP Slim Framework with Angular
PHP Slim Framework with AngularPHP Slim Framework with Angular
PHP Slim Framework with AngularJT Jintae Jung
 
IoT with Raspberry Pi + Node JS - Chapter 3
IoT with Raspberry Pi + Node JS - Chapter 3IoT with Raspberry Pi + Node JS - Chapter 3
IoT with Raspberry Pi + Node JS - Chapter 3Park Jonggun
 

Similar to Vue.js 기초 실습.pptx (20)

자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기
 
Android 기초강좌 애플리캐이션 구조
Android 기초강좌 애플리캐이션 구조Android 기초강좌 애플리캐이션 구조
Android 기초강좌 애플리캐이션 구조
 
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012
 
[D2 오픈세미나]3.web view hybridapp
[D2 오픈세미나]3.web view hybridapp[D2 오픈세미나]3.web view hybridapp
[D2 오픈세미나]3.web view hybridapp
 
Internship backend
Internship backendInternship backend
Internship backend
 
What's new in IE11
What's new in IE11What's new in IE11
What's new in IE11
 
Angular 2 rc5 조사
Angular 2 rc5 조사Angular 2 rc5 조사
Angular 2 rc5 조사
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JS
 
챗봇 시작해보기
챗봇 시작해보기챗봇 시작해보기
챗봇 시작해보기
 
Progressive Web Apps
Progressive Web AppsProgressive Web Apps
Progressive Web Apps
 
3D 모델러 ADDIN 개발과정 요약
3D 모델러 ADDIN 개발과정 요약3D 모델러 ADDIN 개발과정 요약
3D 모델러 ADDIN 개발과정 요약
 
React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기
 
Node.js and react
Node.js and reactNode.js and react
Node.js and react
 
테스트
테스트테스트
테스트
 
Vue 뽀개기 1장 환경설정 및 spa설정
Vue 뽀개기 1장 환경설정 및 spa설정Vue 뽀개기 1장 환경설정 및 spa설정
Vue 뽀개기 1장 환경설정 및 spa설정
 
[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발
 
[Osx dev] server essential lesson 10. configuring os x server to provide de...
[Osx dev] server essential   lesson 10. configuring os x server to provide de...[Osx dev] server essential   lesson 10. configuring os x server to provide de...
[Osx dev] server essential lesson 10. configuring os x server to provide de...
 
React 실무활용 이야기
React 실무활용 이야기React 실무활용 이야기
React 실무활용 이야기
 
PHP Slim Framework with Angular
PHP Slim Framework with AngularPHP Slim Framework with Angular
PHP Slim Framework with Angular
 
IoT with Raspberry Pi + Node JS - Chapter 3
IoT with Raspberry Pi + Node JS - Chapter 3IoT with Raspberry Pi + Node JS - Chapter 3
IoT with Raspberry Pi + Node JS - Chapter 3
 

More from wonyong hwang

Hyperledger Explorer.pptx
Hyperledger Explorer.pptxHyperledger Explorer.pptx
Hyperledger Explorer.pptxwonyong hwang
 
하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회wonyong hwang
 
토큰 증권 개요.pptx
토큰 증권 개요.pptx토큰 증권 개요.pptx
토큰 증권 개요.pptxwonyong hwang
 
Deploying Hyperledger Fabric on Kubernetes.pptx
Deploying Hyperledger Fabric on Kubernetes.pptxDeploying Hyperledger Fabric on Kubernetes.pptx
Deploying Hyperledger Fabric on Kubernetes.pptxwonyong hwang
 
k8s practice 2023.pptx
k8s practice 2023.pptxk8s practice 2023.pptx
k8s practice 2023.pptxwonyong hwang
 
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdfHyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdfwonyong hwang
 
Ngrok을 이용한 Nginx Https 적용하기.pptx
Ngrok을 이용한 Nginx Https 적용하기.pptxNgrok을 이용한 Nginx Https 적용하기.pptx
Ngrok을 이용한 Nginx Https 적용하기.pptxwonyong hwang
 
Nginx Https 적용하기.pptx
Nginx Https 적용하기.pptxNginx Https 적용하기.pptx
Nginx Https 적용하기.pptxwonyong hwang
 
Kafka JDBC Connect Guide(Postgres Sink).pptx
Kafka JDBC Connect Guide(Postgres Sink).pptxKafka JDBC Connect Guide(Postgres Sink).pptx
Kafka JDBC Connect Guide(Postgres Sink).pptxwonyong hwang
 
Nginx Reverse Proxy with Kafka.pptx
Nginx Reverse Proxy with Kafka.pptxNginx Reverse Proxy with Kafka.pptx
Nginx Reverse Proxy with Kafka.pptxwonyong hwang
 
Kafka monitoring using Prometheus and Grafana
Kafka monitoring using Prometheus and GrafanaKafka monitoring using Prometheus and Grafana
Kafka monitoring using Prometheus and Grafanawonyong hwang
 
주가 정보 다루기.pdf
주가 정보 다루기.pdf주가 정보 다루기.pdf
주가 정보 다루기.pdfwonyong hwang
 
App development with quasar (pdf)
App development with quasar (pdf)App development with quasar (pdf)
App development with quasar (pdf)wonyong hwang
 
Hyperledger Fabric practice (v2.0)
Hyperledger Fabric practice (v2.0) Hyperledger Fabric practice (v2.0)
Hyperledger Fabric practice (v2.0) wonyong hwang
 
Hyperledger fabric practice(pdf)
Hyperledger fabric practice(pdf)Hyperledger fabric practice(pdf)
Hyperledger fabric practice(pdf)wonyong hwang
 
Hyperledger composer
Hyperledger composerHyperledger composer
Hyperledger composerwonyong hwang
 

More from wonyong hwang (20)

Hyperledger Explorer.pptx
Hyperledger Explorer.pptxHyperledger Explorer.pptx
Hyperledger Explorer.pptx
 
하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회
 
토큰 증권 개요.pptx
토큰 증권 개요.pptx토큰 증권 개요.pptx
토큰 증권 개요.pptx
 
Deploying Hyperledger Fabric on Kubernetes.pptx
Deploying Hyperledger Fabric on Kubernetes.pptxDeploying Hyperledger Fabric on Kubernetes.pptx
Deploying Hyperledger Fabric on Kubernetes.pptx
 
k8s practice 2023.pptx
k8s practice 2023.pptxk8s practice 2023.pptx
k8s practice 2023.pptx
 
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdfHyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
 
Ngrok을 이용한 Nginx Https 적용하기.pptx
Ngrok을 이용한 Nginx Https 적용하기.pptxNgrok을 이용한 Nginx Https 적용하기.pptx
Ngrok을 이용한 Nginx Https 적용하기.pptx
 
Nginx Https 적용하기.pptx
Nginx Https 적용하기.pptxNginx Https 적용하기.pptx
Nginx Https 적용하기.pptx
 
Kafka JDBC Connect Guide(Postgres Sink).pptx
Kafka JDBC Connect Guide(Postgres Sink).pptxKafka JDBC Connect Guide(Postgres Sink).pptx
Kafka JDBC Connect Guide(Postgres Sink).pptx
 
Nginx Reverse Proxy with Kafka.pptx
Nginx Reverse Proxy with Kafka.pptxNginx Reverse Proxy with Kafka.pptx
Nginx Reverse Proxy with Kafka.pptx
 
Kafka Rest.pptx
Kafka Rest.pptxKafka Rest.pptx
Kafka Rest.pptx
 
Kafka monitoring using Prometheus and Grafana
Kafka monitoring using Prometheus and GrafanaKafka monitoring using Prometheus and Grafana
Kafka monitoring using Prometheus and Grafana
 
주가 정보 다루기.pdf
주가 정보 다루기.pdf주가 정보 다루기.pdf
주가 정보 다루기.pdf
 
KAFKA 3.1.0.pdf
KAFKA 3.1.0.pdfKAFKA 3.1.0.pdf
KAFKA 3.1.0.pdf
 
App development with quasar (pdf)
App development with quasar (pdf)App development with quasar (pdf)
App development with quasar (pdf)
 
kubernetes practice
kubernetes practicekubernetes practice
kubernetes practice
 
Hyperledger Fabric practice (v2.0)
Hyperledger Fabric practice (v2.0) Hyperledger Fabric practice (v2.0)
Hyperledger Fabric practice (v2.0)
 
Docker practice
Docker practiceDocker practice
Docker practice
 
Hyperledger fabric practice(pdf)
Hyperledger fabric practice(pdf)Hyperledger fabric practice(pdf)
Hyperledger fabric practice(pdf)
 
Hyperledger composer
Hyperledger composerHyperledger composer
Hyperledger composer
 

Vue.js 기초 실습.pptx

  • 3. MVVM (Model, View, ViewModel) View Model View Model DOM Listener Data Binding Javascript Object
  • 4. 준비물 IDE : VS Code 또는 ATOM, 기타 - VS Code : Volar extension 설치 크롬 : 개발자 도구와 Vue.js Extenstion (필요시) Node.js (Install Node.js version 16.0 or higher)
  • 5. Hello World Vue 애플리케이션 만들기 https://ko.vuejs.org/guide/quick-start.html#creating-a-vue-application index.html  main.js  App.vue CDN에서 Vue 사용 https://codepen.io/vuejs-examples/pen/eYQpQEG
  • 11. 템플릿 문법 : Boolean 속성
  • 12. 템플릿 문법 : 여러 속성 바인딩
  • 13. 템플릿 문법 : JavaScript 표현식 사용
  • 14. 반응형 기초 : 반응형 상태 선언 Composition API에서 반응형 상태를 선언하는 권장 방법은 ref() 함수를 사용하는 것입니다: 컴포넌트가 처음 렌더링될 때, Vue는 렌더링 과정에서 사용된 모든 ref를 추적합니다. 나중에 ref가 변경되면, 이를 추적하는 컴포넌트 에 대해 재렌더링을 트리거합니다. https://ko.vuejs.org/guide/essentials/reactivity-fundamentals.html#ref
  • 15. 반응형 기초 : reactive  ref와 reactive 차이 알아보기
  • 17. 계산된 속성(computed) <script setup> import { reactive, computed } from 'vue' const author = reactive({ name: 'John Doe', books: [ 'Vue 2 - Advanced Guide', 'Vue 3 - Basic Guide', 'Vue 4 - The Mystery', 'Vue 5 - The Mystery', 'Vue 6 - The Mystery', 'Vue 7 - The Mystery' ] }) // 계산된 ref const publishedBooksMessage = computed(() => { return author.books.length > 3 ? 'Yes' : 'No' }) const funcBtn = (()=>{ author.books.pop() }) </script> <template> <p>책을 많이 가지고 있다:</p> <span>{{ publishedBooksMessage }}</span> <p></p> <button @click="funcBtn">버튼</button> </template>
  • 20. 리스트 렌더링 추가 실습 : https://ko.vuejs.org/guide/essentials/list.html
  • 22. 입력 바인딩 추가 실습 : https://ko.vuejs.org/guide/essentials/forms.html
  • 25. 실습 환경 구성 npm install -g @vue/cli vue create vue-project2 cd vue-project2 npm run serve
  • 28. 컴포넌트 : props (1/3) App.vue HelloWorld.vue App.vue HelloWorld.vue
  • 29. 컴포넌트 : props (2/3) 부모 컴포넌트에서 버튼 클릭시, 부모 컴포넌트의 count 값을 자식 컴포넌트에 전달하고, 전달받은 값을 자식 컴포넌트 화면에 출력한다.
  • 30. 컴포넌트 : props (3/3) App.vue HelloWorld.vue
  • 31. 컴포넌트 : emit event (1/2) App.vue HelloWorld.vue
  • 32. 컴포넌트 : emit event (2/2) 1. Child Component에 버튼 추가하고, 버튼 클릭시 상위 컴포넌트에 메시지 전달
  • 36. Router Kopo 라는 메뉴 만들고, 해당 메뉴 클릭시 Kopo 컴포넌트 호출하게 코드 추가하기
  • 37. Axios
  • 39. vue2 style 준비 (전역 설정) import { createApp } from 'vue' import App from './App.vue' import router from './router' import axios from 'axios' // createApp(App).use(router).mount('#app') const app = createApp(App) app.config.globalProperties.axios=axios app.use(router).mount('#app') main.js
  • 40. vue2 style (사용) 사용하고자 하는 컴포넌트에서... HelloWorld.vue export default { name: 'HelloWorld', methods: { testAxios() { this.axios. get('https://api.coindesk.com/v1/bpi/currentprice.json'). then(response => (console.log(response))) }, btnclicked(){ this.testAxios(); } } }
  • 41. vue3 style 준비 (전역 설정) import { createApp } from 'vue' import App from './App.vue' import router from './router' import axios from 'axios' // createApp(App).use(router).mount('#app') const app = createApp(App) app.provide('$axios', axios); app.use(router).mount('#app') main.js
  • 42. vue3 style (사용) 사용하고자 하는 컴포넌트에서... import { inject } from 'vue' setup(props, ctx) { const axios = inject('$axios'); function sendmymessage () { ctx.emit('send-message',childmsg) axios. get('https://api.coindesk.com/v1/bpi/currentprice.json'). then(response => (console.log(response))) } return{ sendmymessage } } HelloWorld.vue
  • 44. CORS 관찰 만약에? 아마도, backend 응답 헤더에 아래와 같은 속성이 없을 수도?
  • 45. CORS 조치 Vue 개발을 위한 조치 => Production 환경에서는 BackEnd 에서 조치가 필요 function sendmymessage () { axios. get('/v1/bpi/currentprice.json'). then(response => (console.log(response))) const params = { name: "morpheus", job: "leader", }; axios.post("/api/users",params,{} ).then((res)=>{ //성공했을경우 console.log("성공",res) }).catch((res)=>{ //실패했을경우 console.error("실패",res) }) } const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, devServer: { proxy: { '/v1': { target: "https://api.coindesk.com", changeOrigin: true }, '/api': { target: "https://reqres.in", changeOrigin: true } } } }) vue.config.js
  • 46. async await Do you know 콜백지옥? btnclicked(){ this.testAxios(); this.testAsync(); }, async testAsync() { const resultValue = await this.requestPost(); this.requestGet(resultValue); }, requestGet(arg) { console.log(`[START] axios Get, Call Back From Previos Axios Post = ${arg} `); this.axios .get(`https://reqres.in/api/users?/page=1`, {}) .then((res) => { console.log("[END] axios Get "); this.getData = res.data; }) .catch((res) => { console.error(res); }); }, requestPost() { const params = { name: "morpheus", job: "leader", }; console.log("[START] axios Post"); return this.axios .post(`https://reqres.in/api/users`, params, {}) .then((res) => { console.log("[END] axios Post"); this.postData = res.data; return "Success"; }) .catch((res) => { console.error(res); return "Failure"; }); }, },
  • 47. Pinia
  • 48. Pinia Vue의 상태 관리 모듈 npm install pinia --save https://pinia.vuejs.org/introduction.html import { createApp } from 'vue' import App from './App.vue' import router from './router' import axios from 'axios' import { createPinia } from 'pinia' const app = createApp(App) const pinia = createPinia() app.config.globalProperties.axios=axios app.provide('$axios', axios); app.use(pinia) app.use(router).mount('#app')
  • 49. Pinia 폴더와 파일 생성 import { ref } from 'vue' import { defineStore } from "pinia" export const useCounterStore = defineStore('counter', () => { const count = ref(1) function increment() { count.value++ console.log("increment called") } return { count, increment } }) counter.js
  • 54. 조별 실습 과제 Vue Project - 화면 정의 - R&R, WBS, ...
  • 56. 로그인 예제 (준비) setup() { const myemail = ref('a@a.com') const mypwd = ref('1234') const refmyemail = ref(null); function func_signin() { console.log("sign in ",myemail,mypwd) console.log(refmyemail._value.value) } onMounted(() => { setMaterialInput(); }) return{ myemail, mypwd, func_signin, refmyemail } },
  • 57. 로그인 예제 (v-model) <div class="card-body"> <!-- submit.prevent added by hwy --> <form role="form" class="text-start" @submit.prevent> <!-- code modified by hwy --> <div class="input-group input-group-outline my-3"> <input v-model="myemail" id="email" class="form-control form-control-md" type="email" ref="refmyemail"/> </div> <div class="input-group input-group-outline my-3"> <input v-model="mypwd" id="password" class="form-control form-control-md" type="password"/> </div> <div class="text-center"> <MaterialButton class="my-4 mb-2" variant="gradient" color="success" @click="func_signin" fullWidth >Sign in</MaterialButton> </div>
  • 59. 로그인 예제 (ref 살펴보기) setup() { const refmyemail = ref(null); function func_signin() { console.log(refmyemail._value.value) } return{ func_signin, refmyemail } <div class="input-group input-group-outline my-3"> <input v-model="myemail" id="email" class="form-control form-control-md" type="email" ref="refmyemail"/> </div>
  • 60. 로그인 예제 (axios 및 router 적용) import { ref, inject } from 'vue' import { useRouter } from 'vue-router' setup() { const $client = inject("$axios"); const router = useRouter() async function func_signin() { const resp = await $client.get("/api/delayHello"); if(resp.status == 200){ router.push('/') }else{ } } rest call 정상 응답시 최상위 경로로 이동  로그인 관련 Backend에서 응답 받은 정보의 저장 및 관리는?
  • 61. 분석 컴포넌트 배치 확인 그리드 시스템(부트스트랩) https://getbootstrap.kr/docs/5.0/layout/grid/ PresentationView.vue
  • 66. 진행 방향 컴포넌트 구성도 작성 기획 & 화면 정의, R&R, WBS (교수와 협의) * axios, pinia, mitt 등 활용 형상관리(Git) 빌드 및 실서버 배포
  • 67. mitt
  • 68. 컴포넌트간 이벤트 전달 Vue2 : EventBus Vue3 : mitt npm install --save mitt main.js
  • 71. 결과 확인 AboutView.vue를 호출  이벤트 발송 (mount)  이벤트 수신
  • 72. mock
  • 73. 준비 npm install axios-mock-adapter --save npm install axios --save main.js
  • 74. mock 코드 준비 import MockAdapter from "axios-mock-adapter"; function parseQueryString(url) { const queryString = url.replace(/.*?/, ""); const result = {}; if (queryString === url || !queryString) { return result; } const urlParams = new URLSearchParams(queryString); urlParams.forEach((val, key) => { if (Object.prototype.hasOwnProperty.call(result, key)) { result[key] = [result[key], val]; } else { result[key] = val; } }); return result; } export default { mocked(axiosClient) { const mock = new MockAdapter(axiosClient, { onNoMatch: "passthrough" }); mock.onGet("/api/hello").reply(200, { hello: "world" }); mock.onGet(//api/hello2?.*/).reply((config) => { const params = parseQueryString(config.url); return [200, { config, params }]; }); mock.onPost("/api/formPost").reply((config) => { //const formData = config.data; const name = config.data.get("name"); return [200, { config, name: name }]; }); mock.onPost("/api/postJson").reply((config) => { const data = JSON.parse(config.data); return [200, { data }]; }); mock.onGet("/api/delayHello").reply((config) => { const delay = 5000; return new Promise((resolve, reject) => { setTimeout(() => { resolve([200, { hello: "world" }]); }, delay); }); }); } }; mock.js
  • 75. 테스트 // mock import { inject, reactive } from "vue"; const $client = inject("$axios"); const myModel = reactive({}); const btnClick1 = async () => { const resp = await $client.get("/api/hello"); myModel.respCode = resp.status; myModel.respBody = resp.data; }; const btnClick2 = async () => { const resp = await $client.get("https://httpbin.org/get"); //const resp = await $client.get("https://ifconfig.io/all.json"); myModel.respCode = resp.status; myModel.respBody = resp.data; }; const btnClick3 = async () => { const resp = await $client.get("/api/hello2?name=taro"); // &name=taro myModel.respCode = resp.status; myModel.respBody = resp.data; console.log(resp.data) }; const postFormData = async () => { const formData = new FormData(); formData.append("name", "taro"); formData.append("flag1", "true"); const resp = await $client.post("/api/formPost", formData, {}); myModel.respCode = resp.status; myModel.respBody = resp.data; }; <template> <div class="container position-sticky z-index-sticky top-0"> <div class="row"> <!-- <div class="col-12"> <NavbarDefault :sticky="true" /> </div> --> <button @click="btnClick1">Call API(Mock)</button> <button @click="btnClick2">Call API</button> <button @click="btnClick3">Call (Hello2)</button> <button @click="postFormData">Call (postFormData)</button> <button @click="postJson">Call (postJson)</button> <button @click="delayHello">delayHello</button> </div> <div> <dl> <dt>code</dt> <dd>{{ myModel.respCode }}</dd> <dt>body</dt> <dd> <pre>{{ myModel.respBody }}</pre> </dd> </dl> </div> </div> PresentationView.vue
  • 80. copy dist folder to server directory
  • 81. app.js const express = require('express'); const bodyParser = require('body-parser'); const path = require('path'); const cors = require('cors'); const app = express(); var request = require('request'); app.use(bodyParser.json()); // json을 parse하도록 함 app.use(cors()); app.use(express.static(".")); // configuration ========================= app.set('port', process.env.PORT || 8030); app.use( '/', express.static( path.join(__dirname, './dist') )); app.get('/', function (req,res) { res.sendFile(path.join(__dirname, './dist', 'index.html')); }); app.listen(app.get('port'), () => { console.log('Express server listening on port ' + app.get('port')); }); npm install express npm install cors npm install request
  • 83. forever - nodeJS의 무중단 관리도구 ○ forever 설치 npm install forever -g ○ forever 시작 forever start app.js ○ forever 종료 forever stop app.js (또는 forever list에서 확인한 pid) ○ forever 목록 forever list

Editor's Notes

  1. Vue.js devtools
  2. <script setup>과 <script> 차이 https://mine-it-record.tistory.com/640
  3. https://joshua1988.github.io/vue-camp/syntax/computed.html#computed-%E1%84%89%E1%85%A9%E1%86%A8%E1%84%89%E1%85%A5%E1%86%BC-%E1%84%8B%E1%85%A8%E1%84%89%E1%85%B5
  4. {data: {…}, status: 200, statusText: '', headers: AxiosHeaders, config: {…}, …} config: {transitional: {…}, adapter: 'xhr', transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …} data: {time: {…}, disclaimer: 'This data was produced from the CoinDesk Bitcoin P…hourly conversion rate from openexchangerates.org', chartName: 'Bitcoin', bpi: {…}} headers: AxiosHeaders {cache-control: 'max-age=15', content-length: '679', content-type: 'application/javascript', expires: 'Mon, 18 Sep 2023 12:50:07 UTC'} request: XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …} status: 200 statusText: "" [[Prototype]]: Object
  5. {data: {…}, status: 200, statusText: '', headers: AxiosHeaders, config: {…}, …} config: {transitional: {…}, adapter: 'xhr', transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …} data: bpi: EUR: {code: 'EUR', symbol: '&euro;', rate: '26,640.5514', description: 'Euro', rate_float: 26640.5514} GBP: code: "GBP" description: "British Pound Sterling" rate: "22,851.4325" rate_float: 22851.4325 symbol: "&pound;" [[Prototype]]: Object USD: code: "USD" description: "United States Dollar" rate: "27,347.5961" rate_float: 27347.5961 symbol: "&#36;" [[Prototype]]: Object [[Prototype]]: Object chartName: "Bitcoin" disclaimer: "This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org" time: updated: "Sep 18, 2023 12:43:00 UTC" updatedISO: "2023-09-18T12:43:00+00:00" updateduk: "Sep 18, 2023 at 13:43 BST" [[Prototype]]: Object constructor: ƒ Object() hasOwnProperty: ƒ hasOwnProperty() isPrototypeOf: ƒ isPrototypeOf() propertyIsEnumerable: ƒ propertyIsEnumerable() toLocaleString: ƒ toLocaleString() toString: ƒ toString() valueOf: ƒ valueOf() __defineGetter__: ƒ __defineGetter__() __defineSetter__: ƒ __defineSetter__() __lookupGetter__: ƒ __lookupGetter__() __lookupSetter__: ƒ __lookupSetter__() __proto__: (...) get __proto__: ƒ __proto__() set __proto__: ƒ __proto__() [[Prototype]]: Object constructor: ƒ Object() hasOwnProperty: ƒ hasOwnProperty() isPrototypeOf: ƒ isPrototypeOf() propertyIsEnumerable: ƒ propertyIsEnumerable() toLocaleString: ƒ toLocaleString() toString: ƒ toString() valueOf: ƒ valueOf() __defineGetter__: ƒ __defineGetter__() __defineSetter__: ƒ __defineSetter__() __lookupGetter__: ƒ __lookupGetter__() __lookupSetter__: ƒ __lookupSetter__() __proto__: (...) get __proto__: ƒ __proto__() set __proto__: ƒ __proto__() headers: AxiosHeaders {cache-control: 'max-age=15', content-length: '679', content-type: 'application/javascript', expires: 'Mon, 18 Sep 2023 12:45:07 UTC'} request: XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …} status: 200 statusText: "" [[Prototype]]: Object constructor: ƒ Object() hasOwnProperty: ƒ hasOwnProperty() isPrototypeOf: ƒ isPrototypeOf() propertyIsEnumerable: ƒ propertyIsEnumerable() toLocaleString: ƒ toLocaleString() toString: ƒ toString() valueOf: ƒ valueOf() __defineGetter__: ƒ __defineGetter__() __defineSetter__: ƒ __defineSetter__() __lookupGetter__: ƒ __lookupGetter__() __lookupSetter__: ƒ __lookupSetter__() __proto__: (...) get __proto__: ƒ __proto__() set __proto__: ƒ __proto__()
  6. https://cors-anywhere.herokuapp.com
  7. https://icea.tistory.com/47
  8. <script> import { ref } from 'vue' import { onMounted } from "vue"; // example components import DefaultNavbar from "@/examples/navbars/NavbarDefault.vue"; import Header from "@/examples/Header.vue"; //Vue Material Kit 2 components import MaterialInput from "@/components/MaterialInput.vue"; import MaterialSwitch from "@/components/MaterialSwitch.vue"; import MaterialButton from "@/components/MaterialButton.vue"; // material-input import setMaterialInput from "@/assets/js/material-input"; export default {   components: {     DefaultNavbar,     Header,     MaterialInput,     MaterialSwitch,     MaterialButton,     setMaterialInput   },   setup() {     const myemail = ref('a@a.com')     const mypwd = ref('1234')     const refmyemail = ref(null);     function func_signin() {       console.log("sign in ",myemail,mypwd)       console.log(refmyemail._value.value)     }         onMounted(() => {       setMaterialInput();           })     return{       myemail,       mypwd,       func_signin,       refmyemail     }   }, } </script> <template>   <DefaultNavbar transparent />   <Header>     <div       class="page-header align-items-start min-vh-100"       :style="{         backgroundImage:           'url(https://images.unsplash.com/photo-1497294815431-9365093b7331?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1950&q=80)'       }"       loading="lazy"     >       <span class="mask bg-gradient-dark opacity-6"></span>       <div class="container my-auto">         <div class="row">           <div class="col-lg-4 col-md-8 col-12 mx-auto">             <div class="card z-index-0 fadeIn3 fadeInBottom">               <div                 class="card-header p-0 position-relative mt-n4 mx-3 z-index-2"               >                 <div                   class="bg-gradient-success shadow-success border-radius-lg py-3 pe-1"                 >                   <h4                     class="text-white font-weight-bolder text-center mt-2 mb-0"                   >                     Sign in                   </h4>                   <div class="row mt-3">                     <div class="col-2 text-center ms-auto">                       <a class="btn btn-link px-3" href="javascript:;">                         <i class="fa fa-facebook text-white text-lg"></i>                       </a>                     </div>                     <div class="col-2 text-center px-1">                       <a class="btn btn-link px-3" href="javascript:;">                         <i class="fa fa-github text-white text-lg"></i>                       </a>                     </div>                     <div class="col-2 text-center me-auto">                       <a class="btn btn-link px-3" href="javascript:;">                         <i class="fa fa-google text-white text-lg"></i>                       </a>                     </div>                   </div>                 </div>               </div>               <div class="card-body">                 <!-- submit.prevent added by hwy -->                 <form role="form" class="text-start" @submit.prevent>                   <!-- code modified by hwy -->                   <div class="input-group input-group-outline my-3">                     <input v-model="myemail" id="email" class="form-control form-control-md" type="email" ref="refmyemail"/>                   </div>                   <div class="input-group input-group-outline my-3">                     <input v-model="mypwd" id="password" class="form-control form-control-md" type="password"/>                   </div>                                     <!-- <MaterialInput                     :value="myemail"                     id="email"                     class="input-group-outline my-3"                     :label="{ text: 'Email', class: 'form-label' }"                     type="email"                   /> -->                   <!-- <MaterialInput                     id="password"                     class="input-group-outline mb-3"                     :label="{ text: 'Password', class: 'form-label' }"                     type="password"                     v-model="mypwd"                   /> -->                   <MaterialSwitch                     class="d-flex align-items-center mb-3"                     id="rememberMe"                     labelClass="mb-0 ms-3"                     checked                     >Remember me</MaterialSwitch                   >                   <div class="text-center">                     <MaterialButton                       class="my-4 mb-2"                       variant="gradient"                       color="success"                       @click="func_signin"                       fullWidth                       >Sign in</MaterialButton                     >                   </div>                   <p class="mt-4 text-sm text-center">                     Don't have an account?                     <a                       href="#"                       class="text-success text-gradient font-weight-bold"                       >Sign up</a                     >                   </p>                 </form>               </div>             </div>           </div>         </div>       </div>       <footer class="footer position-absolute bottom-2 py-2 w-100">         <div class="container">           <div class="row align-items-center justify-content-lg-between">             <div class="col-12 col-md-6 my-auto">               <div                 class="copyright text-center text-sm text-white text-lg-start"               >                 © {{ new Date().getFullYear() }}, made with                 <i class="fa fa-heart" aria-hidden="true"></i> by                 <a                   href="https://www.creative-tim.com"                   class="font-weight-bold text-white"                   target="_blank"                   >Creative Tim</a                 >                 for a better web.               </div>             </div>             <div class="col-12 col-md-6">               <ul                 class="nav nav-footer justify-content-center justify-content-lg-end"               >                 <li class="nav-item">                   <a                     href="https://www.creative-tim.com"                     class="nav-link text-white"                     target="_blank"                     >Creative Tim</a                   >                 </li>                 <li class="nav-item">                   <a                     href="https://www.creative-tim.com/presentation"                     class="nav-link text-white"                     target="_blank"                     >About Us</a                   >                 </li>                 <li class="nav-item">                   <a                     href="https://www.creative-tim.com/blog"                     class="nav-link text-white"                     target="_blank"                     >Blog</a                   >                 </li>                 <li class="nav-item">                   <a                     href="https://www.creative-tim.com/license"                     class="nav-link pe-0 text-white"                     target="_blank"                     >License</a                   >                 </li>               </ul>             </div>           </div>         </div>       </footer>     </div>   </Header> </template>
  9. parseQueryString 역할 : 물음표 앞에 문자열을 모두 없애버림 "/api/hello2?name=taro"  name=taro Object.prototype.hasOwnProperty.call 문장 테스트: - const resp = await $client.get("/api/hello2?name=taro&name=taro2");에 대한 응답 name: Array(2) 0: "taro" 1: "taro2" length: 2 - const resp = await $client.get("/api/hello2?name=taro")에 대한 응답 params: name: "taro"
  10. const express = require('express'); const bodyParser = require('body-parser'); const path = require('path'); const cors = require('cors'); const app = express(); var request = require('request'); app.use(bodyParser.json()); // json을 parse하도록 함 app.use(cors()); app.use(express.static(".")); // configuration ========================= app.set('port', process.env.PORT || 8030); app.use( '/', express.static( path.join(__dirname, './dist') )); app.get('/', function (req,res) { res.sendFile(path.join(__dirname, './dist', 'index.html')); }); app.listen(app.get('port'), () => { console.log('Express server listening on port ' + app.get('port')); });