Skip to content

Commit 2e343f7

Browse files
authored
Merge pull request #2030 from didi/fix-movable-position
fix: 修改movable默认定位样式&修复同时修改容器尺寸并修改x、y不生效问题
2 parents cc216d1 + 8a201b1 commit 2e343f7

3 files changed

Lines changed: 137 additions & 24 deletions

File tree

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
<template>
2-
<div class="mpx-movable-area-container" ref="movableArea">
3-
<div class="mpx-movable-scroll-wrapper" ref="scroll">
4-
<slot></slot>
5-
</div>
2+
<div class="mpx-movable-area-container" ref="movableArea">
3+
<div class="mpx-movable-scroll-wrapper" ref="scroll">
4+
<slot></slot>
65
</div>
6+
</div>
77
</template>
88

99
<script type="text/ecmascript-6">
1010
export default {
11-
data () {
12-
return {}
11+
data() {
12+
return {
13+
isInited: false,
14+
}
1315
},
14-
mounted () {
16+
mounted() {
1517
this.computedStyle()
16-
},
17-
beforeDestroy () {
18-
18+
if (!this.closeResizeObserver) {
19+
this.createResizeObserver()
20+
}
1921
},
2022
methods: {
2123
computedStyle() {
@@ -26,17 +28,39 @@
2628
if (!style.height) {
2729
this.$refs.movableArea.style.height = '10px'
2830
}
31+
},
32+
createResizeObserver() {
33+
if (typeof ResizeObserver !== 'undefined') {
34+
this.resizeObserver = new ResizeObserver(entries => {
35+
if (!this.isInited) {
36+
this.isInited = true
37+
return
38+
}
39+
this.$children.forEach(child => {
40+
if (child && child.refresh) {
41+
child.refresh()
42+
}
43+
})
44+
})
45+
this.resizeObserver.observe(this.$refs.movableArea)
46+
}
47+
},
48+
},
49+
beforeDestroy () {
50+
if (this.resizeObserver) {
51+
this.resizeObserver.disconnect()
52+
this.resizeObserver = null
2953
}
30-
}
54+
},
3155
}
3256
</script>
3357
<style lang="stylus" rel="stylesheet/stylus" scoped>
34-
.mpx-movable-area-container
35-
position: absolute
36-
.mpx-movable-scroll-wrapper
37-
position: absolute
38-
top: 0
39-
left: 0
40-
bottom: 0
41-
right: 0
58+
.mpx-movable-area-container
59+
position: relative
60+
.mpx-movable-scroll-wrapper
61+
position: absolute
62+
top: 0
63+
left: 0
64+
bottom: 0
65+
right: 0
4266
</style>

packages/webpack-plugin/lib/runtime/components/web/mpx-movable-view.vue

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ export default {
3838
touchEvent: '',
3939
isInited: false,
4040
deactivatedX: 0,
41-
deactivatedY: 0
41+
deactivatedY: 0,
42+
// 缓存高度,用于检测变化
43+
cachedContentHeight: 0,
44+
cachedWrapperHeight: 0,
45+
// 缓存宽度,用于检测变化
46+
cachedContentWidth: 0,
47+
cachedWrapperWidth: 0
4248
}
4349
},
4450
props: {
@@ -107,7 +113,24 @@ export default {
107113
},
108114
watch: {
109115
x (newVal) {
116+
if (this.direction === 'vertical' || this.direction === 'none') {
117+
return
118+
}
110119
this.source = ''
120+
// 检查宽度是否发生变化,只有在变化时才调用 refresh
121+
const widthChanged = this.checkWidthChange()
122+
let currentX = this.bs.x
123+
124+
if (widthChanged) {
125+
// 兼容容器尺寸变化且同时改变x的场景,ResizeObserver回调是异步的,如果不直接refresh,minScrollX, maxScrollX 拿到的都是上一次的值
126+
this.refresh()
127+
// bs refresh 方法内会触发 resetPosition(),如果容器宽度从 100 - 50,y 从 100 - 50,这会导致位置立即跳转到边界内,没有动画效果,造成视觉突兀
128+
// 如果 refresh 导致了位置变化,先恢复到原位置再动画滚动
129+
if (this.bs.x !== currentX) {
130+
this.bs.scrollTo(currentX, this.bs.y, 0)
131+
}
132+
}
133+
111134
if (newVal > this.bs.minScrollX) {
112135
newVal = this.bs.minScrollX
113136
}
@@ -118,7 +141,24 @@ export default {
118141
this.bs.scrollTo(newVal, this.bs.y, this.speed)
119142
},
120143
y (newVal) {
144+
if (this.direction === 'horizontal' || this.direction === 'none') {
145+
return
146+
}
121147
this.source = ''
148+
// 检查高度是否发生变化,只有在变化时才调用 refresh
149+
const heightChanged = this.checkHeightChange()
150+
let currentY = this.bs.y
151+
152+
if (heightChanged) {
153+
// 兼容容器尺寸变化且同时改变y的场景,ResizeObserver回调是异步的,如果不直接refresh,minScrollY, maxScrollY 拿到的都是上一次的值
154+
this.refresh()
155+
// bs refresh 方法内会触发 resetPosition(),如果容器高度从 100 - 50,y 从 100 - 50,这会导致位置立即跳转到边界内,没有动画效果,造成视觉突兀
156+
// 如果 refresh 导致了位置变化,先恢复到原位置再动画滚动
157+
if (this.bs.y !== currentY) {
158+
this.bs.scrollTo(this.bs.x, currentY, 0)
159+
}
160+
}
161+
122162
if (newVal > this.bs.minScrollY) {
123163
newVal = this.bs.minScrollY
124164
}
@@ -146,6 +186,10 @@ export default {
146186
if (!this.scrollOptions.closeResizeObserver) {
147187
this.createResizeObserver()
148188
}
189+
// 初始化尺寸缓存
190+
this.$nextTick(() => {
191+
this.initSizeCache()
192+
})
149193
this.init()
150194
},
151195
activated () {
@@ -178,13 +222,50 @@ export default {
178222
}
179223
this.refresh()
180224
})
181-
const elementToObserve = document.querySelector('.mpx-movable-scroll-content')
182-
elementToObserve && this.resizeObserver.observe(elementToObserve)
225+
this.resizeObserver.observe(this.$refs.scrollContent)
183226
}
184227
},
185228
refresh () {
186229
this.bs && this.bs.refresh()
187230
},
231+
// 检查高度是否发生变化
232+
checkHeightChange () {
233+
if (!this.$refs.scrollContent || !this.$parent.$refs.movableArea) {
234+
return false
235+
}
236+
237+
const currentContentHeight = this.$refs.scrollContent.clientHeight
238+
const currentWrapperHeight = this.$parent.$refs.movableArea.clientHeight
239+
240+
const heightChanged =
241+
currentContentHeight !== this.cachedContentHeight ||
242+
currentWrapperHeight !== this.cachedWrapperHeight
243+
244+
// 更新缓存的高度
245+
this.cachedContentHeight = currentContentHeight
246+
this.cachedWrapperHeight = currentWrapperHeight
247+
248+
return heightChanged
249+
},
250+
// 检查宽度是否发生变化
251+
checkWidthChange () {
252+
if (!this.$refs.scrollContent || !this.$parent.$refs.movableArea) {
253+
return false
254+
}
255+
256+
const currentContentWidth = this.$refs.scrollContent.clientWidth
257+
const currentWrapperWidth = this.$parent.$refs.movableArea.clientWidth
258+
259+
const widthChanged =
260+
currentContentWidth !== this.cachedContentWidth ||
261+
currentWrapperWidth !== this.cachedWrapperWidth
262+
263+
// 更新缓存的宽度
264+
this.cachedContentWidth = currentContentWidth
265+
this.cachedWrapperWidth = currentWrapperWidth
266+
267+
return widthChanged
268+
},
188269
destroyBs () {
189270
if (!this.bs) return
190271
this.bs.destroy()
@@ -364,6 +445,15 @@ export default {
364445
}
365446
extend(this.bsOptions, this.scrollOptions)
366447
},
448+
// 初始化尺寸缓存
449+
initSizeCache () {
450+
if (this.$refs.scrollContent && this.$parent.$refs.movableArea) {
451+
this.cachedContentHeight = this.$refs.scrollContent.clientHeight
452+
this.cachedWrapperHeight = this.$parent.$refs.movableArea.clientHeight
453+
this.cachedContentWidth = this.$refs.scrollContent.clientWidth
454+
this.cachedWrapperWidth = this.$parent.$refs.movableArea.clientWidth
455+
}
456+
},
367457
// 处理小数点,四舍五入,默认保留一位小数
368458
roundFun (value, n = 1) {
369459
return Math.round(value * Math.pow(10, n)) / Math.pow(10, n)

packages/webpack-plugin/lib/runtime/components/web/mpx-swiper.vue

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,7 @@
256256
}
257257
this.initBs()
258258
})
259-
const elementToObserve = document.querySelector('.mpx-swiper');
260-
this.resizeObserver.observe(elementToObserve);
259+
this.resizeObserver.observe(this.$refs.wrapper);
261260
}
262261
},
263262
refresh () {

0 commit comments

Comments
 (0)