Nodejs+vue(express + Element-ui + mySQL)全棧——實現簡單的博客文章管理后台


剛開始學習前端的時候,總覺得全棧離自己很遠,夢想着有一天我也能自己寫完整個項目。經過這段時間的學習,從慢慢接觸到一點點深入,我發現在我眼里的全棧開發其實並沒有那么復雜。這次我使用一個簡單的demo作為例子,向大家簡單介紹一下如何獨自完成前端和后端。

簡單的博客文章管理后台:文章的增刪改查,這里我們把 新建文章 作為一個 view (相當於一個頁面),刪除和修改放到一個 view,文章列表作為一個 view,總共三個view。

 

第一步:打開終端,創建一個vue項目,demo是自己命名的文件名,配置直接default默認的就好。

1 vue create demo

第二步:項目創建好之后按照提示進入項目文件夾,並運行它。

 

這時我們打開上面的任意一個地址(ctrl + 單擊),會跳轉到這個頁面

這個頁面對應到項目文件就是 src 下面的 App.vue ,相當於 vue 的根組件,里面包含了一個子組件HelloWorld,可以在 components 文件夾找到。

因為我們要寫一個簡單的文章管理后台,基本都是表單內容,用不到能復用的子組件,所以我們將子組件HelloWorld刪除。

 

第三步:在項目文件打開終端,安裝 Element-ui 和 router

 

在 src 下創建一個 plugins 文件夾,里面創建一個 element.js 文件,寫入以下代碼:

1 import Vue from 'vue'
2 import Element from 'element-ui'
3 import 'element-ui/lib/theme-chalk/index.css'
4 
5 Vue.use(Element)

 

第四步:到這里我們先寫后端,在項目根目錄下新建 server 文件夾,在里面新建一個 index.js文件

 

寫入以下代碼

 1 const express = require('express') // 引入 express
 2 const app = express() // 實例一個 express 對象
 3 
 4 app.use(require('cors')()) // 解決跨域
 5 app.use(express.json()) // express處理json數據
 6 
 7 
 8  
 9 const mysql = require('mysql'); //調用 MySQL模塊
10 
11 // 創建連接
12 var db = mysql.createConnection({
13   host: 'localhost', 
14   user: 'root', // 用戶名
15   password: '123456', // 密碼
16   database: 'Article',// 數據庫名
17   port: 3306   // 端口號
18 })
19 db.connect( (err) => { 
20   if(err) throw err;
21   console.log('連接成功');
22 })
23 
24 
25 app.get('/', (req, res) => {
26   res.send('index')
27 }) 
28 
29 // 新增文章
30 app.post('/api/article', (req, res) => { 
31   let data = req.body; 
32   let sql = "INSERT INTO posts SET ?"; 
33   db.query(sql, data, (err, result) => {
34     if(err) {
35       console.log(err);
36     } else {
37       console.log(result);
38       res.send(result)
39     }
40   })
41 })
42 
43 // 獲取文章列表
44 app.get('/api/article', (req, res) => {
45   let sql = "SELECT * FROM posts";
46   db.query(sql, (err, result) => {
47     if(err) {
48       console.log(err);
49     } else {
50       console.log(result);
51       res.json(result);
52     }
53   })
54 })
55 
56 // 刪除文章
57 app.delete('/api/article/:id', (req, res) => {
58   let sql = `DELETE FROM posts WHERE id= ${req.params.id}`;
59   db.query(sql, (err, result) => {
60     if(err) {
61       console.log(err);
62     } else {
63       console.log(result);
64       res.json(result);
65     }
66   })
67 })
68 
69 // 獲取文章詳情
70 app.get('/api/article/:id', (req, res) => {
71   let sql = `SELECT * FROM posts WHERE id= ${req.params.id}`
72   db.query(sql, (err, result) => {
73     if(err) {
74       console.log(err);
75     } else {
76       res.json(result)
77     }
78   })
79 })
80 
81 // 修改文章
82 app.put('/api/article/:id', (req, res) => {
83   let newTitle = req.body.title;
84   let newBody = req.body.body;
85   let sql = `UPDATE posts SET title = '${newTitle}',body = '${newBody}' WHERE ID = ${req.params.id}`
86   db.query(sql, (err, result) => {
87     if(err) {
88       console.log(err);
89     } else {
90       res.json(result)
91     }
92   })
93 })
94 
95 // 監聽端口3000
96 app.listen(3000, () => {
97   console.log('http://localhost:3000/')
98 })

 

