最近接到了一家公司的面试题是关于单元格拖动的,下面是题目要求:
1、拖拽“行头”时,其后的整个一行也随之移动原位置以空白显示;当放到其他行头上时交换内容。
2、拖拽“列头”时,其下的整个一列也随之移动原位置以空白显示;当放到其他列头上时交换内容。
3、拖拽“格子”时,只有其自身移动且也只能交换其他格子中的内容;不能交换“行头”或“列头”单元格中的内容。
4、要用面向对象的方法来处理。
拿到这道题想了好久,想用“命令模式”来做。但我的水平有限,总是没有想出好的办法;最后还是用类似于组合模式的方法写了出来,但总觉得还有些地方不够完善。感觉好像还能再做一下改进,今天把这个题目发出来也希望可以看看大家有没有什么更好的办法来解决。
先不从这个题目的实用上来说,单说它所涉及到的知识点就挺多的。先来看看它都有哪些知识点:
1、拖拽
“拖拽”是写JS中经常会用到的一个效果。做法很多,但要做到细腻就不太容易了。需要考虑在拖拽时,拖拽层的位置以及如何可以使其更好的移动;在拖拽过程中页面中的其他元素不能被选中;在快速拖拽时不能失去拖拽目标;解除拖拽时,可以不会粘连。
(1)、在拖拽时,其他内容不被选中可以用到selection办法解决。
(!-[1,]) ? document.selection.empty() : window.getSelection().removeAllRanges();
(2)、在计算拖拽层位置时,以前我使用setCapture()和releaseCapture()。但我觉得这个在有些时候不是那么听话总会出现一些问题,在快速移动时还容易丢掉目标;搞的我很纠结!通过看一些大牛们的博客学习到了不少好的东西。
以后再做拖拽时可以用如下的思路来解决:
A、先计算出当前鼠标距被拖拽元素的距离
计算方法:
a:计算鼠标的clientX和clientY
b:计算被拖拽元素的offsetLeft和offsetTop
c:当前鼠标距被拖拽元素的距离 = a - b
B、再每次拖拽移动时,用鼠标相对于页面的距离 - 当前鼠标距被拖拽元素的距离 = 当前元素要移动的距离。而且也在解决了在快速移动时丢掉目标的问题。
2、计算当前是哪个元素被拖拽层所覆盖
我试过用mouseover。我总是一厢情愿地认为mouseover是万能的,只要鼠标放到它的上面就可以被他捕获到;但是我错了,它也有不行的时候。在这道题目中,当被拖拽元素置于某个页面元素上时,用mouseover是无法捕获其事件的。因为在它上面的不是鼠标而是一个拖拽层。所以只能通过来计算拖拽层与页面其他元素的位置来判断其相对位置关系了。是麻烦了点儿但为了能实现这个功能就忍了!(大家如果还有其他更好的办法,望不吝赐教!)
当拖拽元素在某个页面元素的位置区间时,那就返回当前页面元素。说明此时拖拽层位于它之上。这样可以取到被覆盖元素与当前拖拽元素进行内容的置换。
3、JS面向对象的编写
没办法题目要求必须用这种办法来解决。其实解决这个问题的方法有很多种,不一定非要用面向对象的方法来处理,条条大路通罗马嘛!出题的人无非就是想看一下对方是否对JS面向对象编程有所了解,对其掌握的如何;是否可以灵活运用。
面向对象的编写说起来有些繁琐,在这里一句两句也说不清楚。面向对象编程可以把要编写的内容想像是一个人,这个人有一些功能和属性,比如:性别、头发的颜色,眼睛的大小等等这些都可以归为属性的行列,在定义时可以将这些属性用this关键词定义到函数体中而这个人所具备的功能可能包括:说话的语言是英语还是法语,走路的速度,双手的力量等等,这些都可以用prototype的方法来定义成其相应的功能。更具体的内容留到以后有机会再一点一点的慢慢说。
在用IE6测试用prototype编写代码时出现了一个变态的现象。这个现象就和在做HTML时写注释在IE6下出现多余文字回行的情况很相似,在JS中提出”return statement outside of function”出错信息。查看代码没问题,没有什么地方出现了return写到函数体外面的情况但就是总报这个错误;经过多方查找终于找出了错误的原因: 是因为JS注释所造成的错误。只要将提示那行的注释删除此错误信息也就消失了,我真佩服当初写IE6的这帮大哥们是怎么想的?!
下面是针对这个题目我做的效果,虽然功能都已经达到了但还是感觉有些地方不太稳妥。因为文件比较多我就附上【下载地址】了,希望大家能有其他更好的解决办法。