十四、弹窗组件

目录

一、组件代码

二、使用组件


一、组件代码

(1)在src/libs/popup/index.vue中写如下代码

javascript 复制代码
<script setup>
import { useScrollLock, useVModel } from '@vueuse/core'
import { watch } from 'vue'
const props = defineProps({
  modelValue: {
    required: true,
    type: Boolean
  }
})

// const emits = defineEmits(['update:modelValue']) // 不用这个的原因是,下面的useVModel直接监听到props的变化,然后自动触发update:modelValue
const isOpen = useVModel(props)
// ----- 滚动锁定 -----
const isLocked = useScrollLock(document.body)
watch(
  isOpen,
  () => props.modelValue,
  (val) => {
    isLocked.value = val
  },
  {
    immediate: true
  }
)
</script>
<template>
  <div class="">
    <!-- teleport -->
    <teleport to="body">
      <!-- 蒙版 -->
      <transition name="fade">
        <div
          v-if="isOpen"
          class="w-screen h-screen bg-zinc-900/80 z-40 fixed top-0 left-0"
          @click="isOpen = false"
        ></div>
      </transition>
      <!-- 内容 -->
      <transition name="popup-down-up">
        <div
          v-if="isOpen"
          v-bind="$attrs"
          class="w-screen bg-white z-50 fixed bottom-0 dark:bg-zinc-800"
        >
          <slot />
        </div>
      </transition>
    </teleport>
  </div>
</template>

<style lang="scss" scoped>
// fade 展示动画
.fade-enter-active {
  transition: all 0.3s;
}

.fade-leave-active {
  transition: all 0.3s;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

// popup-down-up 展示动画
.popup-down-up-enter-active {
  transition: all 0.3s;
}

.popup-down-up-leave-active {
  transition: all 0.3s;
}

.popup-down-up-enter-from,
.popup-down-up-leave-to {
  transform: translateY(100%);
}
</style>

(2)src/libs/index.js中注册该组件

javascript 复制代码
import { defineAsyncComponent } from 'vue'

export default {
  install(app) {
    const components = import.meta.glob('./*/index.vue')
    for (const [key, value] of Object.entries(components)) {
      const componentName = 'm-' + key.replace('./', '').split('/')[0]
      app.component(componentName, defineAsyncComponent(value))
    }
  }
}

二、使用组件

在src/views/main/components/navigation/mobile/index.vue中使用组件

javascript 复制代码
<!-- 汉堡按钮 -->
      <li
        ...
        @click="isOpenPopup = !isOpenPopup"
      >
        ...
      </li>

<m-popup v-model="isOpenPopup">
  <div>测试内容</div>
</m-popup>

然后就可以在这个组件的插槽里面放入相应的数据了

至此,这个弹窗组件完成!

三、在插槽中放入业务组件

这里就是展示一个弹出的菜单

(1)组件代码

src/views/main/components/menu/index.vue

javascript 复制代码
<script setup>
defineEmits(['onItemClick'])
//这里的数据是从vuex获取的,也可以从使用组件的地方传过来
</script>
<template>
  <div class="py-2 h-[80vh] flex flex-col">
    <h2 class="text-xl text-zinc-900 font-bold mb-2 px-1 dark:text-zinc-200">所有分类</h2>
    <ul class="overflow-y-scroll">
      <li
        v-for="(item, index) in $store.getters.categorys"
        :key="item.id"
        class="text-lg text-zinc-900 px-1 py-1.5 duration-100 active:bg-zinc-100 dark:text-zinc-300 dark:active:bg-zinc-900"
        @click="$emit('onItemClick', index)"
      >
        {{ item.name }}
      </li>
    </ul>
  </div>
</template>

<style lang="scss" scoped></style>

(2)在popup中绑定业务组件中触发的点击事件

javascript 复制代码
    <m-popup v-model="isOpenPopup">
      <menu-vue @onItemClick="onItemClick"></menu-vue>
    </m-popup>

const onItemClick = (index) => {
  currentCategoryIndex.value = index
  isOpenPopup.value = false
}

至此,整个弹窗封装完成!

相关推荐
寅时码2 小时前
React 之死·终章:一个 useRef,把闭包陷阱、依赖数组、漫天 rerender 全送走
前端·react.js·ai编程
不好听6132 小时前
HTML 事件监听机制:从 DOM Level 0 到 React 合成事件
前端·react.js·html
wordbaby2 小时前
为什么刷新页面就 404?聊聊 SPA 路由与 Nginx 的那点事
前端
不好听6133 小时前
React 核心概念:JSX、组件与数据驱动
前端·react.js
触底反弹3 小时前
🔥 React 零基础入门(中):500 行屎山代码到组件化的蜕变
前端·javascript·react.js
不好听6133 小时前
React vs Vue:两大前端框架技术选型深度对比
前端·vue.js·react.js
GuWenyue3 小时前
Cursor黑盒拆解!1套LangChain.js手写Mini编程Agent,自动生成React项目,效率提升60%
前端·数据库·人工智能
GuWenyue3 小时前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法
小林ixn4 小时前
从 onclick 到 React 合成事件,再到完整应用逻辑:一次前端架构的深度剖析
前端·react.js·前端框架
Csvn4 小时前
🧩「找不到模块」排查全记录——Monorepo 下 TypeScript 路径别名的 5 种「不通」与根治方案
前端