用 `resize` 和 MutationObserver 实现缩放 DOM 并记录尺寸

我厂既然号称“机器编程”,DSL 便属于基础配置。于是,各个产品几乎都需要用到 CodeMirror,用于在线写代码。大家的屏幕分辨率不同,对编辑器的大小要求也不同,最简单的办法就是让大家自己调整,并且将尺寸保存在本地。

以前的做法会复杂一些:

  1. 拿一个元素作为 handle 放在角落里
  2. mousedown 时开始侦听 mousemove,动态调整文本框大小
  3. mouseup 时保存尺寸

如今大家应该都有注意到,<textarea> 右下角多了一个缩放用的 handle。这个功能自然不是 <textarea> 独享,而是受 CSS 样式 resize 控制,任何块级元素都适用。MDN 文档在此,建议大家先好好看一遍。

基于一般的网格化设计,包括响应式的需求,编辑器的宽度是固定的,用户控制的只有高度,所以我们只需要设置 resize: vertical,让它接受垂直方面的缩放就可以了。

接下来该侦听缩放事件。可惜,resize 事件只有 window 可以触发(MDN 文档),所以直接在元素上侦听是不可能的了。好在我们有 MutationObserver,而 Resize Observer 也刚刚从草案变成现实,所以曲线一下就能满足这个需求。

onEditorResize([{target}]) {
  const height = target.clientHeight;
  if (height < 160) {
    return;
  }
  localStorage.setItem(EDITOR_HEIGHT, height);
},

mounted() {
  const onResize = debounce(this.onEditorResize, 1000);
  const observer = this.observer = new MutationObserver(onResize);
  observer.observe(element, {
    attributes: true,
  });
},

beforeDestroy() {
  if (this.observer) {
    this.observer.disconnect();
    this.observer = null;
  }
}

这里有几个 tips:

  1. 我用 Vue,所以用到一些生命周期的钩子
  2. 缩放动作会触发多次事件,所以最好用 debounce 降低执行频率
  3. 编辑器需要设置一个最小高度,不然可能不小心存一个 0px ,用户就看不到编辑器了
  4. 关于参数及含义,大家好好看文档吧。

如果您觉得文章内容对您有用,不妨支持我创作更多有价值的分享:


已发布

分类

来自

评论

《“用 `resize` 和 MutationObserver 实现缩放 DOM 并记录尺寸”》 有 1 条评论

  1. […] 看过我《用 resize 和 MutationObserver 实现缩放 DOM 并记录尺寸》的同学,应该知道 resize 这个 CSS 属性,使用它可以很方便的给元素添加缩放功能。参考 caniuse 上面的普及度,大部分新版本的浏览器都已经支持,可以放心使用。 […]

欢迎吐槽,共同进步

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据