Description
用 Vue.js 搭建前端,使用 echarts 做數據可視化,數據從 Flask 搭建的后端提供的 API 獲取,后端用 pymysql 訪問 MySQL 獲取數據。寫一個盡可能簡單的 demo 實現這一套流程。
Solution
我們從 MySQL 中的數據開始一步步往前端搭建。為了盡可能降低耦合,我們假設,前端、后端、數據庫放在三台不同的服務器上。在本示例中,數據庫在外部服務器上,通過 SSH Tunnel 訪問;前端和后端分別運行在本機的 8080 和 5000 端口。
https://github.com/mollnn/Bilibili-Visualization
(依賴根據報錯提示安裝一下吧……懶得寫了)
數據庫查詢接口
為了偷懶,我們對數據庫訪問的過程做一些封裝,使得輸入數據庫名和查詢語句即可直接獲取結果。
該部分代碼來源於網絡。
// connectorSSHMySQL.py
import pymysql
from sshtunnel import SSHTunnelForwarder
def SSHMysql(DB, SQL):
server = SSHTunnelForwarder(
ssh_address_or_host=('?.?.com', 22), # 指定ssh登錄的跳轉機的address
ssh_username='?', # 跳轉機的用戶
ssh_password='?', # 跳轉機的密碼
local_bind_address=('127.0.0.1', 1268), # 映射到本機的地址和端口
remote_bind_address=('localhost', 3306)) # 數據庫的地址和端口
server.start() # 啟用SSH
db = pymysql.connect(
host="127.0.0.1", # 映射地址local_bind_address IP
port=1268, # 映射地址local_bind_address端口
user="root",
passwd="?",
database=DB,
charset='utf8')
cursor = db.cursor()
cursor.execute(SQL.encode('utf8'))
data = cursor.fetchall()
cursor.close()
return data
def query(DB, SQL):
return SSHMysql(DB, SQL)
if __name__ == "__main__":
SQL = "SELECT * FROM Danmu;"
SelectResult = SSHMysql('bilibili', SQL)
print(SelectResult)
Flask 后端
后端的任務主要是返回 JSON 格式的數據。這里沒有引入帶參數的查詢。提供了兩個 API 接口,一個從數據庫中拉取,一個直接硬編碼數據。用於不同情況的測試。
// app.py
from flask import Flask, jsonify, render_template
from flask.helpers import make_response
import connectorSSHMySQL as msql
from flask_cors import CORS
app = Flask(__name__)
CORS(app, resources=r'/*')
@app.route('/api/demo/')
def api_demo():
return jsonify(msql.query("bilibili", "select view, danmaku from Vinfo;"))
@app.route('/api/test/')
def api_test():
ans = jsonify({
"product": [5, 20, 36, 10, 10, 20]
})
return make_response(ans)
if __name__ == '__main__':
app.run(debug=True)
echarts 圖表組件
創建組件,其名為 chart1,從官網上抄個 option,加上從后端接口拉數據的 vue-resource 操作。注意 get 路徑一定要加 http://,同時盡量設置一下 header,畢竟是跨域請求。
// chart1.vue
<template>
<div>
<div id="echartContainer" style="width: 100%; height: 500px"></div>
</div>
</template>
<script>
export default {
name: "chart1",
data() {
return {};
},
methods: {
draw() {
var myChart = this.$echarts.init(
document.getElementById("echartContainer"),
"infographic"
);
myChart.setOption({
xAxis: {},
yAxis: {},
series: [
{
symbolSize: 5,
data: [],
type: "scatter",
},
],
});
this.$http
.get("http://localhost:5000/api/demo/", {
headers: { "Access-Control-Allow-Origin": "*" },
})
.then((res) => {
myChart.hideLoading();
myChart.setOption({ series: [{ data: res.data }] });
});
},
},
mounted() {
this.draw();
},
};
</script>
<style></style>
Vue.js 前端
把各種東西在 main.js 中引入一下,並在 app 中注冊和創建一個 chart1。
// main.js
import Vue from 'vue'
import App from './App.vue'
import VueResource from 'vue-resource'
import * as VueJsonp from 'vue-jsonp'
import echarts from 'echarts'
Vue.use(VueJsonp)
Vue.use(VueResource)
Vue.prototype.$echarts = echarts
new Vue({
el: '#app',
render: h => h(App)
})
// App.vue
<template>
<div class="main">
<chart1 />
</div>
</template>
<script>
import chart1 from "./components/chart1.vue";
export default {
components: {
chart1,
},
};
</script>
項目結構

測試
在后端根目錄下
python app.py
在前端根目錄下
npm run dev
瀏覽器訪問 localhost:8080,看到這么個圖

這反映的是 B 站部分視頻的彈幕數量和播放量的關系。
魔改指南
后端加 API 直接添路由改 SQL 即可。
前端加圖,從 echarts 官網拿 option 改改,把 option 的 JSON 直接貼到 myChart.setOption(...) 中,修改 this.$http.get("...",...)... 中 GET 的 URL。
