从子组件使用$ emit将数据发送到父组件不适用于Vue

时间:2019-03-25 14:54:59

标签: javascript vue.js ecmascript-6 vuejs2 vue-component

我正在编写“标签”组件。

我正在尝试在代码中使用sendTabsData()方法发送数据,由于某种原因,使用$emit无法正常工作。

这是我的标签组件代码:

<template>
    <div id="tabs">
        <div id="tabs-cont">
            <div class="tabbable-panel">
                <div class="tabbable-line">
                    <ul class="nav nav-tabs" role="tablist"> 
                    </ul>
                    <div class="tab-content">
                        <slot></slot>
                    </div>
                </div>
            </div>
        </div> 
    </div> 
</template>

<script>
export default {
    name: 'DashboardTabs',
    props: {
        tabs: {
            type: Object,
            required: true,
            default: {}
        }
    },
    data() {
        return {
            displayed:      '',
            tabName:        '',
            $tabsContainer: null,
            navTabs:        null, 
            tabContent:     null
        }
    },
    created() {
    },
    mounted() {
        this.init();
    },
    watch: {
    },
    methods: {
        init: function() {
            // Fetch UI elements 
            this.$tabsContainer = $('#tabs');
            this.navTabs        = this.$tabsContainer.find('.nav-tabs');
            this.tabContent     = this.$tabsContainer.find('.tab-content');

            this.createTabs(this.tabs);
        },
        // Create tabs by result
        createTabs: function(tabs) {
            if ( this.tabs !== undefined || this.tabs.length > 0 ) {
                this.setTabsBtns(tabs);
            }
        },
        // 
        tabClick: function(e) {
            this.changeDisplayNames(e);         
            this.sendTabsData();
        },
        // Change display names
        changeDisplayNames: function(e) {

            let liItem = e['target']['dataset']['displaytable'];

            if (liItem) {
                // Update variable table name
                this.displayed = liItem;
                // Remove the '$' and 'Table' text
                let tableCategory   = this.displayed.replace('Table', '');
                tableCategory       =  tableCategory.replace('$', '');
                // Update "global" variable of the current table
                this.tabName        = tableCategory.charAt(0).toUpperCase() + tableCategory.slice(1);
            }
        }, 
        // Set tabs li btns 
        setTabsBtns: function(tabs) {

            for (let key in tabs) {
                this.navTabs.append(`<li class="nav-item" @click="this.tabClick"> <a href="#tab_default_${key}" class="nav-link" data-toggle="tab" data-displayTable="${tabs[key]}"> ${tabs[key]} </a> </li>`);
            }

            this.navTabs.find('li:first a').addClass('active');
            this.displayed  = this.tabs[0];
            this.tabName    = this.tabs[0];
        }, 
        // Set tabs content divs - not relevant if you don't want to load extra data to the DOM
        setTabsContent: function(tabs) {

            for (let key in tabs) {
                this.tabContent.append(`<div class="tab-pane" id="tab_default_${key}"> <table class="aTable hover display" id="${tabs[key]}"> </table> </div>`);
            }

            this.tabContent.find('.tab-pane').first().addClass('active');
        },
        hideTabs: function() {
            this.$tabsContainer.slideUp('slow');
        },
        showTabs: function() {
            this.$tabsContainer.slideDown('slow');
        },
        // Send tab data to parent
        sendTabsData: function(){
            let data = {
                'tabDisplayed': this.displayed,
                'tabName':      this.tabName            
            };
            this.$emit('tabsData', data);
        }
    }
};
</script>   

这是父组件:

<script>
    // import ProgressBar      from "../components/ProgressBar.vue";
    // import _                from 'lodash';
    import DashboardForm    from "../components/DashboardForm.vue";
    import DashboardTabs    from "../components/DashboardTabs.vue";

    export default {
        name: 'testcomponent',
        components: {
            // ProgressBar,
            DashboardForm, 
            DashboardTabs
        },
        // mixins: [GF],
        data() {
            return {
            };
        },
        created() {
        },
        mounted() {
        },
        destroyed() {
        },
        watch: {
        },
        methods: {
            // Submit form
            formSubmit: function(data) {
                console.log('Submit form here');
                console.log(data);
            }, 
            // Tabs data 
            fetchTabsData: function(data) {
                console.log('tab was clicked');
                console.log(data);
            }
        }
    }
</script>

<!-- Template -->
<template>

    <div id="testcomponent">

        <!-- DashboardForm -->
        <DashboardForm 
            :useGroupFilter="true"
            :useDateRange="true"
            @submit="formSubmit"
        />

        <!-- Main Data Container -->
        <div id="data-container">
            <div id="chart-container"></div>
            <!-- Dashboard Tabs and Tab Container -->
            <DashboardTabs
                :tabs="{ 0: 'potato', 1: 'banana' }"
                @tabsData="fetchTabsData"
            >
                <!-- Datatable -->
                <!-- <DashboardDatatable/> -->
            </DashboardTabs>


        </div> 
        <!-- END data-container -->

    </div>
</template>
如您所见,

在我的父组件中,我有一个提交发射来获取数据(并且工作正常)。

选项卡组件和表单组件之间的唯一区别在于,选项卡组件会生成将{click1)绑定到其中的<li> s。

所以我要清楚我的问题:

在这种情况下,如何使用$ emit将数据从子组件发送到父组件,该事件具有绑定到click事件的元素(onClick ==>将数据发送/监听到父组件)动态自行生成,而不是“静态”。

编辑: 使用v-for似乎无法获得请求的结果:

<li class="nav-item" @click="this.tabClick" v-for="(tab,index) in tabs">
<a :href="`#tab_default_${index}`" class="nav-link" data-toggle="tab" :data-displayTable="`${tab}`"> ${tab} </a>
</li>

我得到了错误:

  

渲染错误:“ TypeError:无法读取未定义的属性'tabClick'”

似乎不允许我添加@click

Edit2:

在v-for中使用@click.native="this.tabClick"进行尝试-不会导致任何错误,但不会显示我的虚拟console.logs。 click事件无法正常运行。

1 个答案:

答案 0 :(得分:3)

您的组件会发出tabs事件(this.$emit('tabs', data)),因此,您的父母应该听tabs事件:@tabs="tabsData"而不是提交