vue icon indicating copy to clipboard operation
vue copied to clipboard

Vue mounted component before dom update

Open MammutAlex opened this issue 4 years ago • 5 comments

If i mounted created Vue in app beforeDomUpdate not update existing components

const app = new Vue({
    el: '#app',
});

For example i have vue component

<template>
    <div>
        <input v-model="inputValue" @change="$emit('input', inputValue)">
    </div>
</template>

<script>
    export default {
        props: {
            value: {
                type: String,
                require: true
            },
        },
        watch: {
            value(value) {
                this.inputValue = value
            }
        },
        data() {
            return {
                inputValue: this.value,
            }
        }
    }
</script>

If i submit form and return validation error and vue has input or button they is blocked

But if i force update component they show correctly (like this)

<template>
    <div>
        <input class="form-control" v-model="inputValue" @change="$emit('input', inputValue)" :key="componentKey">
        <span @click="forceRerender">forceRerender</span>
    </div>
</template>

<script>
    export default {
        props: {
            value: {
                type: String,
                require: true
            },
        },
        mounted() {
            console.log('mounted input', this.componentKey);
        },
        watch: {
            value(value) {
                this.inputValue = value
            }
        },
        data() {
            return {
                inputValue: this.value,
                componentKey: 1,
            }
        },
        methods: {
            forceRerender() {
                this.componentKey += 1;
            }
        }
    }
</script>

This is because vue render component before livewire update dom

if i log vue mounter and livewire Javascript Hooks i see like thet

mounted component
beforeDomUpdate
afterDomUpdate

MammutAlex avatar Mar 21 '20 20:03 MammutAlex

Maybe I am wrong. But there is no future about Vue integration, once AlpineJs is around.

I really like approach to use pre-made components provided by Vuetify/Bueffy... that solves many UI heavy lifting.

Many do prefer Tailwind, what is great tool. But I don’t really like the idea about to write many lines of code to build a simple “input + label”.

“So, do package it into components ...”. Well, some one already did the job for Vue world: Vuetify, Buefy ...

I just wanna give a try with Livewire from @calebporzio It is perfect! Buy I really miss this UI nice components out-of-box.

robsontenorio avatar Apr 24 '20 01:04 robsontenorio

Is there any fix for this? Even if using key to update the vue component, some of the v-model data inside the component does not update correctly.

Currently it's very hard to use any reactive vue components inside livewire components.

roitto avatar Jun 22 '20 10:06 roitto

@MammutAlex I am experiencing the same problem. How did you deal with it?

kamilkozak avatar Jun 27 '20 08:06 kamilkozak

@kamilkozak in a project with many vue components I do not use livewire 😔

MammutAlex avatar Jun 30 '20 08:06 MammutAlex

Im using Alpine, Vue and Livewire. I know it can be a headache but I'm trying to migrate components to alpine/wire slowly.

Here's what I'm doing as a workaround now for my complex vue components when data doesn't rebind after livewire updates state/dom.

<div
    x-data="{ showVueComponent: true }"
    x-on:show-vue-component.window="showVueComponent = true"
    x-on:hide-vue-component.window="showVueComponent = false"
    wire:ignore.self>

    @includeWhen($currentStep == 0, 'orders._step_one')

    {{--included in $currentStep 0 --}}
    <div class="mx-auto max-w-4xl" wire:ignore wire:key="vueComponent">
        <my-vue-component 
            x-show="showVueComponent" 
            v-on:input="(select) => [email protected]('submit', select)">
        </my-vue-component>
    </div>

    @includeWhen($currentStep == 1, 'orders._step_two')

    @includeWhen($currentStep == 2, 'orders._step_three')

</div>

In my Livewire component I use browserDispatchEvent inside my functions to toggle the component. Not sure if this is the best way to handle the situation but works for me atm.

    $this->dispatchBrowserEvent('show-vue-component');
    $this->dispatchBrowserEvent('hide-vue-component');

joselara avatar Aug 13 '20 17:08 joselara