记一次Vue3组件简单封装的过程

12 篇文章 0 订阅

我是一名不正经的Android开发,由于工作原因兼职了前端的工作,开始喜欢上了前端,不仅因为前端够灵活、够随意,够洒脱,而且有很多非常输出的UI库供我们选择。使得我们在很多时候只需关注业务逻辑,但有的时候UI库没有现成的组件,就需要我们自己封装了。

功能需求

在使用Vant时,需要一个类似DropdownMenu的下拉弹出层,但是不需要其menu,简单来说就是点击标题栏上的某一个图标,自上而下有一个弹出层,最终弹出层显示在标题栏的正下方。使用DropdownMenuPopup均不能满足需求,如果Popup可以设置偏移量那就完美了。

需求分析

结合Popup和组件taboffset-top属性来封装一个组件,组件具备的基本功能如下:

  1. v-model控制显示和关闭
  2. 是否显示遮罩层
  3. 点击遮罩层是否可以关闭
  4. 动态设置到顶部的偏移量
  5. 动态设置显示的层级(z-index)

前置知识点

  1. v-model的使用
  2. computed的使用
  3. 特殊组件transition的使用
  4. 插槽的使用
  5. css函数v-bind的使用

代码实现

<template>
  <transition name="dropdown-fade">
    <div
      v-if="overlay"
      v-show="isShow"
      @click="dissmissFilter"
      class="dropdown-overlay dropdown-filter"
      :class="isShow ? 'showMove' : ''"
    ></div>
  </transition>

  <transition name="dropdown-popup-slide-top">
    <div
      v-show="isShow"
      :class="isShow ? 'showMove' : ''"
      class="dropdown-container dropdown-filter"
    >
      <slot></slot>
    </div>
  </transition>
</template>

<script setup>
import { computed, ref } from 'vue'
const props = defineProps({
  show: {
    type: Boolean,
    default: false
  },
  offsetTop: {
    type: [String, Number],
    default: 0
  },
  overlay: {
    type: Boolean,
    default: true
  },
  closeOnClickOverlay: {
    type: Boolean,
    default: true
  },
  zIndex: {
    type: [String, Number],
    default: 2
  }
})
const emits = defineEmits(['update:show'])
const topDistance = computed(() => {
  if (typeof props.offsetTop === 'string') {
    return props.offsetTop
  } else {
    return `${props.offsetTop}px`
  }
})
const filterIndex = computed(() => {
  if (typeof props.zIndex == 'string') {
    return props.zIndex * 1
  } else {
    return props.zIndex
  }
})
const isShow = computed({
  get: () => props.show,
  set: (value) => {
    emits('update:show', value)
  }
})
const dissmissFilter = () => {
  if (props.closeOnClickOverlay) {
    isShow.value = false
  }
}
</script>

<style lang="less" scoped>
.dropdown-filter {
  position: fixed;
  top: v-bind(topDistance);

  left: 0;
  right: 0;
  z-index: v-bind(filterIndex);
}
.dropdown-overlay {
  background-color: rgba(0, 0, 0, 0.7);
  bottom: 0;
}
.dropdown-container {
  background-color: #fff;
  -webkit-transform: translate(0, -100%);
  transform: translate(0, -100%);
  -webkit-transition: all ease-in-out 0.3s;
  transition: all ease-in-out 0.3s;
  opacity: 0;
}
.showMove {
  opacity: 1;
  -webkit-transform: translate(0, 0);
  transform: translate(0, 0);
}

@keyframes van-fade-in {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes van-fade-out {
  from {
    opacity: 1;
  }

  to {
    opacity: 0;
  }
}
.dropdown-fade {
  &-enter-active {
    animation: 0.3s van-fade-in both ease-out;
  }
  &-leave-active {
    animation: 0.3s van-fade-out both ease-in;
  }
}
.dropdown-popup {
  &-slide-top-enter-active {
    transition-timing-function: ease-out;
  }
  &-slide-top-leave-active {
    transition-timing-function: ease-in;
  }
  &-slide-top-enter-from,
  &-slide-top-leave-active {
    transform: translate3d(0, -100%, 0);
  }
}
</style>

​ 其中css样式现在不是我的强项,但也算勉强实现了动画效果

组件使用

<template>
    <div>
        <TitleBar ref="navBar" title="提案工作" @clickRight="clickFilter">
        <drop-down-dialog  v-model:show="showFilter" :offset-top="offsetTop">
            下拉弹窗内容
        </drop-down-dialog>
    </div>
</template>

<script setup>
import TitleBar from '@/components/title-bar'
import DropDownDialog from '@/components/DropDownDialog.vue'
import { useRect } from '@vant/use'
import {ref,onMounted} from "vue"
const showFilter = ref(false)
const navBar = ref()
const offsetTop = ref(0)
const clickFilter = () => {
    showFilter.value = true
}
onMounted(()=>{
    // navBar.value.$el获取组件的dom元素
    const rect = useRect(navBar.value.$el)
    offsetTop.value = rect.height
})
</script>

<style lang="less" scoped>

</style>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想使用第三方的 Vue 3 表格组件封装一个表格,可以按照以下步骤进行操作: 1. 安装所需的表格组件。以 Element Plus 为例,你可以使用以下命令进行安装: ``` npm install element-plus ``` 2. 在你的 Vue 3 项目中导入并注册表格组件。在你的 main.js 文件中添加以下代码: ```javascript import { createApp } from 'vue'; import ElementPlus from 'element-plus'; import 'element-plus/dist/index.css'; import App from './App.vue'; const app = createApp(App); app.use(ElementPlus); app.mount('#app'); ``` 3. 创建一个新的 Vue 组件,用于封装表格。在这个组件中,你可以使用 Element Plus 提供的 Table 组件。 ```vue <template> <el-table :data="tableData"> <el-table-column v-for="column in tableColumns" :key="column.prop" :prop="column.prop" :label="column.label"> </el-table-column> </el-table> </template> <script> export default { data() { return { tableColumns: [ { prop: 'name', label: 'Name' }, { prop: 'age', label: 'Age' }, { prop: 'city', label: 'City' } ], tableData: [ { id: 1, name: 'John Doe', age: 25, city: 'New York' }, { id: 2, name: 'Jane Smith', age: 30, city: 'San Francisco' }, { id: 3, name: 'Bob Johnson', age: 35, city: 'Los Angeles' } ] }; } }; </script> ``` 在这个示例中,我们使用了 Element Plus 的 Table 组件,并通过 `tableColumns` 和 `tableData` 来动态渲染表格的列和数据。 你可以根据具体的表格组件的文档和需求,进一步自定义和扩展你的表格组件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值