Vue.js 學習筆記之三:與伺服器的資料互動
阿新 • • 發佈:2020-10-06
顯而易見的,之前的`02_toDoList`存在著一個很致命的缺陷。那就是它的資料只存在於瀏覽器端,一但使用者關閉或重新載入頁面,他之前加入到程式中的資料就會全部丟失,一切又恢復到程式的初始狀態。要想解決這個問題,就需要 Web 應用的前端在適當的時間將獲得的輸入資料儲存到後端伺服器上,然後在需要時再從伺服器上獲取這些資料。這部分筆記將記錄如何利用 Vue.js 框架來完成 Web 應用程式的前端與後端之間的互動。這一次,我同樣會通過構建一個"留言本"應用來貫穿整個學習過程。
首先需要在`code`目錄下依次執行`npm install express body-parser knex`和`npm install sqlite3@<指定的版本>`命令,安裝接下來建立 Web 服務所需要的後端元件(需要注意的是,這裡安裝的`sqlite3`要根據`knex`安裝後的提示選擇對應的版本)。接下來,在`code`目錄下建立一個名為`03_Message`的目錄,並在該目錄下執行`npm init -y`命令,將其初始化成一個 Node.js 專案。在這裡,之所以將服務端所需要的元件安裝在專案目錄的上一級目錄中,是因為我接下來還需要在專案目錄中安裝前端元件,並將其開放給瀏覽器端訪問,所以前後端所需要的元件最好分開存放。
現在,我要基於 Express 框架來建立一個 Web 服務了。具體做法就是在`code/03_Message`目錄下建立一個名為`index.js`的伺服器端指令碼檔案,並在其中輸入如下程式碼:
```JavaScript
const path = require('path');
const express = require('express')
const bodyParser = require('body-parser');
const knex = require('knex');
const port = 8080;
// 建立伺服器例項
const app = express();
// 配置 public 目錄,將其開放給瀏覽器端
app.use('/', express.static(path.join(__dirname, 'public')));
// 配置 node_modules 目錄,將其開放給瀏覽器端
app.use('/node_modules', express.static(path.join(__dirname, 'node_modules')));
//配置 body-parser 中介軟體,以便獲取 POST 請求資料。
app.use(bodyParser.urlencoded({ extended : false}));
app.use(bodyParser.json());
// 建立資料庫連線物件:
const appDB = knex({
client: 'sqlite3', // 設定要連線的資料型別
connection: { // 設定資料庫的連結引數
filename: path.join(__dirname, 'data/database.sqlite')
},
debug: true, // 設定是否開啟 debug 模式,true 表示開啟
pool: { // 設定資料庫連線池的大小,預設為{min: 2, max: 10}
min: 2,
max: 7
},
useNullAsDefault: true
});
appDB.schema.hasTable('notes') // 檢視資料庫中是否已經存在 notes 表
.then(function(exists) {
if(exists == false) { // 如果 notes 表不存在就建立它
appDB.schema.createTable('notes', function(table) {
// 建立 notes 表:
table.increments('uid').primary();// 將 uid 設定為自動增長的欄位,並將其設為主鍵。
table.string('userName'); // 將 userName 設定為字串型別的欄位。
table.string('noteMessage'); // 將 notes 設定為字串型別的欄位。
});
}
})
.then(function() {
// 請求路由
// 設定網站首頁
app.get('/', function(req, res) {
res.redirect('/index.htm');
});
// 響應前端獲取資料的 GET 請求
app.get('/data/get', function(req, res) {
appDB('notes').select('*')
.then(function(data) {
console.log(data);
res.status(200).send(data);
}).catch(function() {
res.status(404).send('找不到相關資料');
});
});
// 響應前端刪除資料的 POST 請求
app.post('/data/delete', function(req, res) {
appDB('notes').delete()
.where('uid', '=', req.body['uid'])
.catch(function() {
res.status(404).send('刪除資料失敗');
});
res.send(200);
});
// 響應前端新增資料的 POST 請求
app.post('/data/add', function(req, res) {
console.log('post data');
appDB('notes').insert(
{
userName : req.body['userName'],
noteMessage : req.body['noteMessage']
}
).catch(function() {
res.status(404).send('新增資料失敗');
});
res.send(200);
});
// 監聽 8080 埠
app.listen(port, function(){
console.log(`訪問 http://localhost:${port}/,按 Ctrl+C 終止服務!`);
});
})
.catch(function() {
// 斷開資料庫連線,並銷燬 appDB 物件
appDB.destroy();
});
```
由於 Vue.js 框架的特點,前端需要後端提供的服務除了獲取指定的 HTML 和 JavaScript 檔案之外,主要就是對資料庫的增刪改查操作了,所以在上面這個服務中,除了將`public`、`node_modules`目錄整體開放給瀏覽器端訪問之外,主要提供了一個基於 GET 請求的資料查詢服務,和兩個基於 POST 請求的資料新增與刪除操作。
接下來,我可以開始前端部分的構建了。首先需要在`code/03_Message`目錄下執行`npm install vue axios`命令,安裝接下來所要用到的前端元件(該命令會自動生成一個`node_modules`目錄,正如上面所說,該目錄會被服務端指令碼整體開放給瀏覽器端)。然後,繼續在同一目錄下建立`public`目錄,並在其中建立一個名為`index.htm`的檔案,其程式碼如下:
```HTML
``` 這個頁面主要被分為了兩個部分,第一部分會根據`notes`中的資料使用`v-for`指令迭代顯示已被新增到資料庫中的留言,並提供了一個`刪除`按鈕以便刪除指定的留言(使用`v-on`指令繫結單擊事件處理函式)。第二部分則是一個用於`新增留言`的輸入介面,這裡使用了`v-model`指令來獲取需要使用者輸入的`userName`和`Message`資料。現在,我需要來建立相應的 Vue 物件例項了,為此,我會在剛才建立的`public`目錄下再建立一個`js`目錄,並在其中建立名為`main.js`的自定義前端指令碼檔案,其程式碼如下: ```JavaScript // 程式名稱: Message // 實現目標: // 1. 學習 axios 庫的使用 // 2. 掌握如何與伺服器進行資料互動 const app = new Vue({ el: '#app', data:{ userName: '', Message: '', notes: [] }, created: function() { that = this; axios.get('/data/get') .then(function(res) { that.notes = res.data; }) .catch(function(err) { console.error(err); }); }, methods:{ addNew: function() { if(this.userName !== '' && this.Message !== '') { that = this; axios.post('/data/add', { userName: that.userName, noteMessage: that.Message }).catch(function(err) { console.error(err); }); this.Message = ''; this.userName = ''; axios.get('/data/get') .then(function(res) { that.notes = res.data; }) .catch(function(err) { console.error(err); }); } }, remove: function(id) { if(uid > 0) { that = this; axios.post('/data/delete', { uid : id }).catch(function(err) { console.error(err); }); axios.get('/data/get') .then(function(res) { that.notes = res.data; }) .catch(function(err) { console.error(err); }); } } } }); ``` 這個 Vue 例項與我們之前建立的大同小異,主要由以下四個成員組成: - `el`成員:用於以 CSS 選擇器的方式指定 Vue 例項所對應的元素容器,在這裡,我指定的是``元素。 - `data`成員:用於設定頁面中繫結的資料,這裡設定了以下三個資料變數: - `notes`:這是一個數組變數,用於存放已被新增的留言記錄。 - `userName`:這是一個字串變數,用於獲取"使用者名稱"資料。 - `Message`:這是一個字串變數,用於獲取"留言"資料。 - `created`成員:用於在程式載入時做初始化操作,在這裡,我從服務端讀取了已被新增的留言記錄,並將其載入到`notes`變數中。 - `methods`成員:用於定義頁面中繫結的事件處理函式,這裡定義了以下兩個事件處理函式: - `addNew`:用於新增新的留言記錄,並同步更新`notes`中的資料。 - `remove`:用於刪除指定的留言記錄,並同步更新`notes`中的資料。 通常情況下,我們在 Vue.js 框架中會選擇使用 axios 這樣的第三方元件來處理髮送請求和接收響應資料的工作,引入該元件的方式與引入 Vue.js 框架的方式是一樣的,可以像上面一樣先下載到本地,然後使用` ``` 需要注意的是,該引用標籤在 HTML 頁面中的位置必須要在自定義 JavaScript 指令碼檔案(即`main.js`)的引用標籤之前。當然,我在上述程式碼中只展示了`axios.get`和`axios.post`這兩個最常用方法的基本用法,由於該元件支援返回 Promise 物件,所以我們可以採用`then`方法呼叫鏈來處理響應資料和異常狀況。關於 axios 元件更多的使用方法,可以參考相關文件([http://www.axios-js.com/zh-cn/docs/](http://www.axios-js.com/zh-cn/docs/))
留言本
{{ note.userName }} 說:{{ note.noteMessage }}請留言:
``` 這個頁面主要被分為了兩個部分,第一部分會根據`notes`中的資料使用`v-for`指令迭代顯示已被新增到資料庫中的留言,並提供了一個`刪除`按鈕以便刪除指定的留言(使用`v-on`指令繫結單擊事件處理函式)。第二部分則是一個用於`新增留言`的輸入介面,這裡使用了`v-model`指令來獲取需要使用者輸入的`userName`和`Message`資料。現在,我需要來建立相應的 Vue 物件例項了,為此,我會在剛才建立的`public`目錄下再建立一個`js`目錄,並在其中建立名為`main.js`的自定義前端指令碼檔案,其程式碼如下: ```JavaScript // 程式名稱: Message // 實現目標: // 1. 學習 axios 庫的使用 // 2. 掌握如何與伺服器進行資料互動 const app = new Vue({ el: '#app', data:{ userName: '', Message: '', notes: [] }, created: function() { that = this; axios.get('/data/get') .then(function(res) { that.notes = res.data; }) .catch(function(err) { console.error(err); }); }, methods:{ addNew: function() { if(this.userName !== '' && this.Message !== '') { that = this; axios.post('/data/add', { userName: that.userName, noteMessage: that.Message }).catch(function(err) { console.error(err); }); this.Message = ''; this.userName = ''; axios.get('/data/get') .then(function(res) { that.notes = res.data; }) .catch(function(err) { console.error(err); }); } }, remove: function(id) { if(uid > 0) { that = this; axios.post('/data/delete', { uid : id }).catch(function(err) { console.error(err); }); axios.get('/data/get') .then(function(res) { that.notes = res.data; }) .catch(function(err) { console.error(err); }); } } } }); ``` 這個 Vue 例項與我們之前建立的大同小異,主要由以下四個成員組成: - `el`成員:用於以 CSS 選擇器的方式指定 Vue 例項所對應的元素容器,在這裡,我指定的是``元素。 - `data`成員:用於設定頁面中繫結的資料,這裡設定了以下三個資料變數: - `notes`:這是一個數組變數,用於存放已被新增的留言記錄。 - `userName`:這是一個字串變數,用於獲取"使用者名稱"資料。 - `Message`:這是一個字串變數,用於獲取"留言"資料。 - `created`成員:用於在程式載入時做初始化操作,在這裡,我從服務端讀取了已被新增的留言記錄,並將其載入到`notes`變數中。 - `methods`成員:用於定義頁面中繫結的事件處理函式,這裡定義了以下兩個事件處理函式: - `addNew`:用於新增新的留言記錄,並同步更新`notes`中的資料。 - `remove`:用於刪除指定的留言記錄,並同步更新`notes`中的資料。 通常情況下,我們在 Vue.js 框架中會選擇使用 axios 這樣的第三方元件來處理髮送請求和接收響應資料的工作,引入該元件的方式與引入 Vue.js 框架的方式是一樣的,可以像上面一樣先下載到本地,然後使用` ``` 需要注意的是,該引用標籤在 HTML 頁面中的位置必須要在自定義 JavaScript 指令碼檔案(即`main.js`)的引用標籤之前。當然,我在上述程式碼中只展示了`axios.get`和`axios.post`這兩個最常用方法的基本用法,由於該元件支援返回 Promise 物件,所以我們可以採用`then`方法呼叫鏈來處理響應資料和異常狀況。關於 axios 元件更多的使用方法,可以參考相關文件([http://www.axios-js.com/zh-cn/docs/](http://www.axios-js.com/zh-cn/docs/))