• 《微信小程序-进阶篇》Lin-ui组件库源码分析-列表组件List(三)


    大家好,这是小程序系列的第二十二篇文章,在这一个阶段,我们的目标是 由简单入手,逐渐的可以较为深入的了解组件化开发,从本文开始,将记录分享lin-ui的源码分析,期望通过对lin-ui源码的学习能加深组件化开发的能力:
    1.《微信小程序-进阶篇》Lin-ui组件库源码分析-动画组件Transition(三)
    2.《微信小程序-进阶篇》Lin-ui组件库源码分析-列表组件List(一)
    3.《微信小程序-进阶篇》Lin-ui组件库源码分析-列表组件List(二)
    ——
    求关注,求收藏,求点赞,这是一个系列文章,建议专栏收藏,肯定分享的都是跟小程序相关的,旨在能提高在小程序中的能力,谢谢~

    前言

    上一篇我们了解了 List组件 的部分属性的实现,本篇将 分析剩下的所有属性与事件,并且我们在分析的过程中还发现了一些问题,耐心看完,你一定有所收获~

    阅读对象与难度

    本文难度属于:初中级,通过本文你可以了解到 Lin-ui的List组件中的属性,事件的实现,属性的解析顺序我们按照上一篇的属性用法顺序进行,本文主要内容参考以下思维导图:
    在这里插入图片描述

    徽标属性实现

    先看张图,回忆一下什么是徽标效果
    在这里插入图片描述
    就是这个,这个属性相关的有5个

    属性说明类型可选值默认值
    badge-position徽标显示的位置Stringleft/right/top/bottomright
    badge-count-type徽标数字的显示方式Stringoverflow/limit/customoverflow
    dot-badge显示圆点徽标Booleanfalse/truefalse
    badge-count徽标的数值String--
    badge-max-count徽标数字最大值,超过最大值时显示${max-count}+Number-----99

    那么在源码中,这5个属性对应的 properties 如下:

    badgePosition: {
      type: String,
      value: 'left'
    },
    dotBadge: Boolean,
    badgeCount: Number,
    badgeMaxCount: {
      type: Number,
      value: 99
    },
    badgeCountType: {
      type: String,
      value: 'overflow'
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这一部分,我们发现了3个默认值,分别是 badgePosition 默认为 leftbadgeMaxCount 默认为 99badgeCountType 默认为 overflow,官网看一下是否符合猜想~
    在这里插入图片描述

    结果发现,不是的.badgePosition 在代码中默认值是 left,但是官网上的默认值填写的却是 right,接下来我们仔细看一下源码,到底 是官方描述错误,还是说这个 在代码内部是反向实现

    badgePosition

    关于badge相关的html代码,一共有2段,分别是:

    <!-- left -->
    <l-badge 
       wx:if="{{(badgeCount > 0 || dotBadge ) && badgePosition ==='left'}}" 
       value="{{badgeCount}}" 
       dot="{{dotBadge}}" 
       max-count="{{badgeMaxCount}}" 
       number-type="{{badgeCountType}}">
        <template is="cell-left-main" data="{{image,icon,title,desc,tagContent,tagPosition,tagColor,tagShape,tagPlain,iconSize,iconColor}}" />
    </l-badge>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    以及

    <!-- right -->
    <l-badge 
      l-class="badge-right" 
      wx:if="{{(badgeCount > 0 || dotBadge ) && badgePosition ==='right'}}" 
      value="{{badgeCount}}" 
      dot="{{dotBadge}}" 
      max-count="{{badgeMaxCount}}" 
      number-type="{{badgeCountType}}">
        <template is="cell-right-main" data="{{rightDesc,tagContent,tagPosition,isLink,tagColor,tagShape,tagPlain}}" />
    </l-badge>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    先不说,这个属性的问题,我们发现这个 徽标属性标签属性 一样,都是内嵌的另外一个组件,l-badge,至此我们发现了 第三个lin-ui组件,然后我们再来看坐标默认显示问题;
    这两段明显是是代表了显示 左侧的l-badge 还是显示 右侧的l-badge,因为这两段都是通过 wx:if 实现的,并不存在我们说的反向显示的问题,所以,我个人认为这是一个BUG~

    路由属性实现

    接着,我们来看路由属性

    属性说明类型可选值默认值
    is-link是否显示跳转的图标Booleanfalse/truetrue
    link-type设置跳转类型StringnavigateTo/redirectTo/reLaunch/switchTabnavigateTo
    url设置跳转的路径String--

    与这3个属性相关的properties如下

    isLink: {
      type: Boolean,
      value: true,
    },
    linkType: {
      type: String,
      value: 'navigateTo'
    },
    url: String
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    与官网的属性核对一下
    在这里插入图片描述

    这个没有问题,都对得上,接着再看一下 wxml中的实现方式,搜索wxml文件,我们会发现,linkTypeurl 竟然 都是绑定在view上的,如下:

    <view 
      mut-bind:tap="tapcell" 
      data-url="{{url}}" 
      data-link-type="{{linkType}}">
    </view>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    由于是data开头,这个属性大概率是一个私有属性,那么这个跳转如何实现?不着急,往下看,既然是一个点击事件,我们接着看这个点击事件

    点击事件lintap

    当点击 view 的时候会触发一个 tap事件,事件的名字为:tapcell,那么就打开index.js文件找到tapcell事件,代码如下:

    tapcell: function (e) {
        const {
          linkType,
          url
        } = e.currentTarget.dataset;
        if (url) {
          wx[linkType]({
            url
          });
        }
        this.triggerEvent('lintap', {
          e
        }, { bubbles: true, composed: true });
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这段代码分开看,共有两部分功能,第一部分:实现路由跳转,第二部分:暴露点击事件lintap,先看第一部分:

    const {
      linkType,
      url
    } = e.currentTarget.dataset;
    if (url) {
      wx[linkType]({
        url
      });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    我们发现,点击的时候会从 e.currentTarget.dataset 中取到 url 以及 linkType,并且通过代码

    wx[linkType]({
      url
    });
    
    • 1
    • 2
    • 3

    实现了页面的跳转,比如现在是 linkType 的值 redirectTourl的值是’…/welcome/index’,这段代码就会变成

    wx['redirectTo']({
      url:'../welcome/index'
    });
    
    • 1
    • 2
    • 3

    这也就是为什么我们只需要在view上绑定了 data-urldata-link-type 后即可实现跳转,再来看第二段代码

     this.triggerEvent('lintap', {
        e
      }, { bubbles: true, composed: true });
    
    • 1
    • 2
    • 3

    根据用法,list上可以绑定一个 名为lintap的事件,为什么这个事件名叫做 lintap,因为这里使用自定义事件的触发方式 triggerEvent,另外这个自定义事件有两个参数:

    • 第一个参数:是提供给事件的 监听对象,这里把默认参数event传递过去了;
    • 第二个参数:这个参数是一个 配置选项,有以下三个参数:
    选项名类型是否必填默认值描述
    bubblesBooleanfalse事件是否冒泡
    composedBooleanfalse事件是否可以穿越组件边界,为 false 时,事件将只能在引用组件的节点树上触发,不进入其他任何组件内部
    capturePhaseBooleanfalse事件是否拥有捕获阶段

    样式属性实现

    最后是样式属性,样式属性有3个,如下

    属性说明类型可选值默认值
    gap设置list内左右两侧内容距list两边的间距Number--
    left-gap
    设置list内左侧内容距list左边的间距Number-
    right-gap
    设置list内右侧内容距list右边的间距Number-

    我们在js中分别搜索这几个属性,得到如下结果:

    gap: Number,
    leftGap: Number,
    rightGap: Number,
    
    • 1
    • 2
    • 3

    并且这几个属性并没有在js文件中另外搜索到,这就代表着 这几个属性也是直接作用在wxml上

    <view 
      class="l-list l-class" 
      hover-class="{{isHover?'l-list-hover':''}}" 
      hover-start-time="20" 
      hover-stay-time="50"  
      style="{{gap?'padding:0 '+gap+'rpx;':''}} {{leftGap?'padding-left:'+leftGap+'rpx':''}} {{rightGap?'padding-right:'+rightGap+'rpx':''}}" 
      mut-bind:tap="tapcell" 
      data-url="{{url}}"
      data-link-type="{{linkType}}">
    </view>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    关键行在于

    style="{{gap?'padding:0 '+gap+'rpx;':''}} {{leftGap?'padding-left:'+leftGap+'rpx':''}} {{rightGap?'padding-right:'+rightGap+'rpx':''}}" 
    
    • 1

    我们发现 gapleftGaprightGap 这几个属性就是 直接作用在DOM上的style中,对应的属性也只是padding 这个 css样式,通过 padding 实现了两侧的缩进功能,那么我们上次遇到的问题呢,看看这是不是一个BUG

    问题

    我们翻看上面的这段代码,发现一个奇怪的问题,它的样式明明是靠style实现的,但是style中的不同样式之间 竟然没有分号分隔,这也许就是造成这个问题的原因,我们尝试修改,在style的样式之间都加上分号,如下:

    <view 
      class="l-list l-class" 
      hover-class="{{isHover?'l-list-hover':''}}" 
      hover-start-time="20" 
      hover-stay-time="50" 
      style="{{gap?'padding:0 '+gap+'rpx;':''}} ;{{leftGap?'padding-left:'+leftGap+'rpx':''}} ;{{rightGap?'padding-right:'+rightGap+'rpx':''}}" 
      mut-bind:tap="tapcell" 
      data-url="{{url}}" 
      data-link-type="{{linkType}}">
    </view>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    加上之后发现确实生效了
    在这里插入图片描述

    hover属性实现

    hover属性在上一篇之中是放在样式属性中的,这篇单独放入一节的原因是因为hover它 虽然实现不复杂,但是它不是和上面的属性一样只做了一层转发,先来看看这个属性,用过用法我们知道传入的属性名叫做 isHover,但是我们直接搜isHover会 发现没有这个值
    在这里插入图片描述

    那么既然本文件没有,看看有没有混入:

    import hover from '../behaviors/hover';
    
    Component({
      behaviors:[hover]
      // ...
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    明显是有混入的,接着看看混入实现了什么功能

    // eslint-disable-next-line no-undef
    export default Behavior({
      behaviors: [],
      properties: {
        isHover:{
          type: Boolean,
          value: true
        }
      }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    打开后发现很简单,就是混入了一个 isHover属性,没有别的了,这样就找到了 isHover属性 的设置来源,之后,再找找实现功能的地方

    <view 
      class="l-list l-class" 
      hover-class="{{isHover?'l-list-hover':''}}" 
      hover-start-time="20" 
      hover-stay-time="50"></view>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    实现hover的地方 和实现padding,url是在一个view上,但是它是通过 hover-class 进行绑定的,绑定的类名叫做 l-list-hover 这个CSS类名,这个类名实现了一些hover上的交互效果;
    可能有小伙伴会问,hover-classhover-start-timehover-stay-time 是什么,简单的说下,这个是小程序 官方提供的一个属性,它提供了 可以指定元素触发时的动态效果,但是仅限绑定在 Viewbuttonnavigator等几个DOM上,具体属性及作用如下:

    属性类型默认值必填说明
    hover-classstringnone指定按下去的样式类。当 hover-class=“none” 时,没有点击态效果
    hover-stop-propagationbooleanfalse指定是否阻止本节点的祖先节点出现点击态
    hover-start-timenumber50按住后多久出现点击态,单位毫秒
    hover-stay-timenumber400手指松开后点击态保留时间,单位毫秒

    小结

    主要分析了Lin-ui中List组件实现,通过分析我们发现List组件其实是一个 复合组件,它的内部包含有三个Lin-ui中的其他组件:

    • 第一个组件:Icon组件,用于前置以及后置的icon图标;
    • 第二个组件:tag组件,用于显示list后部的标签;
    • 第三个组件:l-badge组件,用于实现徽标属性;

    之后,我们在分析到路由属性时发现,linkTypeurl 竟然都是 绑定在view上 的,当我们触发lintap的时候,会去读取 e.currentTarget.dataset 中对应的 urllinkType 的值,再实现路由的跳转;
    (PS:都已经看到这里了,点个赞,求个关注吧,万分感谢~)

  • 相关阅读:
    (pt可视化)利用torch的make_grid进行张量可视化
    Flutter 文件读写-path_provider
    SVN 服务器建立
    SpringBoot 3.0 新特性,内置声明式HTTP客户端
    MDM数据清洗功能开发说明
    多文件上传
    S7-200 SMART PLC 子程序功能块(阀门控制)
    JVM 面试题
    js获取当前地址栏链接参数
    leetcode题目分析(一)leetcode155最小栈
  • 原文地址:https://blog.csdn.net/zy21131437/article/details/126441747