悬浮菜单导航带校验

悬浮菜单导航带校验

  • 提高用户体验感
    • 增加悬浮菜单导航
    • 依赖库
    • 需求
    • 实现
      • 第一步 拖拽功能
        • HTML部分
        • JS 部分
      • 模块导航
        • JS部分
      • 模块必填校验
        • JS部分
      • 滚动锚点定位
        • JS 部分
      • 提交提醒未填项
      • 案例
        • HTML部分
        • JS部分
      • 最后附上 源码地址 欢迎交流

提高用户体验感

当我们项目中遇到比较复杂的表单提交时,业务模块超过一屏显示的时候,又需要一次性提交保存,我们该如何提高用户的体验呢?

增加悬浮菜单导航

让用户实时可以看到未填写项、需要填写的模块、已经填写完成的模块,这样可以减少用户焦虑,以提高功能的实用性

依赖库

1、vue 2
2、element-ui

需求

1、可拖拽
2、模块导航
3、模块必填校验
4、滚动锚点定位
5、提交提醒未填项

实现

第一步 拖拽功能

JS提供了拖拽事件,我们可以用此功能来实现拖拽。其中什么元素或者是哪里发生了拖拽事件是最关键的。有些事件是在被拖动的元素上触发,有些事件是在放置目标上触发的。拖动某元素时候,触发的事件有:dragstart事件、drag事件和dragend事件。

HTML部分

需要拖拽的元素增加dragstart 、dragend 事件,用来获取拖拽开始 和 结束的坐标点

JS 部分
 		// 拖拽
      dragstart(e) {
        this.distX = e.clientX
        this.distY = e.clientY
      },
      dragend(e) {
        const left = this.distX - e.clientX
        const top = e.clientY - this.distY
        this.offsetRight += left
        this.offsetTop += top
      },

保存开始拖拽的X\Y坐标点 和 结束的坐标点来完成容器的拖拽偏移

模块导航

模块导航是根据菜单点击滚动到指定位置和滚动到指定位置时,导航选中到指定菜单项

JS部分
  props: {
      formRules: {
        type: Object
      },
      value: {
        require: true
      }
    }

组件传递各模块id、name 、 必填项教研

Object.keys(this.formRules).forEach((item, index) => {
          this.$set(this.formRules[item], 'requiredAll', false)
          const itemEvent = document.querySelector('#' + item)

          console.log(itemEvent)
          if (itemEvent) {
            this.itemEvents.push({
              height: itemEvent.offsetHeight,
              offsetTop: itemEvent.offsetTop
            })
          }
        })

保存各模块的高度和顶部的距离

模块必填校验

模块必填校验,通过组件传递的字段,分别进行判断,如果有required 必填标识,即进行校验

JS部分
// 校验
      requiredAllHandle() {
        Object.keys(this.formRules).forEach((item) => {
          let list = this.formRules[item]
          let isRequired = true
          Object.keys(list.rules || {}).forEach((itemc) => {
            if (this.computedIsRequired(list.rules[itemc])) {
              if (isNull(this.value[itemc])) {
                isRequired = false
              }
            }
          })
          this.$set(list, 'requiredAll', isRequired)
        })
      },
       computedIsRequired(rules) {
        let isRequired = false
        if (!Array.isArray(rules)) {
          rules = [rules]
        }
        if (rules && rules.length) {
          rules.every(function (rule) {
            if (rule.required) {
              isRequired = true
              return false
            }
            return true
          })
        }
        return isRequired
      },

computedIsRequired 方法用于监听每个字段的值变化

滚动锚点定位

滚动锚点定位通过监听 scroll 事件,获取滚动距离计算当前滚动到指定模块,标记指定模块

JS 部分
 window.addEventListener('scroll', this.handleScroll)
