在我们使用 San 开发的时候,我们常常会写各种的组件,当一个父组件的子组件是绝对定位组件(比如:Select、Tip 等)的时候,我们会遇到两种场景:

  • 场景一:父(祖)组件足够大或不存在 overflow: hidden;
  • 场景二:父(祖)组件不够大且存在 overflow: hidden;

而这两种情形下,我们需要对绝对定位组件的 DOM 做一些处理。

那针对这两种场景我们分别可以如何处理呢?

如何处理

场景一

父(祖)组件足够大或不存在 overflow: hidden; 时的绝对定位。

这种情况比较常规,我们可以直接引入组件,然后可选择在外部或组件内部包含一个 (not static) 元素,来控制显示即可。

使用
  1. class AbsComponent extends san.Component {
  2. static template = `
  3. <div>
  4. <p class="absolute">子绝对定位组件</p>
  5. </div>
  6. `;
  7. }
  8. class Parent extends san.Component {
  9. static template = `
  10. <div>
  11. <div class="parent-rel">
  12. <h3>父是static</h3>
  13. <abs-comp></abs-comp>
  14. </div>
  15. </div>
  16. `;
  17. static components = {
  18. 'abs-comp': AbsComponent
  19. };
  20. }
  21. new Parent().attach(document.querySelector('#paIsRel'));
示例

See the Pen
position-absolute-dom
by dengxiaohong (@The-only)
on CodePen.

场景二

父(祖)组件不够大且存在 overflow: hidden; 时的绝对定位。

这种情况会很常见,如果直接包含的话绝对定位元素会因为父(祖)组件有overflow: hidden;且不够大而导致组件中超出部分被遮住。

若不想被遮住的话,我们可以在组件中做一层处理:

  • 将组件元素挂到 body 上
  • 需要显示的时候进行位置控制
  • 父组件调用
使用
  1. class AbsComponent extends san.Component {
  2. static template = `
  3. <div class="abs-wrap">
  4. <div class="abs" style="{{mainStyle}}">
  5. show content
  6. </div>
  7. </div>
  8. `;
  9. initData() {
  10. return {
  11. targetElem: document.body,
  12. mainStyle: ''
  13. };
  14. }
  15. attached() {
  16. // 将绝对定位元素放在body上
  17. if (this.el.parentNode !== document.body) {
  18. document.body.appendChild(this.el);
  19. }
  20. // 显示的时候进行位置控制
  21. this.changePosition();
  22. }
  23. /**
  24. * 调整位置信息
  25. */
  26. changePosition() {
  27. // 这里可以替换成封装的组件来进行位置控制
  28. let targetElem = this.data.get('targetElem');
  29. targetElem = typeof targetElem === 'function' ? targetElem() : targetElem;
  30. let rect = targetElem.getBoundingClientRect();
  31. let left = rect.left;
  32. let top = document.body.scrollTop + rect.top + rect.height;
  33. let str = 'left:' + left + 'px;top:' + top + 'px;';
  34. this.data.set('mainStyle', str);
  35. }
  36. }
  37. class Parent extends san.Component {
  38. static template = `
  39. <div>
  40. <p class="info">父元素100px overflow:hidden;</p>
  41. <div class="parent-wrap">
  42. <span class="btn">click toggle</span>
  43. <abs-comp targetElem="{{getTarget}}"></abs-comp>
  44. </div>
  45. </div>
  46. `;
  47. static components = {
  48. 'abs-comp': AbsComponent
  49. };
  50. initData() {
  51. return {
  52. getTarget: this.getTarget.bind(this)
  53. };
  54. }
  55. /**
  56. * 获取相对定位的元素
  57. *
  58. * @return {HTMLElemnt} 相对定位的元素
  59. */
  60. getTarget() {
  61. return this.el.querySelector('.btn');
  62. }
  63. }
  64. new Parent().attach(document.querySelector('#instance'));
示例

See the Pen
position-absolute-dom
by dengxiaohong (@The-only)
on CodePen.