文本对比工具

149 阅读2分钟

稀土掘金的文章编辑区是一个典型的文本对比工具。左侧支持md/html等格式文本,右侧将其渲染出来。

在向下滑动时,会有一个滚动条,但两侧的滚动速度不一致。停下滚动时,左右两侧的语义保持一致。

本文实现的是:左右两侧文本长度不一致时,外侧滚动条作为公共滚动,长文本有小滚动条进行微调。

非常简陋的代码示意如下:

 <div style = "display: flex; overflow:auto; height: 200px">
        <div id="id3" style="width: 22px;overflow:auto;">
            <div id="id1">
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
                11
            </div>
        </div>
        <div id="id4" style="width: 22px; overflow:auto;">
            <div id="id2">
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                22
                2
                22
            </div>
        </div>
    </div>
    <script>
        const id1 = document.getElementById('id1')
        const id2 = document.getElementById('id2')
        const id3 = document.getElementById('id3')
        const id4 = document.getElementById('id4')
        const height1 = window.getComputedStyle(id1).height
        id3.style.height = Number(height1.split('px')[0]) + 'px'
        id4.style.height = Number(height1.split('px')[0]) + 'px'
    </script>

思路:

只有当父元素的高度小于子元素的时候,父元素设置 overflow: auto;才会产生滚动条;

因此,左右两侧文本id1,id2自动撑开高度,id3,id4的高度为min(id1,id2)。这样大的文本会产生一个内部小的滚动条微调;同时,整个大盒子的高度若小于min(id1,id2),会产生大的滚动条,左右两侧一起滚动。

问题:

无法获取根元素

由于是在一个非常老旧的纯js系统引入vue写的,template定义非常混乱,没有办法直接通过document.querySelector,给根元素加ref获取, 再querySelector:

console.log(this.$refs.dialog.$el)
const left = this.$refs.dialog.$el.querySelector('.left')
console.log(left)

nextTick等待渲染 上述打印发现,this.refs.dialog.refs.dialog.el能打印完整的dom结构,但是left为null 这是因为打印是一个引用,而不是一个快照,此时此刻,子元素还没有渲染完成 因此:

this.$nextTick(() => {
  const left = this.$refs.dialog.$el.querySelector('.left'
  const height = Math.min(Number(window.getComputedStyle(left).height.split('px')[0]), Number(window.getComputedStyle(right).height.split('px')[0]))
  scroll_area.forEach(i => i.style.height = height + 'px')
}