handleScroll() {
        const top = document.body.scrollTop || document.documentElement.scrollTop
        const { itemEvents } = this
        const lastIndex = itemEvents.length - 1
        const lastItem = itemEvents[lastIndex]
        const lastCount = lastItem.offsetTop + lastItem.height
        if (this.activeIndex >= 0) {
          if (lastCount < top) {
            return (this.activeIndex = lastIndex)
          }
          const firstScroll = itemEvents[0].offsetTop
          const itemScroll = itemEvents[this.activeIndex]
          const next = itemScroll.offsetTop + itemScroll.height
          const prev = this.activeIndex > 0 ? itemEvents[this.activeIndex - 1].offsetTop : 0
          if (next < top) {
            this.activeIndex += 1
          } else if (prev >= top) {
            this.activeIndex -= 1
            return
          }
          if (top < firstScroll - 200) {
            this.activeIndex = -1
          }
        } else {
          let firstScroll = itemEvents[0].offsetTop
          if (top >= firstScroll) {
            this.activeIndex = 0
          }
        }
      },

提交提醒未填项

当提交表单时,校验所有字段是否必填,标记未完成校验模块
悬浮菜单导航带校验_第1张图片

  // 校验
      submit() {
        this.isSubmit = true
      },

this.$refs.FloatBar.submit()

通过ref 调用子组件submit 方法

完成大体功能之后,完善并优化各功能之间联动。

有时候模块比较多的情况下会遮挡页面
悬浮菜单导航带校验_第2张图片
随即我们加了一个收缩功能
悬浮菜单导航带校验_第3张图片

到这里该组件就封装完成了。
下面附带案例查看

案例

HTML部分
 
- 立即创建 重置
- 立即创建 重置
- 立即创建 重置
- 立即创建 重置
提交
JS部分
formRules: {
        formRules1: {
          name: '测试1',
          rules: {
            name: [
              { required: true, message: '请输入活动名称', trigger: 'blur' },
              { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
            ],
          }
        },
        formRules2: {
          name: '测试2',
          rules: {
            name: [
              { required: true, message: '请输入活动名称', trigger: 'blur' },
              { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
            ],
            region: [
              { required: true, message: '请选择活动区域', trigger: 'change' }
            ],
            date1: [
              { type: 'date', required: true, message: '请选择日期', trigger: 'change' }
            ],
            date2: [
              { type: 'date', required: true, message: '请选择时间', trigger: 'change' }
            ],
            type: [
              { type: 'array', required: true, message: '请至少选择一个活动性质', trigger: 'change' }
            ],
            resource: [
              { required: true, message: '请选择活动资源', trigger: 'change' }
            ],
            desc: [
              { required: true, message: '请填写活动形式', trigger: 'blur' }
            ]
          }
        },
        formRules3: {
          name: '测试3',
          rules: {
            name: [
              { required: true, message: '请输入活动名称', trigger: 'blur' },
              { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
            ],
            region: [
              { required: true, message: '请选择活动区域', trigger: 'change' }
            ],
            date1: [
              { type: 'date', required: true, message: '请选择日期', trigger: 'change' }
            ],
            date2: [
              { type: 'date', required: true, message: '请选择时间', trigger: 'change' }
            ],
            type: [
              { type: 'array', required: true, message: '请至少选择一个活动性质', trigger: 'change' }
            ],
            resource: [
              { required: true, message: '请选择活动资源', trigger: 'change' }
            ],
            desc: [
              { required: true, message: '请填写活动形式', trigger: 'blur' }
            ]
          }
        },
        formRules4: {
          name: '测试4',
          rules: {
            name: [
              { required: true, message: '请输入活动名称', trigger: 'blur' },
              { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
            ],
            region: [
              { required: true, message: '请选择活动区域', trigger: 'change' }
            ],
            date1: [
              { type: 'date', required: true, message: '请选择日期', trigger: 'change' }
            ],
            date2: [
              { type: 'date', required: true, message: '请选择时间', trigger: 'change' }
            ],
            type: [
              { type: 'array', required: true, message: '请至少选择一个活动性质', trigger: 'change' }
            ],
            resource: [
              { required: true, message: '请选择活动资源', trigger: 'change' }
            ],
            desc: [
              { required: true, message: '请填写活动形式', trigger: 'blur' }
            ]
          }
        }
      },
      ruleForm: {
        name: '',
        region: '',
        date1: '',
        date2: '',
        delivery: false,
        type: [],
        resource: '',
        desc: ''
      },
submitForm10(){
      this.$refs.FloatBar.submit()
    },

最后附上 源码地址 欢迎交流

码云地址

你可能感兴趣的:(html,web,pc,javascript,前端,html)