小程序click-scroll组件设计


Posted in Javascript onJune 18, 2019

一. 背景

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

二. 功能

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

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

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

1.偏移量(offset dimension):

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

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

小程序click-scroll组件设计

2.客户区大小(client dimension)

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

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

小程序click-scroll组件设计

3.滚动大小(scroll dimension)

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

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

小程序click-scroll组件设计

四. 组件设计思路

小程序click-scroll组件设计

五. 使用文档

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>

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

Javascript 相关文章推荐
css图片自适应大小
Nov 28 Javascript
jQuery写的日历(包括日历的样式及功能)
Apr 23 Javascript
jQuery关于导航条背景切换效果实现示例
Sep 04 Javascript
使用jquery修改表单的提交地址基本思路
Jun 04 Javascript
js 模式窗口(模式对话框和非模式对话框)的使用介绍
Jul 17 Javascript
JS实现淘宝支付宝网站的控制台菜单效果
Sep 28 Javascript
jQuery实现文本框邮箱输入自动补全效果
Nov 17 Javascript
JavaScript中文件上传API详解
Apr 01 Javascript
JS使用正则表达式过滤多个词语并替换为相同长度星号的方法
Aug 03 Javascript
jquery对所有input type=text的控件赋值实现方法
Dec 02 Javascript
BootStrap3中模态对话框的使用
Jan 06 Javascript
关于jQuery.ajax()的jsonp碰上post详解
Jul 02 jQuery
在JavaScript中如何访问暂未存在的嵌套对象
Jun 18 #Javascript
用Vue.js在浏览器中实现裁剪图像功能
Jun 18 #Javascript
JS删除String里某个字符的方法
Jan 06 #Javascript
简单了解Javscript中兄弟ifream的方法调用
Jun 17 #Javascript
vue中typescript装饰器的使用方法超实用教程
Jun 17 #Javascript
简单学习5种处理Vue.js异常的方法
Jun 17 #Javascript
js/jQuery实现全选效果
Jun 17 #jQuery
You might like
PHP+Mysql+jQuery查询和列表框选择操作实例讲解
2015/10/22 PHP
php截取视频指定帧为图片
2016/05/16 PHP
PHP基本语法实例总结
2016/09/09 PHP
thinkPHP模板引擎用法示例
2016/12/08 PHP
Nigma vs Liquid BO3 第一场2.13
2021/03/10 DOTA
js操作checkbox遇到的问题解决
2013/06/29 Javascript
使用javascript实现页面定时跳转总结篇
2013/09/21 Javascript
JavaScript获取网页表单提交方式的方法
2015/04/02 Javascript
JavaScript中switch语句的用法详解
2015/06/03 Javascript
js console.log打印对像与数组用法详解
2016/01/21 Javascript
深入理解JavaScript中为什么string可以拥有方法
2016/05/24 Javascript
第三篇Bootstrap网格基础
2016/06/21 Javascript
关于JSON与JSONP简单总结
2016/08/16 Javascript
jquery UI Datepicker时间控件冲突问题解决
2016/12/16 Javascript
JSON与js对象序列化实例详解
2017/03/16 Javascript
js解决软键盘遮挡输入框的问题分享
2017/12/19 Javascript
React数据传递之组件内部通信的方法
2017/12/31 Javascript
为vue-router懒加载时下载js的过程中添加loading提示避免无响应问题
2018/04/03 Javascript
vue的style绑定background-image的方式和其他变量数据的区别详解
2018/09/03 Javascript
Vue项目实现换肤功能的一种方案分析
2019/08/28 Javascript
在Layui中操作数据表格,给指定单元格添加事件示例
2019/10/26 Javascript
vue 使用鼠标滚动加载数据的例子
2019/10/31 Javascript
详解vue-flickity的fullScreen功能实现
2020/04/07 Javascript
[03:01]2014DOTA2国际邀请赛 DC:我是核弹粉,为Burning和国土祝福
2014/07/13 DOTA
跟老齐学Python之编写类之二方法
2014/10/11 Python
python获得文件创建时间和修改时间的方法
2015/06/30 Python
在Django的视图中使用form对象的方法
2015/07/18 Python
Python Web框架Tornado运行和部署
2020/10/19 Python
python如何变换环境
2020/07/21 Python
详解CSS3媒体查询响应式布局bootstrap 框架原理实战(推荐)
2020/11/16 HTML / CSS
英国最大的运动营养公司之一:LA Muscle
2018/07/02 全球购物
意大利香水和化妆品购物网站:Parfimo.it
2019/10/06 全球购物
庆祝三八妇女节标语
2014/10/09 职场文书
加班费申请报告
2015/05/15 职场文书
2015秋季运动会通讯稿
2015/07/18 职场文书
MySQL分区路径子分区再分区
2022/04/13 MySQL