likes
comments
collection
share

原生小程序实现tooltips提示信息

作者站长头像
站长
· 阅读数 53
大家好我是小文同学,失踪人口回归了。被自己的懒惰失踪的三周里,属实没有学习没有进度,真是太罪恶了。所以我来了。

1. 背景

故事是这样的,之前有个重构的需求里出现了这样的一个弹窗。唤醒姿势是点击某个按钮或者tips的icon时需要出现这样的提示。回过头来找找之前我们维护的组件库,嗯确实有人已经写过的这样的组件啦!正打算用的时候发现用不了。。。。为什么呢,因为我们的小程序项目是基于mpx框架构建而成的,然而已有的组件是用的mpx文件写的,然后我要重构的页面是原生小程序实现的。。。出于安全考虑,还是在原页面上进行修改吧。嗯所以自己就简单的写了一个单纯只在我这里实现的tips而已了。

原生小程序实现tooltips提示信息

2. 学习

在写完这个简单的实现之后,我就去看看当时这个组件是怎么实现的啦。

经过我的粗略学习,该组件的开发者写了一个简单的event.js,实现了一个消息中心,也就是我们所认识的发布订阅模式。通过该方法在组件attached的时候去监听某个事件,在点击某个地方的时候再emit激活该事件。

因为mpx的增加能力使得我们能够在项目中使用ref获取某个元素,这也为实现在该项目中实现该功能提供了很大的便利,例如直接通过ref获取这个元素的一些信息,并且可以做相应的处理。以下是我学习完总结出来用原生的写法的一个版本。

3.原生小程序实现

<view class="tooltip my-class" bindtap="clickTips">
  <view class="tips {{ isNeedTips ? 'visible' : 'hidden' }} {{ placement }}" style="width: {{ tooltipWidth + 'rpx' }}">{{ tips }}</view>
  <view>{{ content }}</view>
</view>
 const screenWidth = wx.getSystemInfoSync().windowWidth // 获取设备信息(宽度)
 externalClasses: ['my-class'],
 properties: {
    placement: {
      type: String,
      value: 'top' // right bottom left
    },
    content: String,
    tips: String,
    maxWidth: {
      type: Number,
      value: 354
    },
    duration: {
      type: Number,
      value: 2000
    }
 },
data() {
  return {
    tooltipWidth: 100
  }
}
lifetimes: {
  attached() {
    this.getTooltipWidth()
    this.judgePosition()
  }
}
methods: {
  getTooltipWidth() {
    const contentRPXWidth = this.data.tips.length * 28 + 36 * 2 // 自定义的一个tips宽度
    const conetntPXWidth = (contentRPXWidth / 750) * screenWidth // 根据屏幕适配的宽度
      wx.createSelectorQuery().in(this).select('.tooltip').boundingClientRect(({ width }) => {
        const {
          maxWidth
        } = this.data
        let tooltipWidth = 0
        // 获取自定义元素的宽度 与 屏幕适配宽度做比较
        // 最终参考使用一个合适的宽度作为 tips 的宽度
        if (conetntPXWidth < width) {
          tooltipWidth = contentRPXWidth
        } else {
          tooltipWidth = contentRPXWidth < maxWidth ? contentRPXWidth : maxWidth
        }
        this.setData({
          tooltipWidth
        })
      }).exec()
    }
  },
  // 判断tips是否在某个位置上有足够的空间放置
  judgePosition() {
     // 同理通过 wx.createSelectorQuery().in(this).select('').boundingClientRect去获取自定义元素的位置元素信息以及tips的位置元素信息去做处理
     // 在这里只列举了其中一种情况的例子进行判断来设置该tips的实际放置位置
     // 以下情况可能出现的场景是:自定义元素放置的位置过于偏左 导致上下的tips没办法放置 因此设置tips到右边 别的情况同理
     if (placement === 'top' || placement === 'bottom') 
     const targetLeftCenter = targetLeft + targetWidth / 2 // 点击元素的中间位置坐标
                if (targetLeftCenter < tipWidth / 2) {
                  this.setData({
                    placement: 'right'
                  })
                }
  }
  clickTips() {
     const { duration } = this.data
     this.setData({ isNeedTips: true }) // 显示tips
     let timer = setTimeout(() => {
         this.setData({
           isNeedTips: false // 在duration毫秒后隐藏tips
         })
         wx.nextTick(() => {
            clearTimeout(timer) && (timer = null) // 清理定时器
         })
     }, duration)
     this.triggerEvent('click') // 抛出一个点击事件
  }
  
  • tooltip最外层样式类名my-class使用了externalClasses: ['my-class'],给用户提供了自定义元素样式的机会
  • clickTips事件实现了点击自定义元素时,弹出tips
  • tips的实现本来是想用伪元素来实现的,但是这样的话就没办法动态改变该tips的宽,在这里tips的宽度是根据自定义元素的宽度tips的文字长度一个计算方式比较得出的使用宽度
  • isNeedTips用于控制该tips的显示与否
  • placement用于控制该tips显示的位置(上、下、左、右)
  • tooltipWidth用于设置该tips的宽度
  • tips用于设置该tips的内容
  • content用于设置自定义元素的内容
  • duration用于设置tips的显示时间
  • maxWidth是该tips的默认最大宽度 参考下图

原生小程序实现tooltips提示信息

4.使用方法

<tooltip my-class="myClass" content="我是内容" tips="我是提示" placement="top" duration="1000" bind:click="handleClick"></tooltip>

5.参考文档

externalClasses

developers.weixin.qq.com/miniprogram…

wx.getSystemInfoSync() developers.weixin.qq.com/miniprogram…

wx.createSelectorQuery() developers.weixin.qq.com/miniprogram…

wx.nextTick() developers.weixin.qq.com/miniprogram…

写在最后

小文同学学艺不精,有写的不好的地方欢迎多多指教啦。一些css代码以及js代码就不贴啦~主要是想跟大家交流一下实现思路。希望广大优秀网友们帮我该组件再提供一些建议我好去补充啦!

最后感谢各位抽出宝贵时间看小文的文章!我们下期再见!

转载自:https://juejin.cn/post/7012301682977538079
评论
请登录