Vue 3: 无法将子组件以编程方式创建的组件固定到视口位置

huangapple go评论59阅读模式
英文:

Vue 3: Unable to position child component as fixed to viewport with programatically created components

问题

我有一个应用程序,看起来像这样:

Vue 3: 无法将子组件以编程方式创建的组件固定到视口位置

在输入正确信息后一切正常。但是在输入错误信息后,应该显示一个覆盖整个页面的错误组件。

主组件的代码如下,为了更好地理解,请查看其中的两个注释(一个在模板中,一个在JavaScript中)

<template>
    <div class="loginpagecontainer screencentered">
        <div class="largetext flexcentered">
            <img src="../../../artwork/emirlogoexported.svg" class="textheight"/><span id="logotext">Emir</span>
        </div>
        <div id="formcontainer">
            <span>BID</span> <TextInput ref="bid"/>
            <span>Password</span> <TextInput password ref="pwd"/>
        </div>
        <div class="flexend">
            <ButtonText text="Sign Up" type="clean" @click="signUp"/>
            <ButtonText text="Sign In" @click="signIn"/>
        </div>
        <!-- 注意这个组件 -->
        <div ref="errcontainer">

        </div>
    </div>
</template>

<script>
import ButtonText from './ButtonText.vue';
import TextInput from './TextInput.vue';
import ErrorPopup from './ErrorPopup.vue';
import * as emirjs from '../emirjs.js';
import { createApp } from 'vue';

export default {
    name: "LoginPage",
    components: { TextInput, ButtonText },
    methods: {
        signIn() {
            localStorage.setItem("emir_bid", this.$refs.bid.getValue());
            localStorage.setItem("emir_pwd", this.$refs.pwd.getValue());
            emirjs.info().then((data) => {
                if (emirjs.emirOkCodes.includes(data.code)) {
                    console.log("Login Successful");
                } else {
                    // 处理错误的代码
                    console.log("Login Failed");
                    localStorage.removeItem("emir_bid");
                    localStorage.removeItem("emir_pwd");
                    
                    // 这是 ErrorPopup 实例的创建,然后挂载到 errcontainer。
                    createApp(ErrorPopup).mount(this.$refs.errcontainer);
                }
            });
        },

        signUp() {
        }
    }
};
</script>

<style>
#background {
    min-height: 100vh;
    min-width: 100vw;
}

.screencentered {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.loginpagecontainer {
    border: 0px solid var(--border);
    border-radius: var(--radius-large);
    padding: 1em;
    text-align: justify;
    background-color: var(--bg-level1);
}

.textcenter {
    text-align: center;
}

.largetext {
    font-size: 2em;
    font-weight: bold;
}

.textheight {
    height: 1em;
    vertical-align: middle;
}

.flexcentered {
    display: flex;
    align-items: center;
    justify-content: center;
}

#logotext {
    padding-left: 0.1ch;
}

#formcontainer {
    display: grid;
    padding-top: 1em;
    grid-template-columns: repeat(2, auto);
    grid-row-gap: 0.3em;
    grid-column-gap: 1em;
    padding-bottom: 1em;
}

.flexend {
    display: flex;
    justify-content: flex-end;
}
</style>

最后,ErrorPopup 组件的代码如下,这里提供的代码非常简单,不要在意它。

<template>
<div class="fixcenter"> ERR </div>
</template>
<script>

</script>
<style>
.fixcenter {
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
    width: 100vw;
    background-color: rgba(0, 0, 0, 0.4);
}
</style>

如您所见,position 被设置为 fixed,这意味着它应该位于视口的左上角,并且应该覆盖整个页面。

现在看看错误凭据时会发生什么:

Vue 3: 无法将子组件以编程方式创建的组件固定到视口位置

通过使用开发者工具进行检查:

Vue 3: 无法将子组件以编程方式创建的组件固定到视口位置

是的,我已经尽力通过谷歌搜索解决问题,但作为最后的手段,我不得不在 Stack Overflow 上提问。

英文:

I have an app that looks something like this:

Vue 3: 无法将子组件以编程方式创建的组件固定到视口位置

Upon entering correct information all works fine. But upon entering wrong information, it is meant to show an error component that covers the whole page.

The code for main component is as follows, to better understand it, just look at the 2 comments in it (one in template, one in javascript)

