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

ResizeObserver是什么? #166

Open
FrankKai opened this issue Oct 23, 2019 · 3 comments
Open

ResizeObserver是什么? #166

FrankKai opened this issue Oct 23, 2019 · 3 comments

Comments

@FrankKai
Copy link
Owner

新来的产品经理,想做一个和qq或者微信聊天一样的,上下拖动动态改变文本内容框和编辑器布局的需求。
其实一开始是一头雾水的,但是通过万能的mdn,以及充满智慧的我,最终还是完成了这个需求。
其中最核心的还是ResizeObserver这个第一次用的类,所以会在这里做一些记录。

  • ResizeObserver初识
  • ResizeObserver实战
@FrankKai
Copy link
Owner Author

ResizeObserver初识

  • ResizeObserver interface可以报告元素content或者border box,或者svg元素box大小的变化
  • ResizeObserver.disconnect() 取消观察某个observer的所有observed目标元素。
  • ResizeObserver.observe() 初始化观察一个指定元素。
  • ResizeObserver.observe() 取消观察一个指定元素。
  • new ResizeObserver(callback) callback的入参包括entries和observer。

entries是一个数组,它由所有的ResizeObserverEntry object组成。通过for (let entry of entries) {}的方式,entry代表一个ResizeObserver object,一个entry由contentRect和target组成。

在resize相关实践中,entry的contentRect对象是最最重要的。

{target: div, contentRect: DOMRectReadOnly}
contentRect: DOMRectReadOnly
bottom: 312.3125
height: 292.3125
left: 20
right: 626
top: 20
width: 606
x: 20
y: 20
__proto__: DOMRectReadOnly
target: div
__proto__: ResizeObserverEntry

@FrankKai
Copy link
Owner Author

FrankKai commented Oct 23, 2019

ResizeObserver实战

Make element resizable

  • 元素应用resize css属性。
  • 元素ResizeObserver化。
<div class="main" :style="{minHeight: dynamicMainHeight}">
      <chatView></chatView>
</div>
.main {
    resize: vertical;
    overflow: auto;
}
 observeChatView() {
    if (window.ResizeObserver) {
      const viewElem = document.querySelector('.main');
      const resizeObserver = new ResizeObserver((entries) => {
        for (const entry of entries) {
          if (!this.initialHeight) {
            this.initialHeight = entry.contentRect.height;
          }
          if (this.initialHeight) {
            const deltaHeight = this.initialHeight - entry.contentRect.height;
            this.$bus.$emit('rerenderViewAndEditor', deltaHeight);
          }
        }
      });
      resizeObserver.observe(viewElem);
    } else {
      this.$Message.warning('不支持ResizeObserver');
    }
  },
},

动态计算的editor组件

<div
  class="rich-text-editor"
  contenteditable
  data-placeholder="按下Enter发送消息,按下Shift+Enter换行"
  :style="{height: dynamicHeight}"
></div>
computed: {
  dynamicHeight() {
    return `${defaultEditorHeight + this.deltaHeight}px`;
  },
},
this.$bus.$on('rerenderViewAndEditor', (deltaHeight) => {
    this.deltaHeight = deltaHeight;
});

动态计算的view组件

自动跳到最新一条消息的chatView组件需要减去deltaHeight,从而增大scrollHeight的高度。

this.$bus.$on('rerenderViewAndEditor', (deltaHeight) => {
  this.visiableHeight = document.body.clientHeight - deltaHeight;
  this.deltaHeight = deltaHeight;
});

scrollToBottom() {
  this.$nextTick(() => {
    this.scrollTop = this.scrollHeight - this.deltaHeight;
  });
},

最终效果

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

No branches or pull requests

1 participant