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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以参考以下步骤: 1. 首先安装 axios 和 qs(如果需要) 2. 在 main.js 中引入 axios 并进行二次封装: ``` import axios from 'axios' import qs from 'qs' axios.defaults.baseURL = 'http://api.xxx.com' // 设置接口基地址 axios.defaults.timeout = 10000 // 设置超时时间 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8' // 设置默认请求头 axios.interceptors.request.use(config => { // 在请求发送之前做一些处理 config.headers.token = localStorage.getItem('token') || '' return config }, error => { // 出错处理 return Promise.reject(error) }) axios.interceptors.response.use(response => { // 在响应成功处理之前做一些处理 return response }, error => { // 响应错误处理 return Promise.reject(error) }) function get (url, params) { return new Promise((resolve, reject) => { axios.get(url, { params }).then(res => { resolve(res.data) }).catch(err => { reject(err.data) }) }) } function post (url, data) { return new Promise((resolve, reject) => { axios.post(url, qs.stringify(data)).then(res => { resolve(res.data) }).catch(err => { reject(err.data) }) }) } export default { get, post } ``` 3. 在组件中使用二次封装后的 axios: ``` import request from '@/utils/request' methods: { getData () { request.get('/api/getData', { id: '123456' }).then(res => { console.log(res) }).catch(err => { console.log(err) }) } } ``` 以上是对于vue3 + vant + ts 配置axios的二次封装的一种实现,仅供参考。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值