&lt;template&gt;
    &lt;div class=&quot;loginpagecontainer screencentered&quot;&gt;
        &lt;div class=&quot;largetext flexcentered&quot;&gt;
            &lt;img src=&quot;../../../artwork/emirlogoexported.svg&quot; class=&quot;textheight&quot;/&gt;&lt;span id=&quot;logotext&quot;&gt;Emir&lt;/span&gt;
        &lt;/div&gt;
        &lt;div id=&quot;formcontainer&quot;&gt;
            &lt;span&gt;BID&lt;/span&gt; &lt;TextInput ref=&quot;bid&quot;/&gt;
            &lt;span&gt;Password&lt;/span&gt; &lt;TextInput password ref=&quot;pwd&quot;/&gt;
        &lt;/div&gt;
        &lt;div class=&quot;flexend&quot;&gt;
            &lt;ButtonText text=&quot;Sign Up&quot; type=&quot;clean&quot; @click=&quot;signUp&quot;/&gt;
            &lt;ButtonText text=&quot;Sign In&quot; @click=&quot;signIn&quot;/&gt;
        &lt;/div&gt;
        &lt;!-- NOTICE THIS COMPONENT --&gt;
        &lt;div ref=&quot;errcontainer&quot;&gt;

        &lt;/div&gt;
    &lt;/div&gt;
&lt;/template&gt;z

&lt;script&gt;
import ButtonText from &#39;./ButtonText.vue&#39;;
import TextInput from &#39;./TextInput.vue&#39;;
import ErrorPopup from &#39;./ErrorPopup.vue&#39;;
import * as emirjs from &#39;../emirjs.js&#39;;
import { createApp } from &#39;vue&#39;;

export default {
    name: &quot;LoginPage&quot;,
    components: { TextInput, ButtonText },
    methods: {
        signIn() {
            localStorage.setItem(&quot;emir_bid&quot;, this.$refs.bid.getValue());
            localStorage.setItem(&quot;emir_pwd&quot;, this.$refs.pwd.getValue());
            emirjs.info().then((data) =&gt; {
                if (emirjs.emirOkCodes.includes(data.code)) {
                    console.log(&quot;Login Successful&quot;);
                } else {
                    // THE CODE THAT HANDLES FALIURES
                    console.log(&quot;Login Failed&quot;);
                    localStorage.removeItem(&quot;emir_bid&quot;);
                    localStorage.removeItem(&quot;emir_pwd&quot;);
                    
                    // THIS IS THE CREATION OF THE INSTANCE OF ErrorPopup and 
                    // is mounted to the errcontainer.
                    createApp(ErrorPopup).mount(this.$refs.errcontainer);
                }
            });
        },

        signUp() {
        }
    }
};
&lt;/script&gt;

&lt;style&gt;
#background {
    min-height: 100vh;
    min-width: 100vw;
}

.screencentered {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.loginpagecontainer {
    border: 0px solid var(--border);
    border-radius: var(--radius-large);
    padding: 1em;
    text-align: justify;
    background-color: var(--bg-level1);
}

.textcenter {
    text-align: center;
}

.largetext {
    font-size: 2em;
    font-weight: bold;
}

.textheight {
    height: 1em;
    vertical-align: middle;
}

.flexcentered {
    display: flex;
    align-items: center;
    justify-content: center;
}

#logotext {
    padding-left: 0.1ch;
}

#formcontainer {
    display: grid;
    padding-top: 1em;
    grid-template-columns: repeat(2, auto);
    grid-row-gap: 0.3em;
    grid-column-gap: 1em;
    padding-bottom: 1em;
}

.flexend {
    display: flex;
    justify-content: flex-end;
}
&lt;/style&gt;

Finally, the code for ErrorPopup component is as follow, the code given here is very crude so do not mind it.

&lt;template&gt;
&lt;div class=&quot;fixcenter&quot;&gt; ERR &lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;

&lt;/script&gt;
&lt;style&gt;
.fixcenter {
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
    width: 100vw;
    background-color: rgba(0, 0, 0, 0.4);
}
&lt;/style&gt;

As you can see, the position is set to be fixed which suggests that it should be on the topleft of the viewport and it is meant to cover the whole page.

Now see what happens on wrong credentials:

Vue 3: 无法将子组件以编程方式创建的组件固定到视口位置

Upon inspecting via devtools:

Vue 3: 无法将子组件以编程方式创建的组件固定到视口位置

And yes, I tried my best to google my way out but as my last
resort, I had to ask a question on SO.

答案1

得分: 2

<!-- 注意此组件 -->
<div ref="errcontainer">

此组件位于&lt;div class="loginpagecontainer screencentered"&gt;内,具有居中样式,请尝试将这些组件分开。

在这里查看:https://codesandbox.io/s/nameless-cloud-5h291l?file=/src/components/Test.vue

屏幕截图

英文:
&lt;!-- NOTICE THIS COMPONENT --&gt;
&lt;div ref=&quot;errcontainer&quot;&gt;
&lt;/div&gt;

This component it's inside &lt;div class=&quot;loginpagecontainer screencentered&quot;&gt; wich has centered style, try to separate these components.

Here, take a look: https://codesandbox.io/s/nameless-cloud-5h291l?file=/src/components/Test.vue

Screenshot

huangapple
  • 本文由 发表于 2023年2月8日 23:50:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/75388322.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定