오전일과
cmd 조작
vue.config.js (서버 등록, 공동 db등)
BoardPage.vue
BoardWritePage.vue
오후일과
BoardPage.vue
BoardContent.vue
ref에서는 계산 속성이 사용 불가능 했으나, reactive에서는 사용이 가능했다.
오전일과
cmd
npm install <= 꾸준히 한번씩 해주는게 좋음
npm run serve <= 서버 구동
reactive활용
state에 변수 선언하면 스크립트에서 바꿔서 페이지에 자동 반영
vue.config.js
서버 등록
읽어들이고 npm으로 서버를 불러들임
so config가 바뀌면 서버 껏다 켜야함(재구동 필수)
공공db도 여기에 넣음
게시판 작업(초기 설정)
index.js BoardPage 추가
컴포넌트 BoardPage 생성
App.vue 게시판 버튼 추가
BoardPage.vue
로그인 페이지는 사용자가 누르면 백엔드
보드는 키자마자 바로 백엔드에서 받아들여옴
<template>
<div>
<h3>게시판</h3>
<button @click="handleNext()">글쓰기</button>
<!-- {{state}} -->
<table border = "1">
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
<th>날짜</th>
</tr>
</thead>
<tbody>
<!-- rows 모양 [{}, {}, {}] -->
<tr v-for="tmp in state.rows" :key="tmp._id">
<td>{{tmp._id}}</td>
<td @click="handleContent(tmp._id)" style="cursor:pointer">{{tmp.title}}</td>
<td>{{tmp.writer}}</td>
<td>{{tmp.hit}}</td>
<td>{{tmp.regdate}}</td>
</tr>
</tbody>
</table>
<button v-for="tmp in state.pages" :key="tmp" @click="handlePage(tmp)">
{{tmp}}
</button>
</div>
</template>
<script>
import axios from 'axios';
import { onMounted, reactive } from '@vue/runtime-core';
import { useRouter } from 'vue-router';
export default {
setup () {
// 1. 변수설정 및 import
const router = useRouter();
// 객체 만들기 (return필수)
const state = reactive({
tml:'aaa', // 테스트용
rows : null, // 백엔드의 데이터 중에서 게시물 목록
total :0, // 백엔드의 데이터 중에서 게시물 전체 개수
pages :0, // 전체개수를 기반으로 계산된 페이지수
page : 1, // 초기페이지 번호
});
// 백엔드로부터 게시판 목록 받아오기
// 함수는 호출되기 전에는 실행되지 않음.
const handleData = async() => {
const url = `/board101/select.json?page=${state.page}&text=`;
const headers = {"Content-Type":"application/json"};
const response = await axios.get(url, {headers:headers});
console.log(response.data);
if(response.data.status === 200){
state.rows = response.data.rows;
state.total = response.data.total;
// console.log(Math.floor((state.total-1)/10) +1);
state.pages = Math.floor((state.total-1)/10) +1;
}
};
// 페이지가 로딩되면 자동으로 호출됨
onMounted( () => {
handleData();
});
const handlePage = ( tmp ) => {
// alert('페이지 클릭'+tmp);
state.page = tmp;
handleData();
};
const handleNext = () => {
router.push({path:'boardw'});
};
const handleContent = async(no) => {
console.log('handleContent', no);
//조회수 1증가
const url = `/board101/updatehit.json?no=${no}`;
const headers = {"Content-Type":"application/json"};
const response = await axios.get(url, {headers});
console.log(response.data);
if(response.data.staus ===200){
//상세페이지로 이동
router.push({path:'/boardc', query:{sendno : no}});
}
};
return {state, handlePage, handleNext, handleContent};
}
}
</script>
<style lang="css" scoped>
</style>
바로 호출하는 함수onMount
import { onMounted, reactive } from '@vue/runtime-core';
onMounted( () => {
handleData();
});
백엔드로부터 게시판 목록 받아오기
const handleData = async() => {
const url = `/board101/select.json?page=${state.page}&text=`;
const headers = {"Content-Type" : "application/json"};
const response = await axios.get(url, {headers:headers});
}
axios에서
아래는 오브젝트 타입이기 때문에
{headers}
{headers : headers} 그냥 이렇게 적으십쇼
짧은게 좋지만, 배열 상태에 따라 하나만 적어도 되는데 아직까지 개념이 안잡힘.
===================================================================
reactive
변수를 받아오고
변수를 쉽게 쓰기 위해서 const state를 만듬(임시로라도 먼저 만들고 시작)
(객체 만들기)
페이지 로딩하자마자 rows와 total이 변경됨.(if문과 연동시킴 status ===200)
테이블 만들기
중요
<tr v-for="tmp in state.rows" :key="tmp._id">
key는 겹치면 안되기때문에 , 고유한 것을 적어야함.
rows 모양 [{}, {}, {}]
tmp{ } 모양 tmp에 해당하는 것을 넣어라는 뜻
v-for 만듬 위 rows의 모양만 반복문이 가능
페이지 개수
console.log(Math.floor((state.total-1)/10) +1);
pages 정의 (전체개수를 기반으로 계산된 페이지수)
Math.floor 소수점 버리기
페이지 개수 버튼 만들기
밑 두개는 같은 것임
1.
<button v-for="tmp in state.pages" :key="tmp"
@click="handlePage()">
{{tmp}}
</button>
2.
<button v-for="tmp in state.pages" :key="tmp" @click="handlePage(tmp)">
{{tmp}}
</button>
===================================
페이지 버튼 클릭시 작동하는 원리 요약
===================================
const page로 페이지 초기선언 및 기본 페이지로 만들고(1)
url을 페이지로 바뀔 수 있게 변수(${state.page})로 바꿈.
버튼에는 handlePage함수가 내포
handlePage 클릭시 tmp가 변함.
state.page = tmp로
state.page가 정의되고
handleData 함수를 불러오면 page가 버튼 불렀던 번호로 바뀐 후 작동
(원하는 페이지로 이동)
===================================
handlePage함수 만듬
const page : 1 //초기선언, 초기페이지 번호입력
(로딩시 처음 화면은 1페이지여야하기 때문)
<handleData>
const url = `/board101/select.json?page=${state.page}&text=`;
<handlePage>
const handlePage = ( tmp ) => {
// alert('페이지 클릭'+tmp);
state.page = tmp;
handleData();
}
====================================
글쓰기 버튼 클릭시 동작
<button @click="handleNext()">글쓰기</button>
1. 버튼 설정
import { useRouter } from 'vue-router';
const router = useRouter();
2. 라우터 설정
const handleNext = () => {
router.push({path:'boardw'});
}
3. BoardWritePage.vue로 이동
boardWritePage는 아래서 설명
BoardWritePage.vue
v-model은 reactive와 연결(데이터를 받아서 백엔드로 넘길때 사용)
ref는 그냥 const 선언(유효성 검사할때 사용)
<template>
<div>
<h3>글쓰기</h3>
<input type="text" ref="title" placeholder="제목" v-model="state.title" /><br/>
<textarea rows="6" ref="content" placeholder="내용" v-model="state.content"></textarea><br/>
<input type="text" ref="writer" placeholder="작성자" v-model="state.writer"/><br/>
<button @click="handleWrite()">글쓰기</button>
</div>
</template>
<script>
import { reactive, ref } from '@vue/reactivity'
import axios from 'axios';
import { useRouter } from 'vue-router';
export default {
setup () {
const router = useRouter();
const title = ref(); //document.byid로 개체 찾는
const content = ref(); //document.byid로 개체 찾는
const writer = ref(); //document.byid로 개체 찾는
const state = reactive({
title : '',
content: '',
writer : '',
});
//글쓰기 버튼 클릭시 호출됨
const handleWrite = async() => {
// 제목, 내용, 작성자 유효성 검사 자리 생략
if(state.title === ''){
alert('아이디를 입력하세요.')
title.value.focus();
return false;
}
if(state.content === ''){
alert('내용을 입력하세요.')
content.value.focus();
return false;
}
if(state.writer === ''){
alert('작성자를 입력하세요.')
writer.value.focus();
return false;
}
const url = `/board101/insert.json`;
const headers = {"Content-Type" : "application/json"}
const body = {
title : state.title,
content : state.content,
writer : state.writer,
}
const response = await axios.post(url, body, {headers:headers});
console.log(response.data);
if(response.data.status === 200){
router.push({path:'/board'});
}
};
return {state, handleWrite, title, content, writer}
}
}
</script>
<style lang="css" scoped>
.container {
width : 700px;
padding : 20px;
border : 1px solid #cccccc;
}
</style>
index에서 매핑(페이지 연결)
BoardWritePage
input, textarea 입력
컨테이너 스타일 입력
state 리액트 선언
div부분
v-model로 변수적용(const state = reactive 실시간 적용)
await axios.post(서버기입, 바디, 헤더) 업로드
response (post 업로드 하는 것이기때문)
const response = await axios.post(url, body, {headers:headers});
url에 body를 첨부하여 보냄
글쓰기 완료후
status 200 확인후
게시판으로 보냄(router)
import { useRouter } from 'vue-router';
const router = useRouter();
라우터를 사용할꺼면 위 코드를 입력하여야함.(import 포함)
router.push({path:'/board'});
<script>
import { reactive, ref } from '@vue/reactivity'
import axios from 'axios';
import { useRouter } from 'vue-router';
export default {
setup () {
const router = useRouter();
const state = reactive({
title : '',
content: '',
writer : '',
});
//글쓰기 버튼 클릭시 호출됨
const handleWrite = async() => {
// 제목, 내용, 작성자 유효성 검사 자리 생략
const url = `/board101/insert.json`;
const headers = {"Content-Type" : "application/json"}
const body = {
title : state.title,
content : state.content,
writer : state.writer,
}
const response = await axios.post(url, body, {headers:headers});
console.log(response.data);
if(response.data.status === 200){
router.push({path:'/board'});
}
};
return {state, handleWrite, title, content, writer}
}
}
</script>
===================================
아래는 유효성 검사를 위한 것.
개체찾기 (연결) reference 레퍼런스 ref
<div>
<h3>글쓰기</h3>
<input type="text" ref="title" placeholder="제목" v-model="state.title" /><br/>
<textarea rows="6" ref="content" placeholder="내용" v-model="state.content"></textarea><br/>
<input type="text" ref="writer" placeholder="작성자" v-model="state.writer"/><br/>
<button @click="handleWrite()">글쓰기</button>
</div>
const title = ref(); //document.byid로 개체 찾는 것
const content = ref(); //document.byid로 개체 찾는 것
const writer = ref(); //document.byid로 개체 찾는 것
handleWrite
유효성 검사(div부분 ref 기입 필요 + const선언 필요)
if(state.title === ''){
alert('아이디를 입력하세요.')
title.value.focus();
return false;
}
if(state.content === ''){
alert('내용을 입력하세요.')
content.value.focus();
return false;
}
if(state.writer === ''){
alert('작성자를 입력하세요.')
writer.value.focus();
return false;
}
오후일과
BoardPage.vue
상세페이지 확인
<td @click="handleContent(tmp._id)" style="cursor:pointer">{{tmp.title}}</td>
handleContent
조회수 증가 성공하면 상세페이지로 이동(query 정보를 다음페이지로 보내줌)
if(response.data.staus ===200){
//상세페이지로 이동
router.push({path:'/boardc', query:{sendno : no}});
}
boardc에 넘버를 보내줌
아래는 오류가 계속나서 강사님께 물었더니, axios put을 이용하고 있었고 + body기입했었음.
axios.get을 사용해야함 게시물을 가져오는 것이니까(가져올때는 body를 쓰지 않음)
-BoardContent.vue
목록으로 이동할때 받아온 쿼리, 이전글, 다음글 정보, 게시글 내용 불러오기
수정, 삭제, 이전글, 다음글, 목록 (수정은 내일 알려주심)
<template>
<div>
<h3>게시판상세</h3>
{{ state }} <!-- 처음에 해놓는게 좋음 -->
<div v-if="state.row">
글번호 : {{state.row._id}} <br/>
제목 : {{state.row.title}}
<input type="text" v-model="state.row.title" />
<br/>
내용 : {{state.row.content}} <br/>
작성자 : {{state.row.writer}} <br/>
조회수 : {{state.row.hit}} <br/>
등록일 : {{state.row.regdate}} <br/>
<button @click="handleUpdate()">수정</button>
<button @click="handleDelete()">삭제</button>
<button v-if="state.prev !==0" @click="handlePrev()">이전글</button>
<button v-if="state.next !==0" @click="handleNext()">다음글</button>
<router-link to ="/board">
<button>목록</button>
</router-link>
</div>
<router-link to="/board">목록으로</router-link>
</div>
</template>
<script>
import { reactive } from '@vue/reactivity'
import { useRoute, useRouter } from 'vue-router'
import { onMounted } from '@vue/runtime-core';
import axios from 'axios';
export default {
setup () {
const route = useRoute(); //query값 받기
const router = useRouter(); //페이지 이동 import 필수
console.log(route);
const state = reactive({ // 초기선언
no : Number(route.query.sendno), // 목록에서 전달되는 글번호
prev : 0, // 이전글 정보
next : 0, // 다음글 정보
row : null, // 게시글 내용 1개
});
const handleData = async() => {
const url = `board101/selectone.json?no=${state.no}`
const headers = {"Content-Type":"application/json"};
const response = await axios.get(url, {headers});
console.log(response.data);
if(response.data.status === 200){
state.prev = response.data.prevNo;
state.next = response.data.nextNo;
state.row = response.data.result;
}
}
onMounted( () => {
handleData();
});
const handlePrev = async() => {
state.no = state.prev;
handleData(); // 여기는 no값을 가지고 내용을 가져옴.
};
const handleNext = async() => {
state.no = state.next;
handleData(); // 여기는 no값을 가지고 내용을 가져옴.
};
const handleDelete = async() => {
if(confirm('삭제할까요?')){
const url = `board101/delete.json?no=${state.no}`;
const headers = {"Content-Type":"application/json"};
const response = await axios.delete(url, {headers});
if(response.data.status === 200){
alert('삭제되었습니다.')
router.push({path:'board'});
}
}
}
const handleUpadte = async() =>{
// 컴포넌트 없음
// BoardUpdatepage.vue 생성
// 라우트 연결
router.push({path:'/boardu', query :{sendno: state.no} });
}
return {state, handlePrev, handleNext, handleDelete, handleUpadte}
}
}
</script>
<style lang="scss" scoped>
</style>
const route = useRoute(); //query값 받기
no : Number(route.query.sendno)
route.query.+키
보드페이지에서 보드컨텐츠로 넘어올때 쿼리
router.push({path:'/boardc', query:{sendno : no}});
BoardContent 같은 것 만들때는
{{state}} 처음에 해놓는고 작업하는게 좋음.
v-if 쓰는 이유
데이터가 있을경우에만 표기
데이터를 받기전에 화면에 표기하기때문에 v-if를 없이 화면표기할때
오류 발생
handleData
상세 데이터 불러오는 펑션
onMounted
바로 실행하게끔 마운트
const handleData = async() => {
const url = `board101/selectone.json?no=${state.no}`
const headers = {"Content-Type":"application/json"};
const response = await axios.get(url, {headers});
console.log(response.data);
if(response.data.status === 200){
state.prev = response.data.prevNo;
state.next = response.data.nextNo;
state.row = response.data.result;
}
}
onMounted( () => {
handleData();
});
참고
v-for key
https://kamang-it.tistory.com/631
[Web][Performance][Vue] v-for과 key, 그리고 성능사이의 관계
참고: Programming/JavaScript-Vue Usage/JavaScript-Vue [Web][Performance][Angular][React][Vue] Angular vs React vs Vue 속도 비교 [Vue-06]반복문(v-for) v-for을 사용하다보면 생각보다 요놈이 문제 많은..
kamang-it.tistory.com
https://dev-josh.tistory.com/28
[Vue] Vue3 ref, reactive 사용해보기
이번에 vue3에서 composition api가 추가됨으로써 vue2 사용자 시점에서 ref와 reactive에 대하여 간단한 예제 소스를 작성해 보았다. 1. data()와 ref() 기존 vue2에서 데이터를 핸들링 할때는 사실 반응형이
dev-josh.tistory.com
ref 와 reactive 차이점
어렵다..
'vue' 카테고리의 다른 글
국비 코딩 풀스택 수업 12일차(에어컨 안되는 날) (0) | 2022.07.06 |
---|---|
국비 코딩 풀스택 수업 11일차 (0) | 2022.07.05 |
국비 코딩 풀스택 수업 10일차 (0) | 2022.07.04 |
국비 코딩 풀스택 수업 9일차 (0) | 2022.07.01 |
국비 코딩 풀스택 수업 7일차 (0) | 2022.06.29 |