- vue_training/ex02/src/views/HomeView.vue
<template>
<div class="home">
<div>
<p>인사: {{ message }}</p>
</div>
<div>
<input type="text" v-model="input1"> <!-- v-model이 input1 변수 상자를 감지하게 됨-->
<input type="text" v-model="input2">
<button @click="show()">확인</button>
</div>
<div>
<p>{{ output }}</p>
</div>
<div>
<h3 v-if="success">성공</h3>
<h3 v-else>실패</h3>
<button @click="changeSuccess">바꾸기</button>
</div>
<ul>
<li>{{ dogs[0].name }}</li>
<li>{{ dogs[1].name }}</li>
<li>{{ dogs[2].name }}</li>
</ul>
<ul>
<li v-for="dog in dogs" :key="dog.id">
#{{ dog.id }} : {{ dog.name }}
</li>
</ul>
<ul>
<li v-for="(dog, index) in dogs" :key="index">
#{{ index + 1 }} : {{ dog.name }}
</li>
</ul>
<div>
<button @click="goToAbout()">정보 화면으로</button>
</div>
<div>
<button @click="goToProfile()">프로필 화면으로</button>
</div>
<div>
<button @click="requestPersonList()">리스트 요청하기</button>
</div>
<ul>
<li v-for="(person, index) in persons" :key="index">
#{{ person.id }} : {{ person.name }}, {{ person.age }}, {{ person.mobile }}
</li>
</ul>
<div>
<p class="group1">사용자 이름 : 홍길동1</p>
<p :class="groupClass">사용자 이름 : 홍길동2</p> <!-- 변수상자라고 생각하고 밑에 data에 추가하면 group1의 스타일을 같이 적용할 수 있다. -->
<button @click="chagneClass()">클래스 지정하기</button>
</div>
</div>
</template>
<style>
.group0 {
color: blue;
}
.group1 {
color: red;
}
</style>
<script>
export default {
name: 'HomeView',
data() {
return {
message: '안녕!',
input1: '',
input2: '',
output: '',
success: true,
dogs: [
{
id: 1,
name: '강아지1',
},
{
id: 2,
name: '강아지2',
},
{
id: 3,
name: '강아지3',
},
],
persons: [],
groupClass: 'group0'
}
},
mounted() { // 이 화면이 로딩될 때 자동으로 호출됨(onload 하고 같은 기능)
console.log(`홈 화면의 mounted 호출 됨`);
this.message = 'Hello!';
},
methods: { //함수 정의하는 곳(객체로 인식해서 콤마 붙여줄 것)
async requestPersonList() {
console.log(`requestPersonList 호출됨.`);
try {
const response = await this.axios({
method: 'post',
url: 'http://127.0.0.1:7001/list',
data: {},
})
console.log(`응답 -> ${JSON.stringify(response.data)}`);
this.persons = response.data;
} catch (err) {
console.error(`에러 -> ${err}`);
}
},
show() {
console.log(`show 함수 호출 됨.`);
this.message = '안녕하세요!';
this.output = `${this.input1} ${this.input2}`;
},
changeSuccess() {
this.success = !this.success;
},
goToAbout() {
this.$router.push({
path: '/about',
})
},
goToProfile() {
this.$router.push({
path: '/profile',
})
},
chagneClass() {
this.groupClass = 'group1';
}
}
}
</script>
https://getbootstrap.com/docs/5.3/examples/
* ex03 프로젝트 생성 후 부트스트랩 적용
- vue_training/ex02/public/index.html
<!DOCTYPE html>
<html lang="">
<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">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
<!-- MDB CSS start-->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/7.2.0/mdb.min.css" rel="stylesheet" />
<!-- MDB CSS end-->
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- MDB JS 추가 start -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/7.2.0/mdb.umd.min.js"></script>
<!-- MDB JS 추가 start -->
</body>
</html>
- vue_training/ex03/src/views/HomeView_old.vue
<template>
<div class="home">
<div>
<p>홈 화면입니다.</p>
<button type="button" class="btn btn-primary" data-mdb-ripple-init>확인</button>
</div>
<div>
<input type="text" v-model="input1">
<input type="text" v-model="input2">
</div>
<div class="row">
<div class="col-3">
</div>
<div class="col-6">
<div class="card text-center">
<div class="card-header">카드 헤더</div>
<div class="card-body">
<h5 class="card-title">카드 본문</h5>
<p class="card-text">본문 내용</p>
<div class="form-outline" data-mdb-input-init>
<input type="text" id="formControlSm" class="form-control form-control-sm" />
<label class="form-label" for="formControlSm">사용자 이름</label>
</div>
<button type="button" class="btn btn-primary" data-mdb-ripple-init>확인</button>
<button style="margin-left: 1em;" type="button" class="btn btn-primary" data-mdb-ripple-init data-mdb-modal-init data-mdb-target="#exampleModal">대화상자 띄우기</button>
</div>
<div class="card-footer text-muted">카드 푸터</div>
</div>
</div>
<div class="col-3">
</div>
</div>
</div>
<!-- 대화 상자 start-->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="btn-close" data-mdb-ripple-init data-mdb-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">...</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-mdb-ripple-init data-mdb-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-mdb-ripple-init>Save changes</button>
</div>
</div>
</div>
</div>
<!-- 대화 상자 end -->
</template>
<style scoped></style>
<script>
export default {
name: 'HomeView',
}
</script>
- vue_training/ex03/src/views/HomeView.vue
<template>
<div class="container">
<div class="card mt-4">
<div class="card-header d-flex align-items-center justify-content-center">
<p>고객 리스트</p>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-1">
</div>
<div class="col-md-3">
<span>이름</span>
</div>
<div class="col-md-3">
<span>전화번호</span>
</div>
<div class="col-md-5">
<span>기능</span>
</div>
</div>
<ul class="list-group">
<li v-for="(person, index) in persons" :key="index" class="list-group-item">
<div class="row">
<div class="col-md-1 d-flex align-items-center justify-content-center">
<img src="images/person.png" style="width:2em;">
</div>
<div class="col-md-3 d-flex align-items-center justify-content-center">
<span>{{ person.name }}</span>
</div>
<div class="col-md-3 d-flex align-items-center justify-content-center">
<span>{{ person.mobile }}</span>
</div>
<div class="col-md-5">
<button class="btn btn-primary btn-sm">수정</button>
<button class="btn btn-danger btn-sm ms-1">삭제</button>
</div>
</div>
</li>
</ul>
</div>
<div class="card-footer">
<div class="row d-flex justify-content-end">
<div class="col-md-3">
<button @click="goToAdd()" class="btn btn-primary btn-sm">추가</button>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped></style>
<script>
export default {
name: 'HomeView',
data() {
return {
persons: []
}
},
mounted() {
console.log(`mounted 호출됨`);
//고객 리스트 요청하기
this.requestPersonList();
},
methods: {
goToAdd() {
this.$router.replace({
path: '/add'
})
},
async requestPersonList() {
console.log(`requestPersonList 호출됨.`);
try {
const response = await this.axios({
method: 'post',
url: 'http://127.0.0.1:7001/list',
data: {},
})
console.log(`응답 -> ${JSON.stringify(response.data)}`);
this.persons = response.data;
} catch (err) {
console.error(`에러 -> ${err}`);
}
},
}
}
</script>
https://www.iconfinder.com/search?q=person
- vue_training/ex03/main.js
* 터미널에서 다운로드
- yarn.cmd add axios
- yarn.cmd add vue-axios
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// axios 설정
import axios from 'axios'
import VueAxios from 'vue-axios'
createApp(App).use(store).use(router).use(VueAxios, axios).mount('#app')
- vue_training/ex03/src/views/addView.vue
<template>
<div>
<div class="card mt-4">
<div class="card-header">
<h3>고객 정보 추가</h3>
</div>
<div class="card-body">
<!-- 이름 입력 상자 start-->
<div class="row mt-2">
<input v-model="nameInput" type="text" class="form-control" placeholder="이름" aria-lable="name">
</div>
<!-- 이름 입력 상자 end -->
<!-- 전화번호 입력상자 start-->
<div class="row mt-2">
<input v-model="mobileInput" type="text" class="form-control" placeholder="전화번호" aria-label="mobile">
</div>
<!-- 전화번호 입력상자 end-->
</div>
<div class="card-footer">
<button @click="saveItem()" class="btn btn-primary btn-sm">저장</button>
<button class="btn btn-primary btn-sm ms-4">닫기</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'AddView',
data() {
return {
nameInput: '',
mobileInput: '',
}
},
methods: {
saveItem() {
console.log(`saveItem 호출됨`)
this.requestPersonAdd();
},
async requestPersonAdd() {
console.log(`requestPersonAdd 호출됨.`);
try {
const response = await this.axios({
method: 'post',
url: 'http://127.0.0.1:7001/add',
data: {
name: this.nameInput,
age: '0',
mobile: this.mobileInput,
},
})
console.log(`응답 -> ${JSON.stringify(response.data)}`);
this.$router.replace({
path: '/'
})
} catch (err) {
console.error(`에러 -> ${err}`);
}
},
}
}
</script>
* 공간정보 관련 데이터 가져오기
<sql>
CREATE TABLE `coffeeshop` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL,
`tel` VARCHAR(32) NOT NULL,
`location` GEOMETRY NOT NULL,
PRIMARY KEY (`id`),
SPATIAL INDEX `location` (`location`)
)
INSERT INTO test.coffeeshop(NAME, tel, location)
VALUES
('스타벅스 서울세관 사거리점',
'1522-3232',
ST_GEOMFROMTEXT('POINT(127.0357329 37.5148388)') -> googlemap url
)
* SELECT id, NAME, tel,
ST_X(location) AS longitude,
ST_Y(location) AS latitude
FROM test.coffeeshop
WHERE NAME like '스타벅스%'
* SELECT id, NAME, tel,
ST_X(location) AS longitude,
ST_Y(location) AS latitude,
ST_DISTANCE(ST_GEOMFROMTEXT('point(127.0357329 37.51555)'), location) * 111195 AS distance
FROM test.coffeeshop
WHERE
ST_DISTANCE(ST_GEOMFROMTEXT('point(127.0357329 37.51555)'), location) * 111195 < 1000
ORDER BY
DISTANCE
node_training2에서 controller, sql, server01_03.js에 코드 추가
export const coffeeshopListController = async (req, res) => {
console.log(`/coffeeshop_list 요청 경로로 요청됨`);
const params = req.query;
console.log(`point -> '${params.point}'`)
try {
const rows = await database.execute(sql.coffeeshopList, [`${params.point}`, `${params.point}`]);
sendResponse(res, JSON.stringify(rows));
} catch (err) {
sendError(res, err);
}
}
export const coffeeshopSearchController = async (req, res) => {
console.log(`/coffeeshop_search 요청 경로로 요청됨`);
const params = req.query;
console.log(`point -> '${params.point}'`)
console.log(`name -> '${params.name}'`)
try {
const rows = await database.execute(sql.coffeeshopSearch, [`${params.point}`, `${params.name}%`]);
sendResponse(res, JSON.stringify(rows));
} catch (err) {
sendError(res, err);
}
}
coffeeshopList: `SELECT id, name, tel,
ST_X(location) AS longitude,
ST_Y(location) AS latitude,
ST_DISTANCE(ST_GEOMFROMTEXT(?), location) * 111195 AS distance
FROM test.coffeeshop
WHERE
ST_DISTANCE(ST_GEOMFROMTEXT(?), location) * 111195 < 1000
ORDER BY
DISTANCE`,
coffeeshopSearch: `SELECT id, name, tel,
ST_X(location) AS longitude,
ST_Y(location) AS latitude,
ST_DISTANCE(ST_GEOMFROMTEXT(?), location) * 111195 AS distance
FROM test.coffeeshop
WHERE NAME like ?`
router.route('/coffeeshop_list').get(coffeeshopListController);
router.route('/coffeeshop_search').get(coffeeshopSearchController);
* 지도 넣어주기
terminal에서 yarn.cmd add vue3-google-map 다운로드
vue_training/ex03/views/HomeView.vue에서 지도 부분 추가, api-key 발급 받아서 넣어줄 것!
<template>
<div class="container">
<div class="card mt-4">
<div class="card-header d-flex align-items-center justify-content-center">
<p>고객 리스트</p>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-1">
</div>
<div class="col-md-3">
<span>이름</span>
</div>
<div class="col-md-3">
<span>전화번호</span>
</div>
<div class="col-md-5">
<span>기능</span>
</div>
</div>
<ul class="list-group">
<li v-for="(person, index) in persons" :key="index" class="list-group-item">
<div class="row">
<div class="col-md-1 d-flex align-items-center justify-content-center">
<img src="images/person.png" style="width:2em;">
</div>
<div class="col-md-3 d-flex align-items-center justify-content-center">
<span>{{ person.name }}</span>
</div>
<div class="col-md-3 d-flex align-items-center justify-content-center">
<span>{{ person.mobile }}</span>
</div>
<div class="col-md-5">
<button class="btn btn-primary btn-sm">수정</button>
<button class="btn btn-danger btn-sm ms-1">삭제</button>
</div>
</div>
</li>
</ul>
</div>
<div class="card-footer">
<div class="row d-flex justify-content-end">
<div class="col-md-3">
<button @click="goToAdd()" class="btn btn-primary btn-sm">추가</button>
</div>
</div>
</div>
</div>
<!-- 지도 -->
<GoogleMap style="width:100%; height: 300px" api-key="" :center="{ lat: 37.51555, lng: 127.034983 }" :zoom="{ zoom }">
<!-- components로 넣고 태그로 사용 -->
<Marker v-for="(coffeeshop, index) in coffeeshopList" :key="index" :options="{ position: {lat: coffeeshop.latitude, lng: coffeeshop.longitude } }"></Marker>
</GoogleMap>
<button @click="requestCoffeeshopList()">커피숍 조회</button>
</div>
</template>
<style scoped></style>
<script>
import { GoogleMap, Marker } from 'vue3-google-map';
export default {
name: 'HomeView',
components: {
GoogleMap,
Marker
},
data() {
return {
zoom: 15,
markerOptions: {
position: {
lat: 37.51555,
lng: 127.034983,
}
},
persons: [],
coffeeshopList: [],
}
},
mounted() {
console.log(`mounted 호출됨`);
//고객 리스트 요청하기
this.requestPersonList();
},
methods: {
goToAdd() {
this.$router.replace({
path: '/add'
})
},
async requestPersonList() {
console.log(`requestPersonList 호출됨.`);
try {
const response = await this.axios({
method: 'post',
url: 'http://127.0.0.1:7001/list',
data: {},
})
console.log(`응답 -> ${JSON.stringify(response.data)}`);
this.persons = response.data;
} catch (err) {
console.error(`에러 -> ${err}`);
}
},
async requestCoffeeshopList() {
console.log(`requestCoffeeshopList 호출됨.`);
try {
const response = await this.axios({
method: 'get',
url: 'http://127.0.0.1:7001/coffeeshop_list?point=POINT(127.0357329 37.51555)',
})
console.log(`응답 -> ${JSON.stringify(response.data)}`);
this.coffeeshopList = response.data;
} catch (err) {
console.error(`에러 -> ${err}`);
}
},
}
}
</script>
'TIL' 카테고리의 다른 글
war, war(exploded) 차이 (0) | 2024.03.28 |
---|---|
24년 1학기 컴퓨터의 이해 중간 과제물 (QR코드 만들기) (0) | 2024.03.18 |
2024년 공간정보 활용을 위한 Node.js 웹서버 프로그래밍 (2) (0) | 2024.03.12 |
2024년 공간정보 활용을 위한 Node.js 웹서버 프로그래밍 (1) (0) | 2024.03.11 |
application.yml에 관하여 (0) | 2024.01.19 |