小程序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 相关文章推荐
js获取单选按钮的数据
Nov 27 Javascript
Javascript 倒计时源代码.(时.分.秒) 详细注释版
May 09 Javascript
这段js代码得节约你多少时间
Dec 20 Javascript
Ext中下拉列表ComboBox组件store数据格式用法介绍
Jul 15 Javascript
设置checkbox为只读(readOnly)的两种方式
Oct 11 Javascript
javascript事件委托的方式绑定详解
Jun 10 Javascript
如何用angularjs制作一个完整的表格
Jan 21 Javascript
详解JavaScript表单验证(E-mail 验证)
Mar 31 Javascript
Vue.js每天必学之计算属性computed与$watch
Sep 05 Javascript
JavaScript实现图片轮播特效
Oct 23 Javascript
bootstrap实现tab选项卡切换
Aug 09 Javascript
vue elementUI批量上传文件
Apr 26 Vue.js
在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调用Java对象的方法
2006/10/09 PHP
PHP CURL模拟GET及POST函数代码
2010/04/25 PHP
PHP扩展开发入门教程
2015/02/26 PHP
分享微信扫码支付开发遇到问题及解决方案-附Ecshop微信支付插件
2015/08/23 PHP
YII CLinkPager分页类扩展增加显示共多少页
2016/01/29 PHP
Zend Framework分页类用法详解
2016/03/22 PHP
PHP中上传文件打印错误错误类型分析
2019/04/14 PHP
php实现session共享的实例方法
2019/09/19 PHP
两个Javascript小tip资料
2010/11/23 Javascript
jquery中dom操作和事件的实例学习 下拉框应用
2011/12/01 Javascript
jQuery插件开发精品教程让你的jQuery提升一个台阶
2016/01/27 Javascript
JavaScript中数组去除重复的三种方法
2016/04/22 Javascript
AngularJS入门教程之Scope(作用域)
2016/07/27 Javascript
JS简单实现tab切换效果的多窗口显示功能
2016/09/07 Javascript
KnockoutJS 3.X API 第四章之事件event绑定
2016/10/10 Javascript
详解利用exif.js解决ios手机上传竖拍照片旋转90度问题
2016/11/04 Javascript
原生JS实现的多个彩色小球跟随鼠标移动动画效果示例
2018/02/01 Javascript
webpack@v4升级踩坑(小结)
2018/10/08 Javascript
详解微信小程序与内嵌网页交互实现支付功能
2018/10/22 Javascript
jQuery实现购物车的总价计算和总价传值功能
2018/11/28 jQuery
深入理解nodejs搭建静态服务器(实现命令行)
2019/02/05 NodeJs
nodejs使用node-xlsx生成excel的方法示例
2019/08/22 NodeJs
利用layer实现表单完美验证的方法
2019/09/26 Javascript
浅谈python可视化包Bokeh
2018/02/07 Python
浅谈python中requests模块导入的问题
2018/05/18 Python
对python 合并 累加两个dict的实例详解
2019/01/21 Python
使用Python进行体育竞技分析(预测球队成绩)
2019/05/16 Python
python爬虫实现爬取同一个网站的多页数据的实例讲解
2021/01/18 Python
Python Pygame实现俄罗斯方块
2021/02/19 Python
将HTML5 Canvas的内容保存为图片借助toDataURL实现
2013/05/20 HTML / CSS
触摸春天教学反思
2014/02/03 职场文书
商场租赁意向书
2014/07/30 职场文书
毕业生银行实习自我鉴定
2014/10/14 职场文书
z-index不起作用
2021/03/31 HTML / CSS
PHP策略模式写法
2021/04/01 PHP
vue-element-admin项目导入和导出的实现
2021/05/21 Vue.js