20240405 Vue.js 7

Leafy·2024년 4월 5일
1

중앙_자바

목록 보기
69/76

오늘 만든 폴더 이름은 vue_final

npm install 뭐뭐 왕왕 왈왈
이런 식으로 붙여서 쓸 수 있다.

npm install vue-router axios bootstrap

근데 오타생기니까 하나하나 하는게 낫다.

router npm install vue-router
axios npm install axios
bootstrap npm install bootstrap bootstrap-vue-3

dependencies 확인

  "dependencies": {
    "axios": "^1.6.8",
    "bootstrap": "^5.3.3",
    "bootstrap-vue-3": "^0.5.1",
    "core-js": "^3.8.3",
    "vue": "^3.2.13",
    "vue-router": "^4.3.0"
  },

src 폴더 하위에 router, views 폴더 생성

components 폴더 하위에 HelloWorld.vue 삭제하고 MenuPage.vue 생성

<template>
    <header>
        <nav class="nav">
            <ul>
                <li><router-link to="/">index</router-link></li>
                <li><router-link to="/boardList">게시판</router-link></li>
            </ul>
        </nav>
    </header>
</template>
<script>
export default {
    name: 'MenuPage'
};
</script>
<style>
header {
    height: 50px;
}

nav {
    position: fixed;
    top: 0;
    width: 100%;
    height: 30px;
    background-color: gray;
}

nav ul {
    margin: 0;
    padding: 0;
}

nav li {
    list-style: none;
    float: left;
    width: 100px;
    height: 30px;
    line-height: 30px;
    text-align: center;
}

nav li:hover {
    font-weight: bold;
}
</style>

router 하위에 index.js 생성

import { createRouter, createWebHistory } from "vue-router";
import IndexPage from "@/views/IndexPage.vue";
import BoardList from "@/views/BoardList.vue";
const routes = [
  { path: "/", component: IndexPage }, // import 먼저
  { path: "/boardList", component: BoardList },
  { path: "/login", component: () => import("../views/LoginPage.vue") }, // 여기서 생성
  { path: "/detail", component: () => import("../views/DetailPage.vue") },
];
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
});
export default router;

이걸 보면
임포트 먼저 해주고 부르는 방법과
컴포넌트 생성을 화살표 함수로 하는 방법 두 가지가 있는데
보기 편한 걸로 하나로 통일하는 것이 좋다.

src 하위 main.js 수정

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";

const app = createApp(App);
app.use(router);
app.mount("#app");

App.vue 수정

<template>
  <MenuPage/>
  <router-view/>
</template>

<script>
import MenuPage from './components/MenuPage.vue';

export default {
  name: 'App',
  components: {
    MenuPage
  }
}
</script>

<style>
</style>

서버

서버를
백그라운드로 (MobaXTerm 창 닫아도)

리눅스때 했어야했지만~

sudo nohup java -jar vue-board-0.4.jar &

nohup = no hang up

suo lsof -i : 8080

8080 포트가 사용되고 있는지 보기


부트스트랩 추가

main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import BootstrapVue3 from 'bootstrap-vue-3'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue-3/dist/bootstrap-vue-3.css'

const app = createApp(App)
app.use(router)
app.use(BootstrapVue3)
app.mount('#app')

부트스트랩 추가했더니
popper js 오류 Can't resolve '@popperjs/core'~

npm install --save @popperjs/core

실행하고 해결

실제 데이터를 박아넣어 상품목록을 만들자 (import / export)


BoardList.vue
(여기까지는 한 거)

<template>
    <div>
        <table class="table table-hover">
            <thead>
                <tr>
                    <th>번호</th>
                    <th>제목</th>
                    <th>글쓴이</th>
                    <th>날짜</th>
                    <th>ip</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="n in list" v-bind:key="n.board_no">
                    <td>{{ n.board_no }}</td>
                    <td v-text="n.board_title" v-on:click="detail(n.board_no)"></td>
                    <td>{{ n.mno }}</td>
                    <td>{{ n.board_date }}</td>
                    <td>{{ n.board_ip }}</td>
                </tr>
            </tbody>
        </table>
        <button @click="$router.push('/write')">글쓰기</button>
    </div>
</template>
<script>
import axios from 'axios'
export default {
    name: 'BoardList',
    data() {
        return {
            list: [],
        }
    },
    mounted() {
        axios.get('http://172.30.1.59:3000/board')
        .then((res) => {this.list = res.data.list})
        .catch((err) => {alert('문제가 발생했습니다. 다시 시도해주세요.' + err);});
    }
}
</script>

서버가 꺼지면 catch 문장이 실행될 것.

상세보기 만들기

detail(n.board_no) 만들어주자.

<script>
import axios from 'axios'
export default {
    name: 'BoardList',
    data() {
        return {
            list: [],
        }
    },
    methods: {
        detail(bno) {
            alert('글 번호는 ' + bno);
        }
    }, 
    mounted() {
        axios.get('http://172.30.1.59:3000/board')
        .then((res) => {this.list = res.data.list})
        .catch((err) => {alert('문제가 발생했습니다. 다시 시도해주세요.' + err);});
    }
}
</script>

methods에 넣어주면 잘 동작한다.

(pdf에 없다)

<script>
import axios from "axios";
export default {
  name: "BoardList",
  data() {
    return {
      list: [],
      requestBody: this.$route.query, //route로 보내서 사용하게 추가
      bno: this.$route.query.bno //추가
    };
  },
  methods:{
    detail(bno){
        //alert('글 번호는 ' + bno)
        this.requestBody.bno = bno //추가
        this.$router.push({path: './detail', query: this.requestBody})// bno도 같이 가져가려고 넣어준 거.
    }
  },
  mounted() {
    axios.get("http://172.30.1.59:3000/board")
      .then(res => {this.list = res.data.list})
      .catch(err => {alert("문제가 발생했습니다. 다시 시도해주세요." + err);});
  }
};
</script>

requestBody가 중요하니까 bno는 없어도 된다(..)

query는 db의 쿼리가 아니라,, 그냥 이름이 똑같은 거다.
bno값을 담아서 넣을 박스 같은 거


bno도 같이 나온다.


DetailPage.vue 수정.

v-on:click이랑 @click은 똑같다고 한다.

<template>
    <div>
        <div class="board-detail">
            글번호 : {{ detail.board_no }}번글
            <button v-on:click="del()">삭제</button>
            <button v-on:click="up(detail.board_no)">수정</button><br />
            글제목 : {{ detail.board_title }}<br />
            글쓴이 : {{ detail.mno }}<br />
            쓴날짜 : {{ detail.board_date }}<br />
            내 용 : <span v-html="detail.board_content"></span><br />
        </div>
    </div>
</template>
<script>
import axios from "axios";
export default {
    data() {
        //변수생성
        return {
            requestBody: this.$route.query,
            detail: {
                board_no: this.$route.query.bno,
                board_title: "기본",
                mno: "기본",
                board_content: "기본",
                board_date: "기본"
            }
        };
    },
    mounted() {
        this.boardDetail();
    },
    methods: {
        boardDetail() {
            axios.get("http://172.30.1.59:3000/detail?bno=" + this.$route.query.bno)
                .then(res => { this.detail = res.data })
                .catch(err => {
                    alert("문제가 발생했습니다. 잠시 후 다시 시도해주세요." + err);
                });
        }
    }
};
</script>
<style scoped></style>

v-html은 사진같은 게 본문에 있을 수 있으니까

db랑 통신이 안되면 "기본"
axios url 틀리게 해서 깨뜨리면

mounted

2가지 방법

BoardList.vue에서
바로 mounted() {} 안에 실행할 코드 적는 거랑
DetailPage.vue에서
methods에 적은 함수를 mounted() {this.함수명()} 이렇게 하는 거


부트스트랩도 클래스명 쓰면 잘 된다

글쓰기

views에 WritePage.vue

<template>
    <div class="write">
        <h1>글쓰기</h1>
        <input v-model="title" />
        <textarea v-model="content"></textarea>
        <button @click="write">글쓰기</button>
    </div>
</template>
<script>
import axios from 'axios';
export default {
    name: "WritePage",
    data() {
        return {
            title: null,
            content: null
        }
    },
    methods: {
        write() {
            let saveData = {}
            saveData.title = this.title
            saveData.content = this.content
            saveData.mno = 1
            axios.post('http://172.30.1.59:3000/write', JSON.stringify(saveData), {
                headers: { "Content-Type": "application/json" }
            }).then((res) => alert("통신결과 : " + res.data.result)
            ).catch((err) => alert('문제가 발생했습니다' + err))
        }
    }
};
</script>
<style>
.write {
    width: 100%;
    height: 500px;
    background-color: rgb(114, 255, 255);
    padding: 10px;
}

.write input {
    width: 100%;
    height: 30px;
    margin-bottom: 5px;
    box-sizing: border-box;
}

.write textarea {
    width: 100%;
    height: 300px;
    box-sizing: border-box;
}
</style>

새 페이지 만들면 라우터에 추가해준다.
router/index.js

const routes = [
  { path: "/", component: IndexPage },
  { path: "/boardList", component: BoardList },
  { path: "/login", component: () => import("../views/LoginPage.vue") },
  { path: "/detail", component: () => import("../views/DetailPage.vue") },
  { path: "/write", component: () => import("../views/WritePage.vue") }
];

삭제하기

DetailPage.vue

버튼 클릭 시 del() 함수 실행할 것.

del() {
    //alert(bno)
    if (confirm("삭제하시겠습니까?")) {
        axios({
            url: "http://172.30.1.59:3000/del",
            method: "post",
            params: { bno: this.detail.board_no }
        }).then((res) => {
            if (res.data.result == 1) {
                this.$router.push({ path: "./boardList", query: this.requestBody, });
            } else {
                alert('문제가 발생했습니다')
            }
        }).catch((err) => {
            alert(err)
        })
    }
},

이러면 삭제 완료


수정하기까지 하면 crud 끝

2개의 댓글

comment-user-thumbnail
2024년 4월 5일

난 왜 글이 안불러와질까요

1개의 답글