物料库之popup

一、分析一波🌝🌝🌝

  • popup 是独立的组件,放到body下面
  • popup 含两部分内容,一部分为背景蒙版,一部分为内容的包裹容器
  • popup 通过双向绑定的值进行控制展示和隐藏
  • popup 展示时,页面滚动应该被锁定
  • 内容区域应该接收所有的 attrs,并且应该通过插槽让调用方指定其内容

二、构建🌪️🌪️🌪️

1. 新建 src/libs/popup/index.vue 文件

小知识点:v-model双向数据绑定,底层机制defineModel 是一个便利宏。 编译器将其展开为以下内容:

  • 一个名为 modelValue 的 prop,本地 ref 的值与其同步;
  • 一个名为 update:modelValue 的事件,当本地 ref 的值发生变更时触发
xml 复制代码
<template>
  <div>
    <!-- teleport -->
    <teleport to="body">
      <!-- 蒙版 -->
      <transition name="fade">
        <div
          v-if="modelValue"
          class="w-screen h-screen bg-zinc-900/80 z-40 fixed top-0 left-0"
          @click="emits('update:modelValue', false)"
        ></div>
      </transition>
      <!-- 内容 -->
      <transition name="popup-down-up">
        <div
          v-if="modelValue"
          v-bind="$attrs"
          class="w-screen bg-white z-50 fixed bottom-0"
        >
          <slot />
        </div>
      </transition>
    </teleport>
  </div>
</template>

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

const emits = defineEmits(['update:modelValue'])

// ------ 滚动锁定 ------
const isLocked = useScrollLock(document.body)
watch(
  () => props.modelValue,
  (val) => {
    isLocked.value = val
  },
  {
    immediate: true
  }
)
</script>

<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>

优化一下:v-model双向数据绑定,由于不可以在子组件直接修改响应式数据,所以有一些不太方便 ,那应该怎么优化呢?可以使用vueuse 提供的 useVModel,通过 useVModel 获取到响应式数据,当响应式数据的状态变化时,自动触发 update:modelValue

xml 复制代码
<template>
<!-- 无需主动触发 事件 -->
<div
  v-if="isOpen"
  class="w-screen h-screen bg-zinc-900/80 z-40 fixed top-0 left-0"
  @click="isOpen = false"
></div>
<div
  v-if="isOpen"
  v-bind="$attrs"
  class="w-screen bg-white z-50 fixed bottom-0"
>
  <slot />
</div>
...
</template>

<script setup>
import { useVModel } from '@vueuse/core'
...
// 不需要主动触发了
// const emits = defineEmits(['update:modelValue'])

// 通过 useVModel 获取到响应式数据 isOpen
const isOpen = useVModel(props)

...
// 监听 isOpen 的变化即可
watch(
  isOpen,
  ...
)
</script>
2. 小试牛刀 demo.vue
xml 复制代码
<template>
<m-popup v-model="isOpenPopup">
  <div>测试m-popup</div>
</m-popup>
</template>

<script setup>
// 控制popup显示/隐藏
const isOpenPopup = ref(true);
</script>
相关推荐
CharlesYu019 小时前
前端性能优化的第一性原理,是不断缩短“用户发起意图 → 获得可用结果”之间的时间
前端
平头哥技术团队9 小时前
Day 21 _ 页内锚点_给每段起个 id,目录写 href=_#id_,点一下页面就滚到那一段
前端·html·html5
子兮曰10 小时前
Bun v1.4.1 深度解析:从 Zig 到 Rust,一场 11 天、64 个 AI 代理的语言迁徙
前端·后端·bun
人民广场吃泡面10 小时前
什么是AI Agent?它又能给前端带来哪些效率提升?
前端·人工智能
中科三方11 小时前
两家域名注册商资质被ICANN终止:企业域名资产安全再受关注
前端·网络·安全·域名
bug总结11 小时前
uniapp vue3全局方法注册使用
前端·javascript·uni-app
华无丽言12 小时前
如何在宜搭中实现获取子表中的字段值赋值到父表中?
前端·javascript·低代码
IT_陈寒12 小时前
Vue的computed属性竟然坑了我一把
前端·人工智能·后端
威斯软科的老司机12 小时前
通俗讲解 CNN 图像识别、向量 Embedding、Softmax 概率计算这三块的简化原理
前端·人工智能·ui·数字孪生
2601_9623824313 小时前
剑指大前端全栈工程师(全2册)主要情节
javascript·实战案例·全栈工程师·剑指大前端·html5+css3