vue父组件异步传递prop到子组件echarts画图问题踩坑总结

Posted goloving

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue父组件异步传递prop到子组件echarts画图问题踩坑总结相关的知识,希望对你有一定的参考价值。

  效果图:

技术分享图片

  大致思路:考虑到5张图都是折线图,所以准备用一个子组件承接echarts画图,然后父组件通过prop传递不同数据来展示不同的图

踩坑问题:

1、引入line子组件,画了5个元素,但是只显示一个

  原因:id重复

  解决方案:prop传递不同id名

2、父组件传递的数据在子组件报错

  这里情况比较特殊,我用父组件数据data里面给demo数据的时候,子组件是拿得到数据的,图片正常显示,所以以为可以了,当换成从后台请求的数据后,发现子组件总是报错,data.count is not a function ,在子组件的mounted里面打印父组件传递过来的prop,发现是空数组。

  刚开始我以为是mounted生命周期的问题,所以改成created阶段去请求后台数据,然后传递给子组件,发现仍然不行。

  这时,我给父组件数据加上默认一些demo数据,然后再created阶段再去请求后台数据,覆盖demo数据。发现子组件mounted阶段打印的还是demo数据,而不是请求的数据,所以知道问题原因就是子组件渲染的时候,在父组件created请求后台数据返回之前就prop传递给了子组件,所以导致子组件获取的都不是从后台请求的数据。

3、刚开始子组件时在mounted里面调用画图方法drawline(),由于这时数据为空,所以报错。我就考虑到是不是不让子组件自身去mounte画图,而是让父组件异步请求到后台数据之后,赋值给prop之后,再通过ref去调用子组件的画图方法drawLine(),这样是不是就可以画图成功了?但是验证还是不行。在drawLine()里面去打印父组件传递的prop,发现还是最初的空或者demo数据。

  所以考虑到父组件传递prop就是渲染时传递,而不是赋值时传递,所以总是传递的data()里面初始化的数据。所以通过父组件去调用子组件方法去画图也行不通。

4、考虑到父组件传递prop就是渲染时传递。

  那么我就可以给子组件加个判断 v-if 条件,当父组件从后台异步取到数据后,并且赋值给prop后,让flag = true再去渲染子组件,那么此时传递给子组件的prop就是异步获取到数据之后的值,图形就正常展示出来了。

5、全部代码:

  miniLine子组件

<template>
    <div :id="myId" :style="{width:‘100%‘,height:‘200px‘}"></div>
</template>
<script type="ecmascript-6">
export default {
    data(){
        return {
            series:[]
        }
    },
    props:[myId,lineDime,lineSeries],
    methods:{
        drawLine(){
            let myLine = this.$echarts.init(document.getElementById(this.myId));
            let option = {
                color:[#1CA6F1,#C1D534,#C6504D],
                tooltip: {
                    trigger: axis
                },
                legend: {
                    icon:stack
                },
                grid: {
                    left: 3%,
                    right: 3%,
                    bottom: 3%,
                    top:15%,
                    containLabel: true
                },
                xAxis: [{
                    type: category,
                    axisTick: {
                        alignWithLabel: true,
                        show:false
                    },
                    axisLabel:{  
                        show:true,
                        formatter: function (value, index) {
                            return value.split( )[1];
                        }
                    }
                }],
                yAxis: [{
                    type: value,
                    axisTick: {
                        show: false
                    },
                    splitLine:{  
                        show:true
                    }
                }],
                dataset:{
                       dimensions:this.lineDime,
                    source:this.lineSeries
                },
                series: this.series
            };
            myLine.setOption(option);
            window.addEventListener("resize", () => { myLine.resize();});
        }
    },
    mounted(){
        let _obj = {
            type:line
        }
        this.series.length = this.lineDime.length - 1
        this.series.fill(_obj)
        this.drawLine()
    }
}
</script>
<style scoped lang="stylus" rel="stylesheet">
</style>

  monitor父组件

<template>
<el-main>
    <el-row class="dbInfo">
        <el-col :span="6">
            <div class="panel-body">
                <img src="../../assets/images/postgreSQL.jpg" height="60">
                <p>{{dbInfo.version}}</p>
            </div>
        </el-col>
        <el-col :span="6">
            <div class="panel-body">
                <p>Rows fetched/returned</p>
                <div class="content" :style="{color:‘#C1D534‘}">{{dbInfo.fetchper}}<span>%</span></div>
            </div>
        </el-col>
        <el-col :span="6">
            <div class="panel-body">
                <p>Database capacity</p>
                <div class="content" :style="{color:‘#1CA6F1‘}">{{parseInt(dbInfo.dbsize)}}<span>MB</span></div>
            </div>
        </el-col>
        <el-col :span="6">
            <div class="panel-body">
                <p>Max connections in use</p>
                <div class="content" :style="{color:‘#C6504D‘}">{{dbInfo.conper}}<span>%</span></div>
            </div>
        </el-col>
    </el-row>
    <div class="query">
        <el-date-picker
        v-model="datetimerange"
        type="datetimerange"
        range-separator=""
        start-placeholder="开始时间"
        end-placeholder="结束时间"
        size="mini">
        </el-date-picker>
        <i class="el-icon-refresh" @click="refresh"></i>
    </div>
    <el-row :gutter="20">
        <el-col :span="12">
            <moniLine v-if="flag" :my-id="ids[0]" :line-dime="dimensions[0]" :line-series="monitorData"></moniLine>
        </el-col>
        <el-col :span="12">
            <moniLine v-if="flag" :my-id="ids[1]" :line-dime="dimensions[1]" :line-series="monitorData"></moniLine>
        </el-col>
    </el-row>
    <el-row :gutter="20">
        <el-col :span="8">
            <moniLine v-if="flag" :my-id="ids[2]" :line-dime="dimensions[2]" :line-series="monitorData"></moniLine>
        </el-col>
        <el-col :span="8">
            <moniLine v-if="flag" :my-id="ids[3]" :line-dime="dimensions[3]" :line-series="monitorData"></moniLine>
        </el-col>
        <el-col :span="8">
            <moniLine v-if="flag" :my-id="ids[4]" :line-dime="dimensions[4]" :line-series="monitorData"></moniLine>
        </el-col>
    </el-row>
    <el-tabs v-model="activeName" type="border-card">
        <el-tab-pane label="Sessions" name="first">
            <el-table :data="sessions" size="mini">
                <el-table-column prop="pid" label="Pid" width="60" align="center"></el-table-column>
                <el-table-column prop="datname" label="Database" width="80" align="center"></el-table-column>
                <el-table-column prop="usename" label="User" width="80" align="center"></el-table-column>
                <el-table-column prop="application_name" label="Application" align="center"></el-table-column>
                <el-table-column prop="client_addr" label="Client" width="140" align="center"></el-table-column>
                <el-table-column prop="backend_start" label="Backend start" width="150" align="center"></el-table-column>
                <el-table-column prop="state" label="State" width="70" align="center"></el-table-column>
                <el-table-column prop="wait_event" label="Wait Event" align="center"></el-table-column>
                <el-table-column prop="blocking_pids" label="Blocking PIDs" width="90" align="center"></el-table-column>
            </el-table>
        </el-tab-pane>
        <el-tab-pane label="Locks" name="second">
            <el-table :data="locks" size="mini">
                <el-table-column prop="pid" label="Pid" width="60"></el-table-column>
                <el-table-column prop="datname" label="Database" width="70"></el-table-column>
                <el-table-column prop="locktype" label="Lock type" width="70"></el-table-column>
                <el-table-column prop="relation" label="Target relation"></el-table-column>
                <el-table-column prop="page" label="Page" width="50"></el-table-column>
                <el-table-column prop="tuple" label="Tuple" width="50"></el-table-column>
                <el-table-column prop="virtualxid" label="vXID(target)"></el-table-column>
                <el-table-column prop="objsubid" label="XID(target)"></el-table-column>
                <el-table-column prop="classid" label="Class" width="50"></el-table-column>
                <el-table-column prop="objid" label="ObjectID" width="65"></el-table-column>
                <el-table-column prop="transactionid" label="vXID(owner)" width="90"></el-table-column>
                <el-table-column prop="mode" label="Mode"></el-table-column>
                <el-table-column prop="granted" label="Granted" width="65">
                    <template slot-scope="scope">{{scope.row.granted ?  :}}</template>
                </el-table-column>
            </el-table>
        </el-tab-pane>
        <el-tab-pane label="Prepared Transactions" name="third">
            <el-table :data="transactions" size="mini">
                <el-table-column prop="gid" label="Name"></el-table-column>
                <el-table-column prop="database" label="Database"></el-table-column>
                <el-table-column prop="owner" label="Owner"></el-table-column>
                <el-table-column prop="transaction" label="XID"></el-table-column>
                <el-table-column prop="prepared" label="Prepared at"></el-table-column>
            </el-table>
        </el-tab-pane>
        <el-tab-pane label="Configuration" name="fourth">
            <el-table :data="configs" size="mini">
                <el-table-column prop="name" label="Name"></el-table-column>
                <el-table-column prop="category" label="Category"></el-table-column>
                <el-table-column prop="setting" label="Setting"></el-table-column>
                <el-table-column prop="unit" label="Unit" width="50"></el-table-column>
                <el-table-column prop="short_desc" label="Description"></el-table-column>
            </el-table>
        </el-tab-pane>
    </el-tabs>
</el-main>
</template>
<script type="ecmascript-6">
import moniLine from ./moniLine
import {getMonitorApi,getPgSessionsApi,getPgLocksApi,getPgPretransApi,getPgConfigsApi,getPgDbinfosApi} from @/apis
export default {
    data(){
        return {
            flag:false,
            ids:[myLine1,myLine2,myLine3,myLine4,myLine5],
            dimensions:[
                [snap_time,active,idle,total],
                [snap_time,commits,rollbacks,transactions],
                [snap_time,inserts,updates,deletes],
                [snap_time,fetched,returned],
                [snap_time,reads,hits]
            ],
            monitorData:[],
            activeName:first,
            sessions:[],
            locks:[],
            transactions:[],
            configs:[],
            dbInfo:{},
            datetimerange:[]
        }
    },
    components:{
        moniLine
    },
    created(){
        this.fetchData()
    },
    methods:{
        fetchData(){
            getMonitorApi().then(res => {
                if(res.status === 200){
                    this.monitorData = res.data
                    this.flag = true
                }
            })
            getPgSessionsApi().then(res => {
                if(res.status === 200){
                    this.sessions = res.data
                }
            })
            getPgLocksApi().then(res => {
                if(res.status === 200){
                    this.locks = res.data
                }
            })
            getPgPretransApi().then(res => {
                if(res.status === 200){
                    this.transactions = res.data
                }
            })
            getPgConfigsApi().then(res => {
                if(res.status === 200){
                    this.configs = res.data
                }
            })
            getPgDbinfosApi().then(res => {
                if(res.status === 200){
                    this.dbInfo = res.data
                }
            })
        },
        refresh(){
            this.fetchData()
        }
    }
}
</script>
<style scoped lang="stylus" rel="stylesheet">
@import ../../assets/css/index.styl
.el-row{
    margin-bottom 20px
}
.query{
    margin 10px
    i{
        font-weight 1000
        color #A0A0A6
    }
    & i:hover{
        color #1CA6F1
        cursor pointer
    }
}
.el-table{
    font-size 10px
}
.el-tabs__nav .el-tabs__item{
    font-size 12px
}
.dbInfo{
    text-align center
    p{
        margin 0px
        font-size 12px
    }
    .panel-body{
        margin 10px 20px
        min-height 82px
        .content{
            font-size 50px
            font-weight 500
            span{
                font-size 30px
            }
        }
    }
}
</style>

 

以上是关于vue父组件异步传递prop到子组件echarts画图问题踩坑总结的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js2.0中子组件修改父组件传递过来的props,并不影响父组件的原始数据

如何在 Vue JS 中将更新的值从父组件发送到子组件?

Vue父子组件传值

对vue的props实现双向数据流

从 Vue 的视角学 React—— 组件传参

第十讲、Vue3.x父组件给子组件传值、Props、Props验证、单向数据流