Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue封装一个简单的div框选时间的组件 #309

Open
confidence68 opened this issue Mar 10, 2019 · 0 comments
Open

vue封装一个简单的div框选时间的组件 #309

confidence68 opened this issue Mar 10, 2019 · 0 comments

Comments

@confidence68
Copy link
Owner

前言

新年第一篇文章,记录一下我前段时间封装的一个vue组件吧。技术需要积累,有时间我把我之前写的还不错的组件都开源出来。并尝试vue和react 两种方式的组件封装。今天简单写下鼠标框选div选中效果的封装吧。

div框选实现

div框选效果,其实没有什么好的方法,就是获取鼠标事件,根据鼠标的位置,动态创建一个跟随鼠标的div。【注:这种方式需要依赖position的定位方式,一般鼠标事件位置是针对全局的,所以鼠标框选的div 位置的position最好父级元素是根元素的定位。不然,鼠标框选区域和被框选区域很难保持一致。】

其实总结起来就两步:

鼠标左键按下不放,移动鼠标出现矩形选框;

鼠标左键松开,根据上边出现的矩形选框统计选框范围内的DOM元素;

创建一个跟随鼠标的div,代码如下:

 //  创建选框节点
      this.selectBoxDashed = document.createElement('div')
      this.selectBoxDashed.className = 'haorooms-select-box'

      document.body.appendChild(this.selectBoxDashed)
      this.scrollX = document.documentElement.scrollLeft || document.body.scrollLeft
      this.scrollY = document.documentElement.scrollTop || document.body.scrollTop
      //  设置选框的初始位置
      this.startX = e.x + this.scrollX || e.clientX + this.scrollX  // e是鼠标事件的event
      this.startY = e.y + this.scrollY || e.clientY + this.scrollY // e是鼠标事件的event
      this.selectBoxDashed.style.cssText = `left:${this.startX}px;top:${this.startY}px`

鼠标移动,获取被选中div列表,增加一个临时class

  this.selectBoxDashed.style.display = 'block' // 上面创建的鼠标跟随div出现
      //  根据鼠标移动,设置选框的位置、宽高
      this.initx = e.x + this.scrollX || e.clientX + this.scrollX //鼠标移动的初始位置+滚动轴的位置
      this.inity = e.y + this.scrollY || e.clientY + this.scrollY
      //  暂存选框的位置及宽高,用于将 select-item 选中
      this.left = Math.min(this.initx, this.startX) 
      this.top = Math.min(this.inity, this.startY)
      this.width = Math.abs(this.initx - this.startX)
      this.height = Math.abs(this.inity - this.startY)
      this.selectBoxDashed.style.left = `${this.left}px`
      this.selectBoxDashed.style.top = `${this.top}px`
      this.selectBoxDashed.style.width = `${this.width}px`
      this.selectBoxDashed.style.height = `${this.height}px`
      let fileDivs = document.getElementsByClassName('list') // 获取要选中的div列表
      for (let i = 0; i < fileDivs.length; i++) {
        let itemX_pos = fileDivs[i].offsetWidth + fileDivs[i].offsetLeft
        let itemY_pos = fileDivs[i].offsetHeight + fileDivs[i].offsetTop
        let condition1 = itemX_pos > this.left
        let condition2 = itemY_pos > this.top
        let condition3 = fileDivs[i].offsetLeft < (this.left + this.width)
        let condition4 = fileDivs[i].offsetTop < (this.top + this.height)
        if (condition1 && condition2 && condition3 && condition4) {// 在框选范围之内
          fileDivs[i].classList.add('temp-selected')
        } else {
          fileDivs[i].classList.remove('temp-selected')
        }
      }

鼠标抬起,增加选中class

 let selectDom = document.getElementsByClassName('temp-selected');
      [].slice.call(selectDom).forEach(item => {
        if (item.classList.contains('selected')) {
          item.classList.remove('selected')
        } else {
          item.classList.add('selected')
        }
        item.classList.remove('temp-selected')
      })
      if (this.selectBoxDashed) {
        try {
          this.selectBoxDashed.parentNode.removeChild(this.selectBoxDashed)
        } catch (err) {
          // console.log(err)
        }
      }
      let fileDivs = document.getElementsByClassName('list') // 这里是改变数据
      for (let i = 0; i < fileDivs.length; i++) {
        if (fileDivs[i].classList.contains('selected')) {
          this.timeList[i] = '1'
        } else {
          this.timeList[i] = '0'
        }
      }

效果如下如:

enter image description here

代码发布到npm

这个组件,包括我之前写的vue移动端下拉加载下一页数据的组件,都发布到了npm,

npm地址:https://www.npmjs.com/package/timedivselect

使用:

npm install timedivselect -S

import timeDivSelect from 'timedivselect'

使用例子:

https://github.com/confidence68/timeDivselect/blob/master/src/App.vue

顺便说说npm发布遇到的一个小问题吧

之前我npm也发布过一些,关于如何发布npm包,我博客之前虽然没有写,但是网上很多。

第一次用的时候一般是:

npm adduser

// 输入用户名,密码等【npm 网站要提前注册,npm网站的用户名和密码】

不是第一次

npm login

发布、删除等

npm publish // 发布

npm unpublish 包名 // 撤销删除

回到正题,我今天遇到的问题是npm: no_perms Private mode enable, only admin can publish this module

之前发布都是好好的,为啥突然这次发布会有这个错误信息呢?原来是因为我指定了npm的淘宝镜像。

目前推荐使用NRM

sudo npm install -g nrm

查看源列表

nrm ls

使用某个源

nrm use npm

这样再发布既可以了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant