【问题标题】:Vue component isn't ready when displayedVue 组件在显示时未准备好
【发布时间】:2021-04-04 02:11:34
【问题描述】:

我是一个初学者,我用 laravel、vue 和 tailwind-css 开始了我自己的小项目。对不起,我的英语不好。我有以下问题:如果我切换路由或重新加载页面,我的表单组件正在呈现一种状态,它还没有准备好获取数据并加载我猜的 CSS 类。当我切换路线或重新加载时,您可以看到表单和所有样式类是如何构建的。那是我不喜欢的。我想在它处于就绪状态时渲染这个组件。

我添加了一个 litte gif,我在其中多次重新加载页面,因此您可以看到问题。 https://imgur.com/a/yN5S4VZ(Imgur 上的 Gif)

我的代码如下所示: EditProfile.vue

<template>
<div class="wrapper">
    <NavbarAuthenticated></NavbarAuthenticated>
    <div class="flex ...">
        <Sidebar class="flex-none"></Sidebar>
        <EditProfileForm :user="user" class="flex-grow"></EditProfileForm>
    </div>

</div>
</template>

<style>
.bg-custom-blue {
    background-color: #F8FAFC;
}
</style>

<script>
import NavbarAuthenticated from '../authenticated/NavbarAuthenticated'
import Sidebar from '../components/Sidebar'
import EditProfileForm from '../components/EditProfileForm'

export default {
    data() {
        return {
            user: null
        }
    },
    created() {
        axios.get('/api/user').then((res) => {
            this.user = res.data
        });
    },
    components: {
        NavbarAuthenticated,
        Sidebar,
        EditProfileForm

    },
}
</script>

EditProfileForm.vue

<template>
<div class=" min-h-screen pt-2 ">

    <div class="container ">

        <div class="inputs w-full max-w-2xl pb-20 pl-3 pt-9 ">

            <h2 class="text-2xl text-gray-900">Account Setting</h2>
            <form class="mt-6 border-t border-gray-400 pt-4">
                <div class='flex flex-wrap -mx-3 mb-6'>
                    <div class='w-full md:w-full px-3 mb-6'>
                        <label class='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2' for='grid-text-1'>email address</label>
                        <input class='appearance-none block w-full bg-white text-gray-700 border border-gray-400 shadow-inner rounded-md py-3 px-4 leading-tight focus:outline-none  focus:border-gray-500' id='grid-text-1' type='text' v-if="user" v-model.lazy="user.email">
                    </div>

                    <div class='w-full md:w-full px-3 mb-6 '>
                        <label class='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'>password</label>
                        <input readonly class='appearance-none block w-full bg-gray-100 text-gray-700 border border-gray-400 shadow-inner rounded-md py-3 px-4 leading-tight focus:outline-none  focus:border-gray-500' type='text' placeholder="**********">
                        <div class="flex justify-end">

                            <router-link class=" bg-gray-200 hover:bg-gray-300 border border-gray-400 text-black font-bold py-2 my-2 px-6 rounded-md" to="resetpassword">Passwort ändern</router-link>
                        </div>
                    </div>

                    <div class="personal w-full border-t border-gray-400 pt-4">
                        <h2 class=" pb-6 text-2xl text-gray-900">Personal info:</h2>

                        <div class='w-full md:w-full px-3 mb-6'>
                            <label class='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'>Name</label>
                            <input readonly class='appearance-none block w-full bg-gray-100 text-gray-700 border border-gray-400 shadow-inner rounded-md py-3 px-4 leading-tight focus:outline-none  focus:border-gray-500' v-if="user" v-model="user.name" type='text'>
                        </div>

                        <div class='w-full md:w-full px-3 mb-6'>
                            <label class='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'>Straße</label>
                            <input class='appearance-none block w-full bg-white text-gray-700 border border-gray-400 shadow-inner rounded-md py-3 px-4 leading-tight focus:outline-none focus:border-gray-500' v-if="user" v-model="user.strasse" type='text'>
                        </div>

                        <div class='w-full md:w-full px-3 mb-6'>
                            <label class='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'>Hausnummer</label>
                            <input class='appearance-none block w-full bg-white text-gray-700 border border-gray-400 shadow-inner rounded-md py-3 px-4 leading-tight focus:outline-none  focus:border-gray-500' v-if="user" v-model="user.hausnummer" type='number'>
                        </div>

                        <div class='w-full md:w-full px-3 mb-6'>
                            <label class='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'>Postleitzahl</label>
                            <input class='appearance-none block w-full bg-white text-gray-700 border border-gray-400 shadow-inner rounded-md py-3 px-4 leading-tight focus:outline-none  focus:border-gray-500' v-if="user" v-model="user.postleitzahl" type='text'>
                        </div>

                        <div class='w-full md:w-full px-3 mb-6'>
                            <label class='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'>Ort</label>
                            <input class='appearance-none block w-full bg-white text-gray-700 border border-gray-400 shadow-inner rounded-md py-3 px-4 leading-tight focus:outline-none  focus:border-gray-500' v-if="user" v-model="user.ort" type='text'>
                        </div>

                        <div class='w-full md:w-full px-3 mb-6'>
                            <label class='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'>Land</label>
                            <div class="flex-shrink w-full inline-block relative">
                                <select class="block appearance-none text-gray-600 w-full bg-white border border-gray-400 shadow-inner px-4 py-2 pr-8 rounded" v-if="user" v-model="user.land">
                                    <option>Deutschland</option>
                                    <option>USA</option>
                                    <option>Frankreich</option>
                                    <option>Spanien</option>
                                    <option>England</option>
                                </select>
                                <div class="pointer-events-none absolute top-0 mt-3  right-0 flex items-center px-2 text-gray-600">
                                    <svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
                                        <path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" /></svg>
                                </div>
                            </div>
                        </div>

                        <div class="flex justify-start">
                            <button @click.prevent="saveData(user)" class="mr-4 bg-green-500 ml-3 hover:bg-blue-700 text-white font-bold py-2 px-3 rounded-lg">
                                Änderungen speichern
                            </button>

                        </div>

                        <p @click.prevent="pushModal" class="flex justify-start mx-6 mt-4 text-xs text-gray-500 cursor-pointer hover:text-black">Account löschen</p>
                        <button v-if="showModal" @click.prevent="deleteAccount(user)" class="mr-4 mt-4 bg-red-500 ml-3 hover:bg-red-700 text-white font-bold py-2 px-3 rounded-lg">
                            Account löschen
                        </button>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>
