@mpxjs/webpack-plugin 2.8.40-beta.0 → 2.8.40-test.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/lib/dependencies/CommonJsExtractDependency.js +51 -0
  2. package/lib/dependencies/DynamicEntryDependency.js +10 -16
  3. package/lib/dependencies/ResolveDependency.js +11 -20
  4. package/lib/extractor.js +1 -0
  5. package/lib/helpers.js +9 -1
  6. package/lib/index.js +239 -134
  7. package/lib/json-compiler/helper.js +27 -17
  8. package/lib/json-compiler/index.js +82 -31
  9. package/lib/loader.js +31 -37
  10. package/lib/native-loader.js +21 -14
  11. package/lib/parser.js +0 -1
  12. package/lib/platform/index.js +15 -4
  13. package/lib/platform/json/wx/index.js +63 -2
  14. package/lib/platform/run-rules.js +1 -1
  15. package/lib/platform/template/normalize-component-rules.js +42 -41
  16. package/lib/platform/template/wx/component-config/README.md +1 -1
  17. package/lib/platform/template/wx/component-config/component.js +1 -2
  18. package/lib/platform/template/wx/component-config/fix-component-name.js +21 -0
  19. package/lib/platform/template/wx/component-config/hypen-tag-name.js +2 -6
  20. package/lib/platform/template/wx/component-config/index.js +6 -4
  21. package/lib/platform/template/wx/component-config/view.js +0 -11
  22. package/lib/platform/template/wx/index.js +84 -32
  23. package/lib/runtime/base.styl +9 -6
  24. package/lib/runtime/components/web/filterTag.js +9 -30
  25. package/lib/runtime/components/web/getInnerListeners.js +3 -16
  26. package/lib/runtime/components/web/mpx-image.vue +13 -10
  27. package/lib/runtime/components/web/mpx-keep-alive.vue +10 -17
  28. package/lib/runtime/components/web/mpx-movable-view.vue +105 -23
  29. package/lib/runtime/components/web/mpx-picker-view-column.vue +10 -2
  30. package/lib/runtime/components/web/mpx-picker-view.vue +1 -1
  31. package/lib/runtime/components/web/mpx-picker.vue +9 -1
  32. package/lib/runtime/components/web/mpx-scroll-view.vue +69 -23
  33. package/lib/runtime/components/web/mpx-swiper.vue +152 -62
  34. package/lib/runtime/components/web/mpx-video.vue +123 -89
  35. package/lib/runtime/components/web/mpx-web-view.vue +120 -81
  36. package/lib/runtime/components/web/promisify.js +19 -0
  37. package/lib/runtime/components/wx/default-page.mpx +27 -0
  38. package/lib/runtime/optionProcessor.js +321 -270
  39. package/lib/runtime/stringify.wxs +44 -8
  40. package/lib/style-compiler/index.js +6 -3
  41. package/lib/template-compiler/bind-this.js +280 -49
  42. package/lib/template-compiler/compiler.js +122 -108
  43. package/lib/template-compiler/index.js +35 -23
  44. package/lib/utils/check-core-version-match.js +18 -14
  45. package/lib/utils/dom-tag-config.js +115 -0
  46. package/lib/utils/make-map.js +12 -0
  47. package/lib/utils/string.js +7 -1
  48. package/lib/utils/ts-loader-watch-run-loader-filter.js +4 -5
  49. package/lib/web/processJSON.js +39 -3
  50. package/lib/web/processMainScript.js +84 -0
  51. package/lib/web/processScript.js +21 -201
  52. package/lib/web/processTemplate.js +11 -35
  53. package/lib/web/script-helper.js +202 -0
  54. package/package.json +7 -6
  55. package/lib/json-compiler/default-page.mpx +0 -3
  56. package/lib/style-compiler/plugins/trim.js +0 -15
  57. package/lib/template-compiler/preprocessor.js +0 -29
  58. package/lib/wxss/compile-exports.js +0 -52
  59. package/lib/wxss/createResolver.js +0 -36
  60. package/lib/wxss/css-base.js +0 -79
  61. package/lib/wxss/getLocalIdent.js +0 -25
  62. package/lib/wxss/localsLoader.js +0 -44
  63. package/lib/wxss/processCss.js +0 -274
