vue

简单轮子:Popover 组件(上)

★开始Popover组件

◇准备工作

◇注意点

◇直接看代码理解

再次强调,可以把组件看成是函数,写在组价标签上的属性是实参(前端开发者决定传啥),组件里边的data是局部变量(组件自己维护)!

★解决新手常见的三个问题

◇注意点

◇直接看代码理解


★支持四个方位

◇注意点

◇开搞

关于popover浮层的样式(非常好看就很难做了)

下一个需求:可以选择4个方向的popover!

代码方面:了解思路就ok了,无须深入到代码细节!

★支持click和hover两种方式

◇表驱动编程

简介(来自代码大全):

表驱动法是一种编程模式,从表里面查找信息而不是使用逻辑语句(if…else…switch),当需求很简单的情况时,用逻辑语句很简单,但如果需求很复杂,再使用逻辑语句就很麻烦了。

➹:表驱动法 -《代码大全》读书笔记 - AngelDevil - 博客园

要优化的代码:

1566207216226

优化后的代码:

1566207967736

何时优化?

很多个 if……else,而且代码逻辑相似就可以用表驱动编程优化了!

这个优化技巧性价比非常高!

怎么优化?

总体上来说,就是画一个excel表格呗:

{top:{top:xxx,left:xxx},} top bottom left right
top top + window.scrollY      
left left + window.scrollX      

有种二维数组的既视感!

if……else的逻辑都差不多,只是有些细节不同!(似乎只要满足 ===啥,然后处理逻辑一样,就可以用表驱动编程了)

针对这个表格我们写个对象即可!(先把这个对象的大致结构给写出来,然后再去填充内容!)

let x = {
  top: {
    left: 'xxx',
    top: 'yyy'
  },
  bottom: {
    left: 'xxx',
    top: 'yyy'
  },
  left: {
    left: 'xxx',
    top: 'yyy'
  },
  right: {
    left: 'xxx',
    top: 'yyy'
  },
}

接着是处理 else的逻辑了。

最后我们整个代码就没有 if……else

虽然,代码行数没有变小,但是代码逻辑却变少了,因为我们咩有任何的 if……else

◇用户可以选择在hover触发,还是在click时触发

用了vue之后,其实什么逻辑就是几句话的事情!

关于destroyed这个api:

Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

该钩子在服务器端渲染期间不被调用。

所以这就是为啥我们要自己手动remove了,因为Vue不知道用户搞了事件监听,只知道 @click那些鬼东西

总之,在造轮子的时候,一定要避免内存泄漏的问题!


★总结

★Q&A

①rgba与background-color的那些事儿?

Basic Idea Green

我们可以通过改变前景色的透明度来生成更深或更浅的颜色。如上边的背景色是绿色,前景色 分别是浅绿色和深绿色!

➹:【转载】CSS技巧-rgba函数的妙用_CSS 教程_w3cplus

②关于ref?

ref:被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的$refs对象上。如果在普通的DOM元素上使用,那么指向的就是普通的DOM元素。

➹:详解vue中的ref和$refs的使用 - 掘金

③把页面里边已经渲染好的DOM移到其它位置里边去?

本来是xx的儿子,现在通过 appendChild这个API却可以成为xx的兄弟!

➹: demo

④js get element offset relative to document?

如何获取一个元素相对于整个页面的top和left(top和left就叫做offset)

简单姿势:

function getOffsetLeft( elem )
{
    var offsetLeft = 0;
    do {
      if ( !isNaN( elem.offsetLeft ) )
      {
          offsetLeft += elem.offsetLeft;
      }
    } while( elem = elem.offsetParent );
    return offsetLeft;
}

再好点的姿势:

function getCoords(elem) { // crossbrowser version
    var box = elem.getBoundingClientRect();

    var body = document.body;
    var docEl = document.documentElement;

    var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
    var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;

    var clientTop = docEl.clientTop || body.clientTop || 0;
    var clientLeft = docEl.clientLeft || body.clientLeft || 0;

    var top  = box.top +  scrollTop - clientTop;
    var left = box.left + scrollLeft - clientLeft;

    return { top: Math.round(top), left: Math.round(left) };
}

最简洁姿势:

element.getBoundingClientRect().top + document.documentElement.scrollTop

芳芳就是用了最简洁姿势,只不过是用了 window.scrollY,不过,这个兼容性可没有那么好呀!

➹:javascript - Finding element’s position relative to the document - Stack Overflow

⑤父元素是absolute,子元素也是absolute,那么子元素是相对于父元素绝对定位吗?

只要父级元素设了position并且不是static(默认既是static),那么设定了absolute的子元素即以此为包含块(最近的)。 绝对定位(Absolute positioning)元素定位的参照物是其包含块,既相对于其包含块进行定位,不一定是其父元素。

➹:父元素position:absolute/relative的区别 - zcy_csdn123的博客 - CSDN博客

➹:CSS 中,为什么绝对定位(absolute)的父级元素必须是相对定位(relative)? - 知乎

⑥话说,这样的浮层样式该怎么实现?

1566117329850

  1. 先完成没有三角形的样式
<div class="popover">我是浮层呀!</div>
.popover {
  margin: 100px 200px ;
  position: absolute;
  border: 1px solid #333;
  border-radius: 4px;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .5));
  background-color: white;
  padding: .5em 1em;
  max-width: 20em;
  word-break: break-all;
}
  1. 搞个三角形,这是用before这个伪元素来搞
  2. 再搞个三角形,这是用after来搞,不然你用before的话显然是样式叠加了,而这个三角形的位置同第一个三角形的位置一样,只是它的top上移 了1px。

1566184962335

➹: demo