# 9. vue全家桶+Echarts+百度地图,搭建数据可视化系统(【续】接口篇)

接上篇

vue全家桶+Echarts+百度地图,搭建数据可视化系统

# 1 前 言

# 1.1 业务场景

实现数据监控的系统。有线图、柱状图、地图,并具有定时刷新的功能。

# 1.2 业务分析

上一篇分析的步骤大致有:

  1. 系统搭建vue-cli
  2. vuex记录登录信息
  3. vue-router路由跳转
  4. 3个维度的页面,提取出共用的组件
  5. 各个组件开发
  6. 调节样式,增加UI
  7. 加入后台接口数据
  8. 优化显示
  9. 测试
  10. 上线

上一篇介绍了 1-6 部分。本篇将介绍一下剩下的 7-10 部分。

😂😂

主要内容是 对数据的处理方式整体的数据逻辑

望各位看官多提 建议和不足 哈,也希望能本篇能给需要人带来 启发。

成品效果图不方便发,还是用上一篇,纯前端的效果图吧。

# 2 正 文

# 2.1 请求处理数据

Vue 中 与后台交互通常使用的是 axios

# 2.1.1 安 装

npm i axios

也可通过cdn引用

# 2.1.2 定 义

新建一个api.js

//  api.js
import axios from 'axios'
const http = axios.create ({
    baseURL : apiurl,       // 连接后端地址
    timeout : 1000 * 30,    // 超时时间,单位为毫秒
    headers : {},          // 请求头,可添加'Authorization'、'X-Requested-With'、'Accept-Language'、'token'等
})

// 请求拦截
http.interceptors.request.use(config =>{
    // 可添加自己的设置,如修改参数、增加参数、修改headers
    return config
},error =>{
    // 可添加报错处理
    return Promise.reject(error)
})

// 响应拦截
http.interceptors.response.use(response =>{
    // 可添加处理逻辑
    return response
},error =>{
    return Promise.reject(error)
})

export default http

同时可在main.js中添加一个自定义全局对象,或者可在单独页面中引用

// main.js
import http from './api.js'

Vue.prototype.$http = http

# 2.1.3 使 用

# a. get请求

在页面中处理时

query(){
    this.$http.get('/xxx/xxx?id='+id).then(res =>{
        // 返回的处理
        console.log(res)
        // res 一般包含code data
    },rej =>{
        // 报错的处理
        console.log(rej)
    })
}
# b. post请求
new(){
    this.$http.post('/xxx/xxx',{
        id : '123',
    }).then(res =>{
        // 返回的处理
        console.log(res)
        // res 一般包含code data
    },rej =>{
        // 报错的处理
        console.log(rej)
    })
}
# c. 其他请求

经常使用到的还有

put 多用于更新操作

delete 多用于删除操作

具体要看后台提供的功能接口方式

# d. 多个请求

比如,我在进来页面后,要同时获取要2个线形图、数字、地图、柱状图、表格的数据

一般情况下,各个数据都是单独的接口来提供的。这样我们就需要至少6个接口。

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 登 录

功能很简单,用户输入用户名、密码、验证码,点击登录。

# 2.2.1 获取uuid

出于对登录时效以及安全性的考虑。在登录验证时,后台根据 uuid 和通过 uuid 获取到的验证码进行校验。

这里列出一些获取 uuid 的方法。来源于:网络。

方法一:

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())
}

方法四:

/*
    指定长度和基数
*/
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" 可使输入框中内容隐藏

传输时,我使用了md5加密

npm i -S js-md5
import md5 from 'js-md5'

let enCode = md(code)

然后就是调用后台接口将你的用户名、密码、验证码发送进行验证登录。

# 2.2.3 存储登录信息

使用过 Vue 的童鞋都清楚,使用vuex的时候,进行刷新页面,store中的数据就会重置。

会防止用户在刷新页面后数据无法获取的情况,一般会将数据同时储存到 sessionStoragelocalStorage

两者区别这里就不介绍了。

// 储存session,具体放在哪个位置根据实际业务
// 我这里放在了登录验证通过之后,当然有很多参数,可使用对象类型转成json ----JSON.stringify(info)
sessionStorage.setItem('info', '123')
// store.js

store = {
    state : JSON.parse(sessionStorage.getItem('info')) || {}
}

这样页面刷新后,store 会从 sessionStorage 拿到我们的数据

# 2.3 业务页面

业务页面分了3个维度。

这里介绍2个维度的实现。

# 2.3.1 整体逻辑

单独的组件只处理数据的展示

如线形图单独写在一个组件中

我在需要的页面中进行引用,传入数据进行显示。

  1. 用户登录验证后,储存业务 IDsession 中,从登录页面跳转到 层级1 页面。
  2. 进入 层级1 后,created 中增加初始化方法。就是使用了上面介绍的 axios.all
  3. 拿到各数据后,分别渲染到各个组件中。
  4. 初始化完成后,触发定时刷新开发。
  5. 根据定时器的时间,触发需要刷新的功能,同上 axios.all 和处理结果。
  6. 点击层级1中某个数据,记录层级2需要的 ID2session中,关闭定时刷新,跳转到 层级2 页面。
  7. 进入 层级2 后,同层级1,先进行初始化,再进行定时刷新。
  8. 层级3 以及 返回 的逻辑都基本和上面一样。

下面介绍一些可能会有 疑问 的地方

# 2.3.2 层级页面举例

相当于介绍了一些父子组件的一些处理。

// 层级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(){
            //  定时查询方法
            this.timeq()
        },
        
        data() {
            return {
                //  传入子组件的数据,可可以使用store
                argA : {},
                argB : {},
                
                // 定时开关
                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) =>{
                    // 数据传入组件a,触发组件a的初始化方法
                    that.argA = res1.data
                    that.$refs.aRef.init();
                    
                    // 数据传入组件b,触发组件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')
            },
            
            //  跳转第二层级
            goto2(){
                this.timing = false
                if(this.timequery){
                    clearInterval(this.timequery)
                }
                // replace、push, 也可以使用name 
                this.$router.replace('./path2')
            },
        }
    }
</script>

# 2.3.3 组件页面举例

// 如果使用了父组件向子组件传值的方式,需在子组件的 data 中 定义 props 用于接收

// echarts 初始化
init(){
    // 和上篇介绍 echarts 中定义差不多
    var myChart = this.$echarts.init(document.getElementById("id"),'temp')
    let option = {}
    option = {
        // 吧啦吧啦 一顿操作和配置
        // 可参考上一篇文章,更多参考 官网配置页面
        myChart.setOption(option, true)
    }
}

这里有一个需要注意的地方就是

横向柱状图,最下方 是第一条,我们自定义标题的时候,就要颠倒过来使用。

同时会根据条数自动切换位置,我们的表头也需要根据数量进行位置调整。

# 2.4 测 试

说实话,这方面一直都没认真写过。。。

一般业务变动的情况下,逻辑也会变动频繁。

但编写测试代码还是很重要的。

Vue 官方推荐的是使用 karmamochachai 等。

感兴趣的 可以 专门去了解学习下

这一大块不亚于 编写 业务代码 😅😅😅

这里不多介绍了哈。

# 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 后 记

感谢支持。若不足之处,欢迎大家指出,共勉。

如果觉得不错,记得 点赞,谢谢大家 😂

上次更新: 12/17/2019, 3:00:57 PM