首页 > 解决方案 > vue Fullcalendar eventRender,添加vue组件

问题描述

我使用fullcalendar.io vue扩展。

而且我想挂钩事件渲染以添加操作,但事件回调仅包含 JS 元素。

有办法将vue组件注入其中吗?

<FullCalendar
    ref="fullCalendar"
    defaultView="dayGridMonth"
    :firstDay="1"
    :editable="true"
    :draggable="true"
    :timeZone="'UTC'"
    :header="false"
    :events="events"
    :plugins="plugins"
    @eventRender="eventRender"
/>

JS

import FullCalendar from '@fullcalendar/vue'
import dayGridPlugin from '@fullcalendar/daygrid'
import interactionPlugin from '@fullcalendar/interaction';

export default {
        components: {
            FullCalendar
        },
        data () {
            return {
                loader: false,
                calendar: null,
                plugins: [
                    dayGridPlugin, interactionPlugin
                ],
                events: [
                    {"id":1,"start":"2019-11-25","end":"2019-11-27"},
                    {"id":2,"start":"2019-11-23","end":"2019-11-26"},
                    {"id":3,"start":"2019-11-22","end":"2019-11-25"},
                    {"id":4,"start":"2019-11-21","end":"2019-11-24"}
                ]
            }
        },

        mounted() {

            this.calendar = this.$refs.fullCalendar.getApi();

        },

        methods:{

            eventRender(info){

                console.log(info);

            },
        }
}

例如内部eventRender(这是需要的肮脏示例):

eventRender(info){

    $(info.el).append('<component-name></component-name>');

}

更新 另一个解决方案是Vue.extend(不知道是否是正确的方法,有什么建议吗?):

添加外部组件:

<template>
    <v-btn @click="click" :class="type">
        <slot name="text"/>
    </v-btn>
</template>

<script>
export default {
    name: 'Button',
    props: [
        'type'
    ],
    methods: {
        click() {
            this.$emit('click')
        }
    }
}

</script>

导入所需组件

import Vue from "vue"
import Button from "./helpers/Button"
var ActionClass = Vue.extend(Button)

在渲染函数中使用propssloteventRender

eventRender(info){

    let action = new ActionClass({
        propsData: {
             type: 'primary'
        }
    })
    action.$slots.text = 'Click me!'
    action.$mount()
    action.$on('click', () => {
         console.log(info);
    });

    info.el.appendChild(action.$el)

}

标签: javascriptvue.jsvuejs2fullcalendarvuetify.js

解决方案


更新 使用 fullCalendar V5,有一个插槽支持,所以不再需要这个 hack。

所以我最后做的是使用Vue.extend()解决方案(包括手动创建和销毁组件)直到他们将添加插槽

完整示例(日历组件):

<template>
    <FullCalendar
        ref="fullCalendar"
        defaultView="dayGridMonth"
        :events="events"
        :plugins="plugins"
        @eventRender="eventRender"
        @eventDestroy="eventDestroy"
    />
</template>
<script>
    import Vue from "vue"
    import dayGridPlugin from '@fullcalendar/daygrid'
    import FullCalendar from '@fullcalendar/vue'

    //Import Event component
    import Event from "./helpers/Event"

    //Init Event component
    const EventClass = Vue.extend(Event)

    export default {
        components: {
            FullCalendar
        },
        data () {
            return {
                plugins: [
                    dayGridPlugin
                ],
                events: {
                    url: "/api/calendar",
                },
                eventsObj: {}
            }
        },

        methods:{

            //FullCalendar Render event
            eventRender(info){

                //create our component instance
                const event = new EventClass({
                    propsData: {
                        event: info.event
                    }
                })

                event.$on('edit', this.edit)

                event.$on('delete', this.delete)

                event.$mount();

                //assign created component to our eventObj with uuid as key (to destroy in future)
                this.eventsObj[event._uid] = event;

                //set data-vue="{id}"
                //append our compiled component to .fc-event
                info.el.setAttribute('data-vue-id', event._uid);
                info.el.appendChild(event.$el)

            },


            //we need to destroy out component when element is removed from calendar
            eventDestroy(info){

                //get uuid
                let id = parseInt(info.el.getAttribute('data-vue-id'));

                if(this.eventsObj[id]){

                    //if exist destroy
                    this.eventsObj[id].$destroy(true);

                }
            },

            edit(event){

                console.log("edit Click")

            },

            delete(event){

                console.log("delete Click")

            }
        }
    }
</script>

事件组件:

<template>
    <v-toolbar flat dense height="30px" class="elvation-0">
        <v-btn @click="clickHandler('edit')" color="white">
            <v-icon small>edit</v-icon>
        </v-btn>
        <v-btn @click="clickHandler('delete')" color="white">
            <v-icon small>delete</v-icon>
        </v-btn>
    </v-toolbar>
</template>
<script>
export default {
    name: 'Event',
    props: ['event']
    methods: {
        clickHandler(type) {
            this.$emit(type, this.event)
        }
    }
}
</script>

推荐阅读