第五步:創建三個view,分別命名為CreateArticle,EditArticle,ListArticle.

 

寫入以下代碼:

CreateArticle.vue

 1 <template>
 2   <el-form @submit.native.prevent="saveArticle" ref="form" :model="article" label-width="80px">
 3     <el-form-item label="文章標題">
 4       <el-input v-model="article.title"></el-input>
 5     </el-form-item>
 6     
 7     <el-form-item label="文章內容">
 8       <el-input type="textarea" v-model="article.body"></el-input>
 9     </el-form-item>
10     <el-form-item>
11       <el-button type="primary" native-type="submit">立即創建</el-button>
12       <el-button>取消</el-button>
13     </el-form-item>
14   </el-form>
15 </template>
16 <script>
17 export default {
18   data() {
19     return {
20       article: {
21         title: "",
22         body: ""
23       }
24     };
25   },
26   methods: {
27     saveArticle() {
28       this.$http.post('/article', this.article).then(res => {
29         console.log(res.config.data)
30         this.$message({
31           message: '文章創建成功',
32           type: 'success'
33         });
34         this.$router.push('/article/index')
35       })
36     }
37   }
38 };
39 </script>

 

EditArticle.vue

 1 <template>
 2   <el-form @submit.native.prevent="saveArticle" ref="form" :model="article" label-width="80px">
 3     <el-form-item label="文章標題">
 4       <el-input v-model="article.title"></el-input>
 5     </el-form-item>
 6     
 7     <el-form-item label="文章內容">
 8       <el-input type="textarea" v-model="article.body"></el-input>
 9     </el-form-item>
10     <el-form-item>
11       <el-button type="primary" native-type="submit">保存</el-button>
12       <el-button>取消</el-button>
13     </el-form-item>
14   </el-form>
15 </template>
16 <script>
17 export default {
18   data() {
19     return {
20       article: {
21         title: "",
22         body: ""
23       }
24     };
25   },
26   methods: {
27     saveArticle() {
28       this.$http.put(`/article/${this.$route.params.id}`, this.article).then(res => {
29         console.log(res.config.data)
30         this.$message({
31           message: '文章更新成功',
32           type: 'success'
33         });
34         this.$router.push('/article/index')
35       })
36     },
37     fetch() {
38       this.$http.get(`/article/${this.$route.params.id}`).then(res => {
39         
40         this.article = res.data[0]
41       })
42     }
43   },
44   created() {
45     this.fetch()
46   }
47 };
48 </script>

ListArticle.vue

 1 <template>
 2   <div>
 3     <el-table :data="articles">
 4       <el-table-column prop="title" label="標題" width="140"></el-table-column>
 5       <el-table-column prop="body" label="內容" width="220"></el-table-column>
 6       <el-table-column fixed="right" label="操作" width="100">
 7         <template slot-scope="scope">
 8           <el-button @click="edit(scope.row.id)" type="text" size="small">編輯</el-button>
 9           <el-button @click="remove(scope.row.id)" type="text" size="small">刪除</el-button>