</template>

<style>
</style>

<script>
export default {
    name: 'user',
    props: {
        user: {
            type: Object

        }
    },
    errors: [],
    data() {
        return {
            showModal: false,
        }
    },
    methods: {
        saveData(user) {
            axios.patch('/api/updateUser/' + user.id, user).then(() => {}).catch((error) => {
                this.errors = error.response.data.errors;
            });
        },
        deleteAccount(user) {
            axios.delete('/api/updateUser/' + user.id, user).then(() => {
                this.$router.push({
                    name: "Home"
                });

            }).catch((error) => {
                this.errors = error.response.data.errors;
            });
        },

        pushModal() {
            this.showModal = true;
        },
        hideModal() {
            this.showModal = false;
        }
    }
}
</script>

【问题讨论】:

  • errors放在数据返回对象里面,在showModal旁边。

标签: laravel vue.js vue-router tailwind-css


【解决方案1】:

您可以添加一个仅在获取数据时显示组件的条件:

<EditProfileForm v-if="user" :user="user" class="flex-grow"></EditProfileForm>

【讨论】:

    【解决方案2】:

    您想要实现的是服务器端渲染。因此,当页面从服务器返回时,您已经有用户在其中,并且表单中没有闪烁。

    在这里,Vue 做了它应该做的事情。当您在浏览器中加载页面时,它会获取用户。在页面加载到浏览器之前,它无法执行该操作。

    目前,使用 Laravel 和 PHP,您似乎无法为 Vue 实现 SSR。但是您可以在用户加载时简单地显示一个占位符

    试试类似的东西

    <EditProfileForm v-if="user" :user="user" class="flex-grow"></EditProfileForm>
    <MyProgressIndicator v-else />
    

    您可以使用 tailwind 和 vue 创建一个简单的进度指示器。

    或者,如果您可以像在顺风中使用 Skeleton Loader 会更好docs

    编辑:使用 Laravel 的 SSR 似乎很少有解决方法,例如 one

    【讨论】:

      猜你喜欢
      • 2020-03-07
      • 1970-01-01
      • 1970-01-01
      • 2017-02-22
      • 1970-01-01
      • 2017-06-29
      • 1970-01-01
      • 2019-03-28
      相关资源
      最近更新 更多