您现在的位置是:首页 >技术杂谈 >基于Vant组件库二次封装组件(TS+Vue3.x环境)网站首页技术杂谈

基于Vant组件库二次封装组件(TS+Vue3.x环境)

凡大来啦 2023-05-15 08:00:02
简介基于Vant组件库二次封装组件(TS+Vue3.x环境)

1. 今天的需求是封装一个 Navigation Bar 导航栏组件,目的是给到App几乎所有的页面复用:

  

 


2. 因为之前的项目里使用过Vant组件库,笔者第一时间想到了Vant组件库中的 NavBar 组件,和当前App的需求匹配度很高。Vant组件库的 NavBar 组件:


3. 相信你也发现了,Vant组件库默认主题色是蓝色,而当前App的主题色是绿色,翻看了下Vant组件库的API文档,存在 ConfigProvider 全局配置,简单修改下样式即可:

:root {
  # 自定义主题色变量
  --cp-primary: #16C2A3;
  # 覆盖Vant主题色
  --van-primary-color: var(--cp-primary);
}

笔者在 http://t.csdn.cn/cCGFP 文章中介绍过全局引入Vant样式,这里我把需要修改主题色的代码放在了项目 src/styles/main.scss 里,不明白的小伙伴可以翻看前文!


4. 准备工作完成后正式开干,项目 src/components 文件夹下新建 cp-nav-bar.vue 组件,因为前文配置过按需引入,这里直接使用 <van-nav-bar /> 

<template>
  <div>
    <van-nav-bar
      :title="..."
      :right-text="..."
      left-arrow
      fixed
      @click-left="..."
      @click-right="..."
    />
  </div>
</template>
title                标题
right-text           右侧文案
left-arrow           是否显示左侧箭头
fixed                是否固定在顶部
click-left           点击左侧按钮时触发的事件
click-right          点击右侧按钮时触发的事件

跑起来观察后发现,van-nav-bar组件的字号和当前App有些差距,这里使用深度选择器修改下

<style scoped lang="scss">
:deep() {
  .van-nav-bar {
    &__arrow {
      font-size: 18px;
    }
    &__text {
      font-size: 15px;
    }
  }
}
</style>

vue3深度选择器不熟悉的同学,可以查看笔者的另一篇软文 http://t.csdn.cn/NkDbl


5. cp-nav-bar组件需要支持的功能:

① 支持  title  rightText  属性,父传子实现 (标题和右侧文字的自定义)

② 支持 click-right 事件,子传父实现 (右侧点击事件的抛出)

        注:右侧按钮对应要做的事情,应该是自己定义的,所以我们要支持事件,让他有自己的实现逻辑

③ 支持返回上一页功能        

        注: vue2和vue3获取路由方式有区别

                this.$router => useRouter()

                 this.$route => useRoute()


6. 标题和右侧文字的自定义

# 当前组件里
<script lang="ts" setup>
withDefaults(
  defineProps<{
    title?: string
    rightText?: string
  }>(),
  {
    title: '标题',
    rightText: '按钮'
  }
)
</script>
# 使用组件时
<cp-nav-bar title="凡大来了" right-text="他真的来了" />


7. 右侧点击事件的抛出

# 当前组件里
<script lang="ts" setup>
const emits = defineEmits<{
  (e: 'click-right'): void
}>()
const onClickRight = () => {
  emits('click-right')
}
</script>

<template>
  <div>
    <van-nav-bar
      :title="title"
      :right-text="rightText"
      left-arrow
      fixed
      @click-right="onClickRight"
    />
  </div>
</template>
# 使用组件时
<template>
  <div>
    <cp-nav-bar
      title="凡大来了"
      right-text="他真的来了"
      @click-right="handleClickRight"
    />
  </div>
</template>

<script lang="ts" setup>
const handleClickRight = () => {
  console.log('儿子的右侧按钮被点击了,父亲你要做点什么吗?')
}
</script>


8. 返回上一页功能

# 当前组件里
<script lang="ts" setup>
import { useRouter } from 'vue-router'

const router = useRouter()
const onClickLeft = () => {
  # 无脑回退是不严谨的
  # 如果back字段是个null,强制拉回我们项目的首页,反之回退
  # history不熟悉的,看下这里 https://developer.mozilla.org/zh-CN/docs/Web/API/History
  if (history.state.back) {
    router.back()
  } else {
    router.push('/')
  }
}
</script>

<template>
  <div>
    <van-nav-bar
      :title="title"
      :right-text="rightText"
      left-arrow
      fixed
      @click-left="onClickLeft"
      @click-right="onClickRight"
    />
  </div>
</template>
# 使用组件时
<cp-nav-bar />标签不需要任何操作,@click-left并没有抛出,只要引用了组件,都具有back功能


9. 有同学可能会有疑问:为什么可以直接使用组件,不导入不注册?

因为笔者在前文中 配置了 unplugin-vue-components 插件,该插 默认会把项目 src/compoenents 目录下的组件自动导入注册,是不是爽歪歪!!!

再次附上前文地址 http://t.csdn.cn/cCGFP


10. cp-nav-bar 组件类型配置

写到这里咱们的 cp-nav-bar 组件基本完成,还剩下最后一个痛点是缺失属性提示、事件提示、鼠标放上去也没有类型提示,这该怎么解决呢?

前文里我在 vite.config.js 文件中做了如下配置:

...
 
export default {
  plugins: [
    vue(),
    Components({
      # 不生成类型声明文件自己写
      dts: false
      ...   
    })
  ]
}

对!没错!我取消了自动生成类型声明文件,实际上你配置了也没卵用!为了解决缺失提示的痛点,笔者在 src目录下 types目录下 新建 components.d.ts

# 怎么给全局的组件提供类型?
# 写一个类型声明文件,declare module 'vue' 声明一个 vue 类型模块
# 然后 interface GlobalComponents 书写全局组件的类型
# key组件名称支持大驼峰, value是组件类型, 通过 typeof 组件实例得到

import CpNavBar from '@/components/cp-nav-bar.vue'

declare module 'vue' {
  interface GlobalComponents {
    CpNavBar: typeof CpNavBar
  }
}

End-------------------

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。