10         </template>
11       </el-table-column>
12     </el-table>
13   </div>
14 </template>
15 
16 <script>
17 export default {
18   data() {
19     return {
20       articles: []
21     };
22   },
23   methods: {
24     fetch() {
25       this.$http.get("/article").then(res => {
26       this.articles = res.data
27     })
28     },
29     edit(id) {
30       this.$router.push(`/article/${id}/edit`)
31     },
32     remove(id) {
33       this.$http.delete(`/article/${id}`).then(res => {
34         console.log(res.data)
35         this.$message({
36           message: '文章刪除成功',
37           type: 'success'
38         });
39       })
40       this.fetch()
41     }
42   },
43   created() {
44     this.fetch()
45   }
46 };
47 </script>

 

修改 App.vue

 1 <template>
 2   <el-container style="height: 100vh; border: 1px solid #eee">
 3     <el-aside width="200px" style="background-color: rgb(238, 241, 246)">
 4       <el-menu router :default-openeds="['1']">
 5         <el-submenu index="1">
 6           <template slot="title">
 7             <i class="el-icon-tickets"></i>內容管理
 8           </template>
 9           <el-menu-item index="/article/index">文章列表</el-menu-item>
10           <el-menu-item index="/article/create">新建文章</el-menu-item>
11         </el-submenu>
12       </el-menu>
13     </el-aside>
14 
15     <el-container>
16       <el-header style="text-align: right; font-size: 12px">
17         <el-dropdown>
18           <i class="el-icon-setting" style="margin-right: 15px"></i>
19           <el-dropdown-menu slot="dropdown">
20             <el-dropdown-item>查看</el-dropdown-item>
21             <el-dropdown-item>新增</el-dropdown-item>
22             <el-dropdown-item>刪除</el-dropdown-item>
23           </el-dropdown-menu>
24         </el-dropdown>
25         <span>王小虎</span>
26       </el-header>
27 
28       <el-main>
29         <router-view></router-view>
30       </el-main>
31     </el-container>
32   </el-container>
33 </template>
34 
35 <style>
36 html,
37 body {
38   padding: 0;
39   margin: 0;
40 }
41 .el-header {
42   background-color: #b3c0d1;
43   color: #333;
44   line-height: 60px;
45 }
46 
47 .el-aside {
48   color: #333;
49 }
50 </style>
51 
52 <script>
53 export default {
54   data() {
55     const item = {
56       date: "2016-05-02",
57       name: "王小虎",
58       address: "上海市普陀區金沙江路 1518 弄"
59     };
60     return {
61       tableData: Array(20).fill(item)
62     };
63   }
64 };
65 </script>

 

修改 main.js 

 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 
 4 import router from './router' // 引入 router文件夾下的 index.js
 5 import './plugins/element.js' // 引入 element-ui
 6 
 7 Vue.config.productionTip = false 
 8 
 9 import axios from 'axios' // 引入 axios
10 Vue.prototype.$http = axios.create({ // 將 axios方法定義到vue的原型上
11   baseURL: 'http://127.0.0.1:3000/api' // 基礎url,前端發起請求要先拼接上這個地址 
12 })
13 
14 new Vue({
15   router, 
16   render: h => h(App)
17 }).$mount('#app')

修改 router 文件夾下方的 index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
// 分別引入三個 view
import ListArticle from '../views/ListArticle.vue' 
import CreateArticle from '../views/CreateArticle.vue'
import EditArticle from '../views/EditArticle.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    redirect: '/article/index' // 訪問根路徑,重定向到 /article/index
  },
  {
    path: '/article/index',
    name: 'List-article',
    component: ListArticle
  },
  {
    path: '/article/create',
    name: 'create-article',
    component: CreateArticle
  },
  {
    path: '/article/:id/edit',
    name: 'edit-article',
    component: EditArticle
  }
]

const router = new VueRouter({
  routes
})

export default router

到此所有的配置完畢

 

最后在項目目錄打開終端執行

1 npm run serve

 

在server文件夾目錄打開終端執行

1 node server

 

最終效果

 

 

數據庫中也能找到錄入的數據。

 

結語:陰郁的日子總會過去,黎明就在前方,武漢加油!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM