小程序click-scroll组件设计

一. 背景

有些业务需求,要求前端展示的内容多时可以通过scroll的形式拖拉查看,但是太多的滚动条又造成页面太乱,于是封装了这个click-scroll 组件。在组件上设定好展示的位置和空间大小,在组件内部放置实际要展示的内容,实际展示的内容宽度或长或短都由此组件来控制。

二. 功能

组件内的内容宽度超过组件宽度时,组件两侧会自动出现『左右移动』交互。

当内部展示的内容超过组件的可见区域时,可以在组件的可见区域单击拖动查看内容

三. 背景知识,元素大小的测量

1.偏移量(offset dimension):

元素在屏幕上占用的可见的所有空间,元素的可见大小由其高度、宽度决定,包括所有内边距、滚动条和边框大小。由四个值决定:offsetHeight、offsetWidth、offsetLeft和offsetRight。

  • offsetHeight:元素在垂直方向上占用的空间大小,以像素计。包括元素的高度、(可见)水平滚动条的高度、上边框高度和下边框高度。
  • offsetWidth:元素在水平方向上占用的空间大小,以像素计。包括元素的宽度、(可见)垂直滚动条的宽度、左边框宽度和右边框宽度。
  • offsetLeft:元素的左外边框至包含元素的左内边框之间的像素距离。 d.
  • offsetTop:元素的上外边框至包含元素的上内边框之间的像素距离。

2.客户区大小(client dimension)

元素内容及其内边距所占据空间的大小,滚动条占用的空间不计算在内。

  • clientWidth:元素内容区宽度加上左右内边距的宽度
  • clientHeight: 元素内容区高度加上上下内边距的高度

3.滚动大小(scroll dimension)

包含滚动内容的元素的大小。

  • scrollHeight:在没有滚动条的情况下,元素内容的实际总高度。
  • scrollWidth:在没有滚动条的情况下,元素内容的实际总宽度。
  • scrollLeft:被隐藏在内容区域左侧的像素数。通过设置这个属性可以改变元素的滚动位置。
  • scrollTop:被隐藏在内容区域上方的像素数。通过设置这个属性可以改变元素的滚动位置。

四. 组件设计思路

五. 使用文档

slot:

参数 说明 类型
content 组件实际要展示的内容 dom
<click-scroll>
  <template slot="content">
    <div>
      我是实际要展示的内容啊啊啊啊啊……
    </div>
  </template>
</click-scroll>

六. 组件源码

<template>
 <div class="hui-hui" :id="domId.compID">
  <!--向左滑动-->
  <div class="hui-drag-left"
     :class="{'hui-drag-action': drag.isLeft}"
     v-if="drag.isShow"
     @click="onClickLeft">
  </div>

  <!--展示的内容-->
  <div :id="domId.containerID"
     class="hui-container"
     v-show="hasContent"
     ref='container'
     @mousedown="onMouseDown">
   <slot name="content"></slot>
  </div>
  <div v-show="!hasContent" class="hui-no-data">暂无数据</div>

  <!--向右滑动-->
  <div class="hui-drag-right"
     :class="{'hui-drag-action': drag.isRight}"
     v-if="drag.isShow"
     @click="onClickRight">
  </div>
 </div>
</template>

<script>
import store from '@/store'
export default {
 name: 'cards-container',
 data () {
  return {
   hasContent: false,
   domId: {
    compID: `hui-comp-${+new Date()}`,
    containerID: `hui-container-${+new Date()}`
   },
   drag: {
    isShow: false,
    isLeft: false,
    isRight: false
   }
  }
 },
 methods: {
  judgeHasContent () {
   this.hasContent = this.$slots.hasOwnProperty('content')
  },

  judgeDragIsShow () {
   const compWidth = this.getCompWidth()
   const contextMaxWidth = this.getContextMaxWidth()

   if (compWidth >= contextMaxWidth) {
    this.drag.isShow = false
   } else {
    this.drag.isShow = true
   }
   return this.drag.isShow
  },
  judgeIsLeft () {
   const containerDom = this.getContainerDom()
   const contentWidth = this.getContextMaxWidth()

   if (!containerDom && !contentWidth) this.drag.isLeft = false
   if (containerDom.offsetWidth + containerDom.scrollLeft >= contentWidth) {
    this.drag.isLeft = false
   } else {
    this.drag.isLeft = true
   }
  },
  judgeIsRight () {
   const containerDom = this.getContainerDom()

   if (!containerDom) this.drag.isRight = false
   if (containerDom.scrollLeft === 0) {
    this.drag.isRight = false
   } else {
    this.drag.isRight = true
   }
  },

  getCompDom () {
   return document.getElementById(this.domId.compID) || null
  },
  getCompWidth () {
   const compDom = this.getCompDom()
   if (!compDom) {
    return 0
   } else {
    return compDom.offsetWidth
   }
  },
  getContainerDom () {
   return document.getElementById(this.domId.containerID) || null
  },
  getContextMaxWidth () {
   if (!this.$refs.hasOwnProperty('container')) {
    return 0
   } else {
    const widthArr = []
    for(let e of this.$refs['container'].childNodes) {
     widthArr.push(e.offsetWidth)
    }
    return Math.max(...widthArr)
   }
  },

  onMouseDown (e) { // 手动滑动
   const containerDom = this.getContainerDom()
   if (!containerDom) return

   let scrollLeft = containerDom.scrollLeft
   const containerLeft = containerDom.offsetLeft
   let ev = e || window.event
   let offsetLeft = ev.clientX - containerLeft

   document.onmousemove = (e) => {
    let ev = e || window.event
    let nowOffsetLeft = ev.clientX - containerLeft
    containerDom.scrollLeft = scrollLeft + (offsetLeft - nowOffsetLeft)

    this.judgeIsLeft()
    this.judgeIsRight()
   }

   document.onmouseup = () => {
    document.onmousemove = null
    document.onmouseup = null
   }
  },

  onClickLeft () { // 向左滑动
   if (!this.hasContent && !this.drag.isLeft) return

   const containerDom = this.getContainerDom()
   if (!containerDom) return

   const scrollWidth = containerDom.offsetWidth
   containerDom.scrollLeft += scrollWidth

   this.judgeIsLeft()
   this.judgeIsRight()
  },

  onClickRight () { // 向右滑动
   if (!this.hasContent && !this.drag.isRight) return

   const containerDom = this.getContainerDom()
   if (!containerDom) return

   const scrollWidth = containerDom.offsetWidth
   containerDom.scrollLeft -= scrollWidth

   this.judgeIsLeft()
   this.judgeIsRight()
  }
 },
 updated () {
  this.$nextTick(() => {
   this.judgeHasContent()
   const isShow = this.judgeDragIsShow()
   if (isShow) {
    this.judgeIsLeft()
    this.judgeIsRight()
   }
  })
 },
 mounted () {
  this.judgeHasContent()
  const isShow = this.judgeDragIsShow()
  if (isShow) {
   this.judgeIsLeft()
   this.judgeIsRight()
  }
 }
}
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 微信小程序实现YDUI的ScrollTab组件

    本文实例为大家分享了微信小程序实现滚动选项卡效果的具体代码,供大家参考,具体内容如下 DEMO下载 效果图 YDUI的ScrollTab(滚动选项卡) WXML <!--导航 --> <view class="tui-fixed-left"> <scroll-view class="tui-city-scroll" scroll-x="true"> <text bindtap="getStatu

  • 小程序scroll-view组件实现滚动的示例代码

    前言:这章我们使用小程序的 scroll-view组件 实现横向滚动和竖向滚动. GitHub: https://github.com/Ewall1106/miniProgramDemo 1.竖向滚动 首先从简单的来,竖向滚动很简单,只用记住两点即可: 首先得设置 scroll-y 属性: 其次,一定要给 scroll-view 设置一个 height 高度: <scroll-view scroll-y style="height: 200px;"> <view cl

  • 微信小程序scroll-view组件实现滚动动画

    本文实例为大家分享了scroll-view组件实现索引列表滚动动画效果,供大家参考,具体内容如下 效果图 实现原理 利用scroll-view的scroll-into-view属性进行定位: 利用scroll-view的scroll-with-animation属性实现滚动动画过度. WXML <view class="right-nav"> <view bindtap="getCurrentCode" class="{{chooseIn

  • 微信小程序 scroll-view组件实现列表页实例代码

    scroll-view组件介绍 scroll-view是微信小程序提供的可滚动视图组件,其主要作用是可以用来做手机端经常会看到的上拉加载下拉刷新列表页!下面就以<摇出微笑>为例来讲解一下这个组件的使用吧! 为app导入新page页面 首先需要为我们的小程序导入新的page页面,项目根目录打开app.json这个项目配置文件在里面的pages数组添加"pages/allJoke/allJoke"然后设置底部导航在"tabBar"的列表项("lis

  • 微信小程序实现YDUI的ScrollNav组件

    本文实例为大家分享了微信小程序实现滚动导航效果的具体代码,供大家参考,具体内容如下 DEMO下载 效果图 实现原理 采用双 scroll-view 组件实现双滚动! WXML <!--导航滚动 --> <scroll-view class="tui-city-scroll" scroll-x="true" scroll-into-view="NAV{{status}}" scroll-with-animation="t

  • 微信小程序(九)scroll-view组件详细介绍

    scroll-view为滚动视图,分为水平滚动和垂直滚动.注意滚动视图垂直滚动时一定要设置高度否则的话scroll-view不会生效.滚动视图常用的地方一般都是Item项比较多的界面,比如我的模块 主要属性: 使用演示: wxml <!--垂直滚动,这里必须设置高度--> <scroll-view scroll-y="true" style="height: 200px"> <view style="background: r

  • 微信小程序开发之组件设计规范

    微信小程序组件设计规范 组件化开发的思想贯穿着我开发设计过程的始终.在过去很长一段时间里,我都受益于这种思想. 组件可复用 - 减少了重复代码量 组件做为抽离的功能单元 - 方便维护 组件作为template使用,可以方便计算各种属性而不是在wxml引入wxs 在日常的小程序开发组件过程中,我一般会遵循如下几个规则: 1.样式独立 & 依赖独立 在组件开发过程中,组件可以依赖于全局样式,组件在引入时,使用该页面样式和全局样式共同渲染. options: { addGlobalClass: tru

  • 仿iPhone通讯录制作小程序自定义选择组件的实现

    前言 近期闲来无事,想着闲着也是闲着,不如给自己搞点事情做!敢想敢做,于是选择了给微信小程序做个 仿iPhone通讯录 效果的自定义组件. 先来整理一下,瞧瞧需要实现的核心功能. 按照第一个字的首字母排序; 实现输入搜索功能: 侧边栏字母导航: 基本上分为3块: 顶部的搜索区域: 内容的展示区域: 侧边字母导航栏区域: // index.wxml <view class="main"> <!-- 顶部搜索区域 --> <view class="h

  • uni-app小程序中父组件和子组件传值的实现实例

    目录 前言 一.父组件向子组件传值 二.子组件向父组件传值 总结 前言 1.父组件向子组件传值 → 通过数据绑定 2.子组件向父组件传值 → 通过事件 一.父组件向子组件传值 通过props实现,即:子组件通过props来接收父组件传过来的值 实现 父组件中: 1.引入子组件 2.注册子组件 3.通过标签形式载入:使用数据绑定进行传值 子组件中: 1.通过props接收父组件中传递过来的值 具体演示代码 父组件:index.vue <template> <comA :list="

  • 微信小程序 wxapp内容组件 icon详细介绍

    微信小程序 内容组件 相关文章: 微信小程序 wxapp内容组件 icon 微信小程序 wxapp内容组件 text 微信小程序 wxapp内容组件progress icon 图标. 属性名 类型 默认值 说明 type String   icon的类型,有效值:success, success_no_circle, info, warn, waiting, cancel, download, search, clear size Number 23 icon的大小,单位px color Col

  • 微信小程序 视图容器组件的详解及实例代码

    微信小程序 视图容器组件详解: 小程序给出的视图容器组件有三个:</view>.</scroll-view>和</swiper>: 1.</view> 视图容器 </view>相当于html中的</div>标签,有四个属性: hover和hover-class与点击效果有关:hover设置是否启用点击效果,而hover-class设置点击的效果. hover-start-time和hover-stay-time与点击效果的时间有关:h

  • 微信小程序中button组件的边框设置的实例详解

    微信小程序中button组件的边框设置的实例详解 button的边框是用:after方式实现的,用户如果在button上定义边框会出现两条线,需用:after的方式去覆盖默认值. 如果设置了Button的背景色,没有用:after设置边框的颜色,则button的四个角会出现模糊的尖角.如下图所示: 如上图四个角会模糊..wxss代码如下: .clickEncryptBtn{ width:130px; border-radius: 3px; margin:20px auto; padding-to

  • 微信小程序 wxapp内容组件 progress详细介绍

    微信小程序 内容组件 相关文章: 微信小程序 wxapp内容组件 icon 微信小程序 wxapp内容组件 text 微信小程序 wxapp内容组件progress 微信小程序内容组件 进度条:progress 进度条 属性名 类型 默认值 说明 percent Float 无 百分比0~100 showInfo Boolean false 在进度条右侧显示百分比 strokeWidth Number 6 进度条线的宽度,单位px color Color #09BB07 进度条颜色 active

  • 微信小程序 Canvas增强组件实例详解及源码分享

    WeZRender是一个微信小程序Canvas增强组件,基于HTML5 Canvas类库ZRender. 使用 WXML: <canvas style="width: 375px; height: 600px;" canvas-id="line-canvas-1">canvas> JS: var wezrender = require('../../lib/wezrender'); zr = wezrender.zrender.init("

  • 微信小程序 wxapp内容组件 text详细介绍

    微信小程序 内容组件 相关文章: 微信小程序 wxapp内容组件 icon 微信小程序 wxapp内容组件 text 微信小程序 wxapp内容组件progress 微信小程序内容组件:text 文本节点,支持转义符"\". 除了文本节点以外的其他节点都无法长按选中 示例: <view class="section section_gap"> <text>{{text}}</text> <view class="b

  • 微信小程序基于slider组件动态修改标签透明度的方法示例

    本文实例讲述了微信小程序基于slider组件动态修改标签透明度的方法.分享给大家供大家参考,具体如下: 1.效果展示 2.关键代码 index.wxml <view class="img" style="opacity:{{imgOpacity}}"></view> <slider min="0" max="1" step="0.1" show-value value=&quo

随机推荐