如何编写一个vue弹出模式,动态切换标签中的2个附加vue组件

z9zf31ra  于 2022-11-17  发布在  Vue.js
关注(0)|答案(1)|浏览(144)

我尝试做的是在前端为Laravel Breeze附带的标准Vue搭建设计一个新的Vue/Inertia登录/注册模式。
我想达到的目标是:
Login / Register按钮-〉点击后会打开一个模态。模态包含一个头部分,其中有一个“Login”标签和一个“Register”标签,默认情况下选择了Login标签。然后它包含一个主体部分,这是一个在“login.vue”文件和“register.vue”文件之间切换的面板。
根据我的理解,我需要做以下工作:
为创建模态的按钮创建一个Vue文件,该模态包括一个包含选项卡和切换面板的vue文件,这些选项卡和切换面板称为“登录”和“注册”Vue文件。
我希望我对Vue3.js框架处理事情的方式的理解是正确的。我对Laravel和Vue都很陌生,所以请耐心等待。
我的文件结构如下
资源|日本|页数|Auth -〉Login.vue(文件中的标准代码)
资源|日本|页数|Auth -〉Register.vue(文件中的标准代码)
资源|日本|页数|模态-〉登录注册.vue

<script>
  import Register from "./Auth/Register.vue";
  import Login from "./Auth/Login";

  export default {
    data: function () {
      return {
        tabs: ["Login", "Register"],
        selected: "Login",
      };
    },
    components: {
      Register,
      Login,
    },
  };
</script>

<template>
  <div>
    <button
      v-for="tab in tabs"
      :key="tab"
      @click="selected = tab;"
      :class="['tab-btn', { active: selected === tab }]"
    >
      {{ tab }}
    </button>
    <component :is="selected" class="tab"></component>
  </div>
</template>

或者我也在LoginRegister.vue中尝试过这段代码

<style>
  .tab-btn {
    padding: 6px 10px;
    background: #ffffff;
    cursor: pointer;
    margin-bottom: 1rem;
    border: 2px solid #cccccc;
    outline: none;
  }

  .active {
    border-bottom: 3px solid green;
    background: whitesmoke;
  }

  .tab {
    border: 1px solid #ccc;
    padding: 10px;
  }
</style>

<script>
  import Login from "./Auth/Login.vue";
  import Register from "./Auth/Register.vue";
  import PrimaryButton from "@/Components/PrimaryButton.vue";
  export default { components: { Login, Register } };
</script>

<template>
  <div>
    <PrimaryButton v-on:click="showModal = true"
      >Login / Register</PrimaryButton
    >
    <modal v-if="showModal" @close="showModal = false">
      <div
        class="modal fade"
        id="myModal"
        tabindex="-1"
        role="dialog"
        aria-labelledby="LoginRegisterModal"
      >
        <div class="modal-dialog" role="document">
          <div class="modal-content">
            <div class="modal-header">
              <button
                type="button"
                class="close"
                data-dismiss="modal"
                aria-label="Close"
              >
                <span aria-hidden="true">×</span>
              </button>
              <h4 class="modal-title" id="myModalLabel">Login / Register</h4>
            </div>
            <div class="modal-body">
              <ul class="nav nav-tabs">
                <li role="presentation" class="active">
                  <a
                    href="#tab1"
                    aria-controls="home"
                    role="tab"
                    data-toggle="tab"
                    >Login</a
                  >
                </li>
                <li role="presentation">
                  <a
                    href="#tab2"
                    aria-controls="profile"
                    role="tab"
                    data-toggle="tab"
                    >Register</a
                  >
                </li>
              </ul>
              <!-- Tab panes -->
              <div class="tab-content">
                <div role="tabpanel" class="tab-pane active" id="tab1">
                  <Login></Login>
                </div>
                <div role="tabpanel" class="tab-pane" id="tab2">
                  <Register></Register>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </modal>
  </div>
</template>

我仍然没有制定出如何创建一个按钮,将启动这在模态还没有,我知道我是一个很长的路要走,但我真的很感激指导。

qni6mghb

qni6mghb1#

我找到了一个很好的解决方案...下面的代码。

<script setup>
import { computed, onMounted, onUnmounted, watch } from 'vue';

const props = defineProps({
    show: {
        type: Boolean,
        default: false,
    },
    maxWidth: {
        type: String,
        default: '2xl',
    },
    closeable: {
        type: Boolean,
        default: true,
    },
});

const emit = defineEmits(['close']);

watch(() => props.show, () => {
    if (props.show) {
        document.body.style.overflow = 'hidden';
    } else {
        document.body.style.overflow = null;
    }
});

const close = () => {
    if (props.closeable) {
        emit('close');
    }
};

const closeOnEscape = (e) => {
    if (e.key === 'Escape' && props.show) {
        close();
    }
};

onMounted(() => document.addEventListener('keydown', closeOnEscape));

onUnmounted(() => {
    document.removeEventListener('keydown', closeOnEscape);
    document.body.style.overflow = null;
});

const maxWidthClass = computed(() => {
    return {
        'sm': 'sm:max-w-sm',
        'md': 'sm:max-w-md',
        'lg': 'sm:max-w-lg',
        'xl': 'sm:max-w-xl',
        '2xl': 'sm:max-w-2xl',
    }[props.maxWidth];
});
</script>

<template>
    <teleport to="body">
        <transition leave-active-class="duration-200">
            <div v-show="show" class="fixed inset-0 overflow-y-auto px-4 py-6 sm:px-0 z-50" scroll-region>
                <transition
                    enter-active-class="ease-out duration-300"
                    enter-from-class="opacity-0"
                    enter-to-class="opacity-100"
                    leave-active-class="ease-in duration-200"
                    leave-from-class="opacity-100"
                    leave-to-class="opacity-0"
                >
                    <div v-show="show" class="fixed inset-0 transform transition-all" @click="close">
                        <div class="absolute inset-0 bg-gray-500 opacity-75" />
                    </div>
                </transition>

                <transition
                    enter-active-class="ease-out duration-300"
                    enter-from-class="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
                    enter-to-class="opacity-100 translate-y-0 sm:scale-100"
                    leave-active-class="ease-in duration-200"
                    leave-from-class="opacity-100 translate-y-0 sm:scale-100"
                    leave-to-class="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
                >
                    <div v-show="show" class="mb-6 bg-white rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full sm:mx-auto" :class="maxWidthClass">
                        <slot v-if="show" />
                    </div>
                </transition>
            </div>
        </transition>
    </teleport>
</template>

然后使用无头用户界面切换选项卡,效果很好。

相关问题