@@ -1,8 +1,6 @@
1
1
  import { isEmptyObject } from '../../utils'
2
2
  import { isBrowser } from '../../env'
3
3
 
4
- const isTouchDevice = isBrowser ? document && ('ontouchstart' in document.documentElement) : true
5
-
6
4
  function processModel (listeners, context) {
7
5
  // 该函数只有wx:model的情况下才调用,而且默认e.detail.value有值
8
6
  // 该函数必须在产生merge前执行
@@ -49,6 +47,7 @@ function mergeListeners (listeners, otherListeners, options = {}) {
49
47
  function processTap (listeners, context) {
50
48
  const listenerMap = {}
51
49
  const tapEvents = ['tap', 'longpress', 'longtap']
50
+ const isTouchDevice = isBrowser ? document && ('ontouchstart' in document.documentElement) : true
52
51
  tapEvents.forEach((eventName) => {
53
52
  if (listeners[eventName]) {
54
53
  listenerMap[eventName] = true
@@ -144,20 +143,8 @@ export function inheritEvent (type, oe, detail = {}) {
144
143
  }
145
144
 
146
145
  export function getCustomEvent (type, detail = {}, target = null) {
147
- const targetInfo = {}
148
- if (target) {
149
- const targetEl = target.$el || {}
150
- const info = {
151
- id: targetEl.id || '',
152
- dataset: targetEl.dataset || {},
153
- offsetTop: targetEl.offsetTop || 0,
154
- offsetLeft: targetEl.offsetLeft || 0
155
- }
156
- Object.assign(targetInfo, {
157
- target: info,
158
- currentTarget: info
159
- })
160
- }
146
+ const targetEl = (target && target.$el) || null
147
+ const targetInfo = targetEl ? { target: targetEl, currentTarget: targetEl } : {}
161
148
  return {
162
149
  type,
163
150
  detail,
@@ -1,5 +1,6 @@
1
1
  <script>
2
2
  import getInnerListeners, { getCustomEvent } from './getInnerListeners'
3
+ import { isBrowser } from '../../env'
3
4
 
4
5
  export default {
5
6
  name: 'mpx-image',
@@ -21,21 +22,23 @@
21
22
  }
22
23
  },
23
24
  beforeCreate () {
24
- this.image = new Image()
25
- this.image.onload = () => {
26
- this.$emit('load', getCustomEvent('load', {
27
- width: this.image.width,
28
- height: this.image.height
29
- }, this))
30
- }
31
- this.image.onerror = () => {
32
- this.$emit('error', getCustomEvent('error', {}, this))
25
+ if (isBrowser) {
26
+ this.image = new Image()
27
+ this.image.onload = () => {
28
+ this.$emit('load', getCustomEvent('load', {
29
+ width: this.image.width,
30
+ height: this.image.height
31
+ }, this))
32
+ }
33
+ this.image.onerror = () => {
34
+ this.$emit('error', getCustomEvent('error', {}, this))
35
+ }
33
36
  }
34
37
  },
35
38
  watch: {
36
39
  src: {
37
40
  handler (src) {
38
- if (src) this.image.src = src
41
+ if (src && this.image) this.image.src = src
39
42
  },
40
43
  immediate: true
41
44
  }
@@ -30,9 +30,7 @@
30
30
  }
31
31
 
32
32
  function getVnodeKey (vnode) {
33
- if (vnode && vnode.componentOptions) {
34
- return vnode.componentOptions.Ctor.cid + (vnode.componentOptions.tag ? ('::' + (vnode.componentOptions.tag)) : '')
35
- }
33
+ return vnode.tag + (vnode.key ? `::${vnode.key}` : '')
36
34
  }
37
35
 
38
36
  export default {
@@ -44,12 +42,13 @@
44
42
  if (!isBrowser) {
45
43
  return vnode || (slot && slot[0])
46
44
  }
47
- const vnodeKey = getVnodeKey(vnode)
48
45
  const router = global.__mpxRouter
49
- if (vnodeKey && router && vnode.data.routerView) {
46
+ if (router) {
47
+ // 存在routeCount的情况下修改vnode.key避免patch时复用旧节点实例
48
+ if (router.currentRoute.query.routeCount) vnode.key = router.currentRoute.query.routeCount
49
+ const vnodeKey = getVnodeKey(vnode)
50
50
  if (router.needCache) {
51
51
  router.needCache.vnode = vnode
52
- router.needCache.vnodeKey = vnodeKey
53
52
  router.needCache = null
54
53
  }
55
54
 
@@ -65,29 +64,23 @@
65
64
  removeItem.vnode.componentInstance.$destroy()
66
65
  }
67
66
  })
67
+ // 在执行完destroy后再同步lastStack信息,让用户在destroy钩子中还能够访问到销毁之前的页面栈,与小程序保持一致
68
+ router.lastStack = router.stack.slice()
68
69
  router.needRemove.length = 0
69
70
 
70
71
  const stack = router.stack
71
72
  if (stack.length) {
72
- // 只要历史栈缓存中存在对应的页面存活实例,就进行复用
73
+ // 只要历史栈缓存中存在对应的页面存活实例且vnodeKey相同,就进行复用
73
74
  for (let i = stack.length; i > 0; i--) {
74
75
  const current = stack[i - 1]
75
- if (current.vnode && current.vnodeKey === vnodeKey && current.vnode.componentInstance) {
76
+ if (current.vnode && getVnodeKey(current.vnode) === vnodeKey && current.vnode.componentInstance) {
76
77
  vnode.componentInstance = current.vnode.componentInstance
77
- // 避免组件实例复用但是vnode.key不一致带来的bad case
78
- vnode.key = current.vnode.key
79
78
  break
80
79
  }
81
80
  }
82
81
  }
83
82
 
84
- if (router.__mpxAction) {
85
- if (router.__mpxAction.type === 'reLaunch') {
86
- // reLaunch时修改新vnode的key, 确保任何情况下都新创建组件实例
87
- vnode.key = (vnode.key || '') + router.__mpxAction.reLaunchCount
88
- }
89
- router.__mpxAction = null
90
- }
83
+ if (router.__mpxAction) router.__mpxAction = null
91
84
  vnode.data.keepAlive = true
92
85
  }
93
86
 
@@ -1,19 +1,21 @@
1
1
  <template>
2
- <div class="mpx-movable-scroll-content" ref="scrollContent">
3
- <div class="mpx-movable-scroll-item">
4
- <slot></slot>
5
- </div>
2
+ <div class="mpx-movable-scroll-content" ref="scrollContent">
3
+ <div class="mpx-movable-scroll-item">
4
+ <slot></slot>
6
5
  </div>
6
+ </div>
7
7
  </template>
8
8
 
9
9
  <script type="text/ecmascript-6">
10
- import {getCustomEvent} from './getInnerListeners'
10
+ import {getCustomEvent, extendEvent} from './getInnerListeners'
11
11
  import BScroll from '@better-scroll/core'
12
12
  import Movable from '@better-scroll/movable'
13
+ import ObserveDOM from '@better-scroll/observe-dom'
13
14
  import Zoom from '@better-scroll/zoom'
14
15
 
15
16
  BScroll.use(Movable)
16
17
  BScroll.use(Zoom)
18
+ BScroll.use(ObserveDOM)
17
19
 
18
20
  export default {
19
21
  data () {
@@ -23,6 +25,8 @@
23
25
  maxScrollX: 0,
24
26
  minScrollY: 0,
25
27
  maxScrollY: 0,
28
+ currentX: this.x,
29
+ currentY: this.y,
26
30
  lastestX: 0,
27
31
  lastestY: 0,
28
32
  lastestScale: 1,
@@ -30,7 +34,10 @@
30
34
  isZooming: false,
31
35
  isFirstTouch: true,
32
36
  source: '',
33
- touchEvent: ''
37
+ touchEvent: '',
38
+ isInited: false,
39
+ deactivatedX: 0,
40
+ deactivatedY: 0
34
41
  }
35
42
  },
36
43
  props: {
@@ -89,7 +96,13 @@
89
96
  speed: {
90
97
  type: Number,
91
98
  default: 1000
92
- }
99
+ },
100
+ scrollOptions: {
101
+ type: Object,
102
+ default: () => {
103
+ return {}
104
+ }
105
+ },
93
106
  },
94
107
  watch: {
95
108
  x (newVal) {
@@ -100,6 +113,7 @@
100
113
  if (newVal < this.bs.maxScrollX) {
101
114
  newVal = this.bs.maxScrollX
102
115
  }
116
+ this.currentX = newVal
103
117
  this.bs.scrollTo(newVal, this.bs.y, this.speed)
104
118
  },
105
119
  y (newVal) {
@@ -110,6 +124,7 @@
110
124
  if (newVal < this.bs.maxScrollY) {
111
125
  newVal = this.bs.maxScrollY
112
126
  }
127
+ this.currentY = newVal
113
128
  this.bs.scrollTo(this.bs.x, newVal, this.speed)
114
129
  },
115
130
  scaleValue (newVal) {
@@ -121,16 +136,61 @@
121
136
  newVal = 0.5
122
137
  }
123
138
  this.bs.zoomTo(newVal, 'center', 'center')
139
+ },
140
+ disabled () {
141
+ this.init()
124
142
  }
125
143
  },
126
144
  mounted () {
145
+ if (!this.scrollOptions.closeResizeObserver) {
146
+ this.createResizeObserver()
147
+ }
127
148
  this.init()
128
149
  },
150
+ activated () {
151
+ if (this.deactivatedX || this.deactivatedY) {
152
+ this.refresh()
153
+ this.bs.putAt(this.deactivatedX, this.deactivatedY, 0)
154
+ }
155
+ },
156
+ deactivated () {
157
+ // when the hook is triggered
158
+ // bs will recalculate the boundary of movable to 0
159
+ // so record the position of the movable
160
+ this.deactivatedX = this.bs.x
161
+ this.deactivatedY = this.bs.y
162
+ },
129
163
  beforeDestroy () {
130
- this.bs && this.bs.destroy()
164
+ this.destroyBs()
165
+ if (this.resizeObserver) {
166
+ this.resizeObserver.disconnect()
167
+ this.resizeObserver = null
168
+ }
131
169
  },
132
170
  methods: {
171
+ createResizeObserver () {
172
+ if (typeof ResizeObserver !== 'undefined') {
173
+ this.resizeObserver = new ResizeObserver(entries => {
174
+ if (!this.isInited) {
175
+ this.isInited = true
176
+ return
177
+ }
178
+ this.refresh()
179
+ })
180
+ const elementToObserve = document.querySelector('.mpx-movable-scroll-content')
181
+ elementToObserve && this.resizeObserver.observe(elementToObserve)
182
+ }
183
+ },
184
+ refresh () {
185
+ this.bs && this.bs.refresh()
186
+ },
187
+ destroyBs () {
188
+ if (!this.bs) return
189
+ this.bs.destroy()
190
+ delete this.bs
191
+ },
133
192
  init () {
193
+ this.destroyBs()
134
194
  if (!this.$refs.scrollContent.parentNode || (this.$refs.scrollContent.parentNode && this.$refs.scrollContent.parentNode.className !== 'mpx-movable-scroll-wrapper')) {
135
195
  return
136
196
  }
@@ -143,8 +203,8 @@
143
203
  scrollX: false,
144
204
  scrollY: false,
145
205
  movable: true,
146
- startX: this.x,
147
- startY: this.y,
206
+ startX: this.currentX,
207
+ startY: this.currentY,
148
208
  bounce: this.outOfBounds,
149
209
  bounceTime: 800 / (this.damping / 20),
150
210
  probeType: 3,
@@ -153,7 +213,7 @@
153
213
  const BehaviorHooks = this.bs.scroller.scrollBehaviorY.hooks
154
214
  const actionsHandlerHooks = this.bs.scroller.actionsHandler.hooks
155
215
  const scrollerHooks = this.bs.scroller.hooks
156
- this.bs.putAt(this.x, this.y, 0)
216
+ this.bs.putAt(this.currentX, this.currentY, 0)
157
217
  this.lastestX = this.roundFun(this.x)
158
218
  this.lastestY = this.roundFun(this.y)
159
219
  this.lastestScale = this.roundFun(this.scaleValue)
@@ -184,6 +244,10 @@
184
244
  this.lastestX = this.roundFun(position.x)
185
245
  this.lastestY = this.roundFun(position.y)
186
246
  })
247
+ scrollerHooks.on('scrollEnd', (position) =>{
248
+ this.currentX = this.bs.x
249
+ this.currentY = this.bs.y
250
+ })
187
251
  scrollerHooks.on('touchEnd', (position) => {
188
252
  this.isFirstTouch = true
189
253
  if (position.x > this.minScrollX || position.x < this.maxScrollX ||
@@ -204,6 +268,14 @@
204
268
  this.bs.movingDirectionY = -1
205
269
  }
206
270
  })
271
+ actionsHandlerHooks.on('start', (e) => {
272
+ extendEvent(e, { detail: Object.assign({}, e.detail) })
273
+ this.$emit('touchstart', e)
274
+ })
275
+ actionsHandlerHooks.on('end', (e) => {
276
+ extendEvent(e, { detail: Object.assign({}, e.detail) })
277
+ this.$emit('touchend', e)
278
+ })
207
279
  actionsHandlerHooks.on('move', ({ deltaX, deltaY, e }) => {
208
280
  if (this.isZooming) {
209
281
  return
@@ -215,7 +287,9 @@
215
287
  this.touchEvent = 'vtouchmove'
216
288
  }
217
289
  }
218
- this.$emit(this.touchEvent, getCustomEvent(this.touchEvent, {}, this))
290
+ extendEvent(e, { detail: Object.assign({}, e.detail), currentTarget: e.target })
291
+ this.$emit(this.touchEvent, e)
292
+ this.$emit('touchmove', e)
219
293
  this.isFirstTouch = false
220
294
  })
221
295
  if (this.inertia) { // movable-view是否带有惯性
@@ -240,9 +314,6 @@
240
314
  this.isZooming = false
241
315
  })
242
316
  }
243
- if (this.disabled) { // 禁用
244
- this.bs.disable()
245
- }
246
317
  },
247
318
  initOptions () {
248
319
  if (!this.friction || this.friction < 0) {
@@ -273,19 +344,24 @@
273
344
  swipeTime: 50
274
345
  }
275
346
  }
276
- if (this.direction === 'vertical') {
347
+ if (this.disabled) {
348
+ this.bsOptions = {
349
+ ...this.bsOptions,
350
+ freeScroll: false,
351
+ scrollY: false,
352
+ scrollX: false
353
+ }
354
+ } else if (this.direction === 'vertical') {
277
355
  this.bsOptions = {
278
356
  ...this.bsOptions,
279
357
  scrollY: true
280
358
  }
281
- }
282
- if (this.direction === 'horizontal') {
359
+ } else if (this.direction === 'horizontal') {
283
360
  this.bsOptions = {
284
361
  ...this.bsOptions,
285
362
  scrollX: true
286
363
  }
287
- }
288
- if (this.direction === 'all') {
364
+ } else if (this.direction === 'all') {
289
365
  this.bsOptions = {
290
366
  ...this.bsOptions,
291
367
  freeScroll: true,
@@ -293,6 +369,10 @@
293
369
  scrollY: true
294
370
  }
295
371
  }
372
+ this.bsOptions = {
373
+ ...this.bsOptions,
374
+ ...this.scrollOptions
375
+ }
296
376
  },
297
377
  // 处理小数点,四舍五入,默认保留一位小数
298
378
  roundFun(value, n = 1) {
@@ -302,7 +382,9 @@
302
382
  }
303
383
  </script>
304
384
  <style lang="stylus" rel="stylesheet/stylus" scoped>
305
- .mpx-movable-scroll-content {
306
- position: absolute
307
- }
385
+ .mpx-movable-scroll-content
386
+ position: absolute
387
+ .mpx-movable-scroll-item
388
+ width: 100%
389
+ height: 100%
308
390
  </style>
@@ -15,7 +15,13 @@
15
15
  export default {
16
16
  name: 'mpx-picker-view-column',
17
17
  props: {
18
- value: Array
18
+ value: Array,
19
+ scrollOptions: {
20
+ type: Object,
21
+ default: () => {
22
+ return {}
23
+ }
24
+ }
19
25
  },
20
26
  data() {
21
27
  return {
@@ -64,7 +70,9 @@
64
70
  rotate: -5,
65
71
  wheelWrapperClass: 'wheel-scroll'
66
72
  },
67
- probeType: 3
73
+ probeType: 3,
74
+ bindToWrapper: true,
75
+ ...this.scrollOptions
68
76
  })
69
77
  this.wheels[0].on('scrollStart', function () {
70
78
  if (this.pickerView) {
@@ -163,7 +163,7 @@
163
163
  height: 100%
164
164
  overflow: hidden
165
165
  text-align: center
166
- font-size: 14px
166
+ font-size: 16px
167
167
  position: relative
168
168
 
169
169
  &.mpx-picker-fade-enter, &.mpx-picker-fade-leave-active
@@ -138,6 +138,12 @@
138
138
  fields: {
139
139
  type: String,
140
140
  default: 'day'
141
+ },
142
+ scrollOptions: {
143
+ type: Object,
144
+ default: () => {
145
+ return {}
146
+ }
141
147
  }
142
148
  },
143
149
  data () {
@@ -311,7 +317,9 @@
311
317
  wheelWrapperClass: 'wheel-scroll',
312
318
  wheelItemClass: 'wheel-item'
313
319
  },
314
- probeType: 3
320
+ probeType: 3,
321
+ bindToWrapper: true,
322
+ ...this.scrollOptions
315
323
  })
316
324
  if (this.mode === 'time' || this.mode === 'date') {
317
325
  this.wheels[i].on('scrollStart', function (i) {
@@ -30,7 +30,12 @@
30
30
  type: [Number, String],
31
31
  default: 0
32
32
  },
33
- scrollOptions: Object,
33
+ scrollOptions: {
34
+ type: Object,
35
+ default: () => {
36
+ return {}
37
+ }
38
+ },
34
39
  updateRefresh: {
35
40
  type: Boolean,
36
41
  default: true
@@ -57,15 +62,23 @@
57
62
  data () {
58
63
  return {
59
64
  isLoading: false,
60
- isAutoPullDown: true
65
+ isAutoPullDown: true,
66
+ currentX: 0,
67
+ currentY: 0,
68
+ lastX: 0,
69
+ lastY: 0
61
70
  }
62
71
  },
63
72
  computed: {
64
73
  _scrollTop () {
65
- return processSize(this.scrollTop)
74
+ const size = processSize(this.scrollTop)
75
+ this.currentY = size
76
+ return size
66
77
  },
67
78
  _scrollLeft () {
68
- return processSize(this.scrollLeft)
79
+ const size = processSize(this.scrollLeft)
80
+ this.currentX = size
81
+ return size
69
82
  },
70
83
  _lowerThreshold () {
71
84
  return processSize(this.lowerThreshold)
@@ -87,10 +100,13 @@
87
100
  className += ' active'
88
101
  }
89
102
  return className
103
+ },
104
+ scroll() {
105
+ return this.scrollX || this.scrollY
90
106
  }
91
107
  },
92
108
  mounted () {
93
- this.init()
109
+ this.initBs()
94
110
  },
95
111
  activated () {
96
112
  if (!this.__mpx_deactivated) {
@@ -106,14 +122,14 @@
106
122
  this.__mpx_deactivated = true
107
123
  },
108
124
  beforeDestroy () {
109
- this.destroy()
125
+ this.destroyBs()
110
126
  },
111
127
  updated () {
112
128
  if (this.updateRefresh) this.refresh()
113
129
  },
114
130
  watch: {
115
131
  scrollIntoView (val) {
116
- this.bs && this.bs.scrollToElement('#' + val, this.scrollWithAnimation ? 200 : 0)
132
+ this.scrollToView(val, this.scrollWithAnimation ? 200 : 0)
117
133
  },
118
134
  _scrollTop (val) {
119
135
  this.bs && this.bs.scrollTo(this.bs.x, -val, this.scrollWithAnimation ? 200 : 0)
@@ -136,20 +152,33 @@
136
152
  }
137
153
  }
138
154
  },
155
+ },
156
+ scroll(val) {
157
+ if (val) {
158
+ this.initBs()
159
+ } else {
160
+ this.disableBs()
161
+ }
139
162
  }
140
163
  },
141
164
  methods: {
142
- destroy () {
165
+ destroyBs () {
143
166
  if (!this.bs) return
144
167
  this.bs.destroy()
145
168
  delete this.bs
146
169
  },
147
- init () {
148
- if (this.bs) return
170
+ disableBs() {
171
+ if (!this.bs) return
172
+ this.bs.disable()
173
+ this.currentX = -this.bs.x
174
+ this.currentY = -this.bs.y
175
+ },
176
+ initBs () {
177
+ this.destroyBs()
149
178
  this.initLayerComputed()
150
179
  const originBsOptions = {
151
- startX: -this._scrollLeft,
152
- startY: -this._scrollTop,
180
+ startX: -this.currentX,
181
+ startY: -this.currentY,
153
182
  scrollX: this.scrollX,
154
183
  scrollY: this.scrollY,
155
184
  probeType: 3,
@@ -170,8 +199,8 @@
170
199
  this.bs.scroller.hooks.on('beforeRefresh', () => {
171
200
  this.initLayerComputed()
172
201
  })
173
- this.lastX = -this._scrollLeft
174
- this.lastY = -this._scrollTop
202
+ this.lastX = -this.currentX
203
+ this.lastY = -this.currentY
175
204
  this.bs.on('scroll', throttle(({ x, y }) => {
176
205
  const deltaX = x - this.lastX
177
206
  const deltaY = y - this.lastY
@@ -201,9 +230,11 @@
201
230
  leading: true,
202
231
  trailing: false
203
232
  }))
204
- if (this.scrollIntoView) {
205
- this.bs.scrollToElement('#' + this.scrollIntoView)
206
- }
233
+ this.bs.on('scrollEnd', () => {
234
+ this.currentX = -this.bs.x
235
+ this.currentY = -this.bs.y
236
+ })
237
+ if (this.scrollIntoView) this.scrollToView(this.scrollIntoView)
207
238
  // 若开启自定义下拉刷新 或 开启 scroll-view 增强特性
208
239
  if (this.refresherEnabled || this.enhanced) {
209
240
  const actionsHandlerHooks = this.bs.scroller.actionsHandler.hooks
@@ -258,12 +289,19 @@
258
289
  }
259
290
  }
260
291
  },
292
+ scrollToView (id, duration = 0) {
293
+ if (!id) return
294
+ id = '#' + id
295
+ if (!document.querySelector(id)) return // 不存在元素时阻断,直接调用better-scroll的方法会报错
296
+ this.bs?.scrollToElement(id, duration)
297
+ },
261
298
  initLayerComputed () {
262
299
  const wrapper = this.$refs.wrapper
263
- const wrapperWidth = wrapper.offsetWidth
264
- const wrapperHeight = wrapper.offsetHeight
265
- this.$refs.innerWrapper.style.width = `${wrapperWidth}px`
266
- this.$refs.innerWrapper.style.height = `${wrapperHeight}px`
300
+ const computedStyle = getComputedStyle(wrapper)
301
+ // 考虑子元素样式可能会设置100%,如果直接继承 scrollContent 的样式可能会有问题
302
+ // 所以使用 wrapper 作为 innerWrapper 的宽高参考依据
303
+ this.$refs.innerWrapper.style.width = `${wrapper.clientWidth - parseInt(computedStyle.paddingLeft) - parseInt(computedStyle.paddingRight)}px`
304
+ this.$refs.innerWrapper.style.height = `${wrapper.clientHeight - parseInt(computedStyle.paddingTop) - parseInt(computedStyle.paddingBottom)}px`
267
305
  const innerWrapper = this.$refs.innerWrapper
268
306
  const childrenArr = Array.from(innerWrapper.children)
269
307
 
@@ -342,7 +380,11 @@
342
380
  class: 'circle circle-c'
343
381
  }),
344
382
  ]
345
- ) : null
383
+ ) : this.$slots.refresher
384
+ ? createElement('div', {
385
+ class: 'mpx-pull-down-slot',
386
+ }, this.$slots.refresher)
387
+ : null
346
388
 
347
389
  const pullDownWrapper = this.refresherEnabled ? createElement('div', {
348
390
  class: 'mpx-pull-down-wrapper',
@@ -376,7 +418,11 @@
376
418
  bottom: 20px
377
419
  left: 50%
378
420
  transform: translateX(-50%)
379
-
421
+ .mpx-pull-down-slot
422
+ position: absolute
423
+ width: 100%
424
+ height: auto
425
+ bottom: 0
380
426
  .mpx-pull-down-content-black
381
427
  .circle
382
428
  display: inline-block;