接上篇
1 前 言
1.1 業(yè)務(wù)場(chǎng)景
實(shí)現(xiàn)數(shù)據(jù)監(jiān)控的系統(tǒng)。有線圖、柱狀圖、地圖,并具有定時(shí)刷新的功能。
1.2 業(yè)務(wù)分析
上一篇分析的步驟大致有:
- 系統(tǒng)搭建
vue-clivuex記錄登錄信息vue-router路由跳轉(zhuǎn)- 3個(gè)維度的頁(yè)面,提取出共用的組件
- 各個(gè)組件開(kāi)發(fā)
- 調(diào)節(jié)樣式,增加UI
- 加入后臺(tái)接口數(shù)據(jù)
- 優(yōu)化顯示
- 測(cè)試
- 上線
上一篇介紹了 1-6 部分。本篇將介紹一下剩下的 7-10 部分。
????
主要內(nèi)容是 <font color=red>對(duì)數(shù)據(jù)的處理方式</font> 和 <font color=red>整體的數(shù)據(jù)邏輯</font> 。
望各位看官多提 建議和不足 哈,也希望能本篇能給需要人帶來(lái) 啟發(fā)。
成品效果圖不方便發(fā),還是用上一篇,純前端的效果圖吧。
2 正 文
2.1 請(qǐng)求處理數(shù)據(jù)
Vue 中 與后臺(tái)交互通常使用的是 axios
2.1.1 安 裝
npm i axios
也可通過(guò)cdn引用
2.1.2 定 義
新建一個(gè)api.js
// api.js
import axios from 'axios'
const http = axios.create ({
baseURL : apiurl, // 連接后端地址
timeout : 1000 * 30, // 超時(shí)時(shí)間,單位為毫秒
headers : {}, // 請(qǐng)求頭,可添加'Authorization'、'X-Requested-With'、'Accept-Language'、'token'等
})
// 請(qǐng)求攔截
http.interceptors.request.use(config =>{
// 可添加自己的設(shè)置,如修改參數(shù)、增加參數(shù)、修改headers
return config
},error =>{
// 可添加報(bào)錯(cuò)處理
return Promise.reject(error)
})
// 響應(yīng)攔截
http.interceptors.response.use(response =>{
// 可添加處理邏輯
return response
},error =>{
return Promise.reject(error)
})
export default http
同時(shí)可在main.js中添加一個(gè)自定義全局對(duì)象,或者可在單獨(dú)頁(yè)面中引用
// main.js
import http from './api.js'
Vue.prototype.$http = http
2.1.3 使 用
a. get請(qǐng)求
在頁(yè)面中處理時(shí)
query(){
this.$http.get('/xxx/xxx?id='+id).then(res =>{
// 返回的處理
console.log(res)
// res 一般包含code data
},rej =>{
// 報(bào)錯(cuò)的處理
console.log(rej)
})
}
b. post請(qǐng)求
new(){
this.$http.post('/xxx/xxx',{
id : '123',
}).then(res =>{
// 返回的處理
console.log(res)
// res 一般包含code data
},rej =>{
// 報(bào)錯(cuò)的處理
console.log(rej)
})
}
c. 其他請(qǐng)求
經(jīng)常使用到的還有
put 多用于更新操作
delete 多用于刪除操作
具體要看后臺(tái)提供的功能接口方式
d. 多個(gè)請(qǐng)求
比如,我在進(jìn)來(lái)頁(yè)面后,要同時(shí)獲取要2個(gè)線形圖、數(shù)字、地圖、柱狀圖、表格的數(shù)據(jù)
一般情況下,各個(gè)數(shù)據(jù)都是單獨(dú)的接口來(lái)提供的。這樣我們就需要至少6個(gè)接口。
async query(){
let that = this
await axios.all([that.get1(), that.get2(), that.get3()]).then(axios.spread((res1, res2, res3) =>{
// res1 為 get1 的返回
// res2 為 get2 的返回
// res3 為 get3 的返回
}))
}
get1(){
return this.$http.get('/xxx/xxx')
}
get2(){
return this.$http.get('/xxx/xxx')
}
get3(){
return this.$http.get('/xxx/xxx')
}
2.2 登 錄
功能很簡(jiǎn)單,用戶輸入用戶名、密碼、驗(yàn)證碼,點(diǎn)擊登錄。
2.2.1 獲取uuid
出于對(duì)登錄時(shí)效以及安全性的考慮。在登錄驗(yàn)證時(shí),后臺(tái)根據(jù) uuid 和通過(guò) uuid 獲取到的驗(yàn)證碼進(jìn)行校驗(yàn)。
這里列出一些獲取 uuid 的方法。來(lái)源于:網(wǎng)絡(luò)。
方法一:
getUUID () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16)
})
},
方法二:
generateUUID() {
var d = new Date().getTime()
if (window.performance && typeof window.performance.now === "function") {
d += performance.now()
}
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16)
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16)
})
return uuid
}
方法三:
guid() {
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4())
}
方法四:
/*
指定長(zhǎng)度和基數(shù)
*/
function uuid2(len, radix) {
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
var uuid = [],
i;
radix = radix || chars.length;
if (len) {
for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
} else {
var r;
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4';
for (i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random() * 16;
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
}
}
}
return uuid.join('');
}
2.2.2 密碼加密
--input
type="password" 可使輸入框中內(nèi)容隱藏
傳輸時(shí),我使用了md5加密
npm i -S js-md5
import md5 from 'js-md5'
let enCode = md(code)
然后就是調(diào)用后臺(tái)接口將你的用戶名、密碼、驗(yàn)證碼發(fā)送進(jìn)行驗(yàn)證登錄。
2.2.3 存儲(chǔ)登錄信息
使用過(guò) Vue 的童鞋都清楚,使用vuex的時(shí)候,進(jìn)行刷新頁(yè)面,store中的數(shù)據(jù)就會(huì)重置。
會(huì)防止用戶在刷新頁(yè)面后數(shù)據(jù)無(wú)法獲取的情況,一般會(huì)將數(shù)據(jù)同時(shí)儲(chǔ)存到 sessionStorage 或 localStorage
兩者區(qū)別這里就不介紹了。
// 儲(chǔ)存session,具體放在哪個(gè)位置根據(jù)實(shí)際業(yè)務(wù)
// 我這里放在了登錄驗(yàn)證通過(guò)之后,當(dāng)然有很多參數(shù),可使用對(duì)象類型轉(zhuǎn)成json ----JSON.stringify(info)
sessionStorage.setItem('info', '123')
// store.js
store = {
state : JSON.parse(sessionStorage.getItem('info')) || {}
}
這樣頁(yè)面刷新后,store 會(huì)從 sessionStorage 拿到我們的數(shù)據(jù)
2.3 業(yè)務(wù)頁(yè)面
業(yè)務(wù)頁(yè)面分了3個(gè)維度。
這里介紹2個(gè)維度的實(shí)現(xiàn)。
2.3.1 整體邏輯
單獨(dú)的組件只處理數(shù)據(jù)的展示
如線形圖單獨(dú)寫在一個(gè)組件中
我在需要的頁(yè)面中進(jìn)行引用,傳入數(shù)據(jù)進(jìn)行顯示。
- 用戶登錄驗(yàn)證后,儲(chǔ)存業(yè)務(wù)
ID到session中,從登錄頁(yè)面跳轉(zhuǎn)到 層級(jí)1 頁(yè)面。 - 進(jìn)入 層級(jí)1 后,
created中增加初始化方法。就是使用了上面介紹的axios.all - 拿到各數(shù)據(jù)后,分別渲染到各個(gè)組件中。
- 初始化完成后,觸發(fā)定時(shí)刷新開(kāi)發(fā)。
- 根據(jù)定時(shí)器的時(shí)間,觸發(fā)需要刷新的功能,同上
axios.all和處理結(jié)果。 - 點(diǎn)擊層級(jí)1中某個(gè)數(shù)據(jù),記錄層級(jí)2需要的
ID2到session中,關(guān)閉定時(shí)刷新,跳轉(zhuǎn)到 層級(jí)2 頁(yè)面。 - 進(jìn)入 層級(jí)2 后,同層級(jí)1,先進(jìn)行初始化,再進(jìn)行定時(shí)刷新。
- 層級(jí)3 以及 返回 的邏輯都基本和上面一樣。
下面介紹一些可能會(huì)有 疑問(wèn) 的地方
2.3.2 層級(jí)頁(yè)面舉例
相當(dāng)于介紹了一些父子組件的一些處理。
// 層級(jí)1.vue
<template>
<div id="xxx">
<a-com ref="aRef" :args="argA"/>
<b-com ref="bRef" :args="argB"/>
</div>
</template>
<script>
import Acom from './a.vue'
import Bcom from './b.vue'
import store from './store.js'
export default {
components : {
'a-com':Acom,
'b-com':Bcom,
},
created(){
// 初始化方法
this.init()
},
mounted(){
// 定時(shí)查詢方法
this.timeq()
},
data() {
return {
// 傳入子組件的數(shù)據(jù),可可以使用store
argA : {},
argB : {},
// 定時(shí)開(kāi)關(guān)
timimg : false,
}
},
methods: {
async init(){
let id1 = store.state.info.id1
await this.query(id1)
this.timimg = true
},
timeq(){
// 這里定義了 5S 刷新一次
let that = this
this.timequery = setInterval(() =>{
if(timimg){
that.querytime(store.state.info.id1)
}
},5000)
},
async query(id){
let that = this
await axios.all([that.get1(id), that.get2(id)]).then(axios.spread((res1, res2) =>{
// 數(shù)據(jù)傳入組件a,觸發(fā)組件a的初始化方法
that.argA = res1.data
that.$refs.aRef.init();
// 數(shù)據(jù)傳入組件b,觸發(fā)組件b的初始化方法
that.argB = res2.data
that.$refs.bRef.init();
}))
},
querytime(id){
// 同 query()
},
get1(id){
return this.$http.get('xxx')
},
get2(id){
return this.$http.get('xxx')
},
// 跳轉(zhuǎn)第二層級(jí)
goto2(){
this.timing = false
if(this.timequery){
clearInterval(this.timequery)
}
// replace、push, 也可以使用name
this.$router.replace('./path2')
},
}
}
</script>
2.3.3 組件頁(yè)面舉例
// 如果使用了父組件向子組件傳值的方式,需在子組件的 data 中 定義 props 用于接收
// echarts 初始化
init(){
// 和上篇介紹 echarts 中定義差不多
var myChart = this.$echarts.init(document.getElementById("id"),'temp')
let option = {}
option = {
// 吧啦吧啦 一頓操作和配置
// 可參考上一篇文章,更多參考 官網(wǎng)配置頁(yè)面
myChart.setOption(option, true)
}
}
這里有一個(gè)需要注意的地方就是
橫向柱狀圖,最下方 是第一條,我們自定義標(biāo)題的時(shí)候,就要顛倒過(guò)來(lái)使用。
同時(shí)會(huì)根據(jù)條數(shù)自動(dòng)切換位置,我們的表頭也需要根據(jù)數(shù)量進(jìn)行位置調(diào)整。
2.4 測(cè) 試
說(shuō)實(shí)話,這方面一直都沒(méi)認(rèn)真寫過(guò)。。。
一般業(yè)務(wù)變動(dòng)的情況下,邏輯也會(huì)變動(dòng)頻繁。
但編寫測(cè)試代碼還是很重要的。
Vue 官方推薦的是使用 karma, mocha 和 chai 等。
感興趣的 可以 專門去了解學(xué)習(xí)下
這一大塊不亞于 編寫 業(yè)務(wù)代碼 ??????
這里不多介紹了哈。
2.5 打 包
npm run build
可在根目錄中 新建 vue.config.js
官方文檔: https://cli.vuejs.org/zh/config/
// 官方文檔: https://cli.vuejs.org/zh/config/
module.exports = {
baseUrl: process.env.NODE_ENV === 'production' ? './' : '/',
}
3 后 記
感謝支持。若不足之處,歡迎大家指出,共勉。
如果覺(jué)得不錯(cuò),記得 點(diǎn)贊,謝謝大家 ??
歡迎關(guān)注 我的: 【Github】 【掘 金】 【簡(jiǎn) 書(shū)】
本文章采用 知識(shí)共享署名-非商業(yè)性使用-相同方式共享 4.0 國(guó)際許可協(xié)議 進(jìn)行許可。