Skip to content

Commit

Permalink
fix(taro-h5): fix scroll issue in iOS when using showToast/showModal/…
Browse files Browse the repository at this point in the history
…showActionSheet (#5092)
  • Loading branch information
leoswing authored and Littly committed Dec 26, 2019
1 parent 7852967 commit 698c057
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 16 deletions.
24 changes: 15 additions & 9 deletions packages/taro-h5/src/api/interactive/actionSheet.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { inlineStyle, setTransform } from '../utils'
import { inlineStyle, setTransform, interactiveHelper } from '../utils'

const noop = function () {}
export default class ActionSheet {
Expand All @@ -12,13 +12,13 @@ export default class ActionSheet {

style = {
maskStyle: {
'position': 'fixed',
'z-index': '1000',
'top': '0',
'right': '0',
'left': '0',
'bottom': '0',
'background': 'rgba(0,0,0,0.6)'
'position': 'fixed',
'z-index': '1000',
'top': '0',
'right': '0',
'left': '0',
'bottom': '0',
'background': 'rgba(0,0,0,0.6)'
},
actionSheetStyle: {
'z-index': '4999',
Expand Down Expand Up @@ -123,6 +123,8 @@ export default class ActionSheet {

// show immediately
document.body.appendChild(this.el)
// set body position fixed style
interactiveHelper().handleAfterCreate()
setTimeout(() => {
this.el.style.opacity = '1'
setTransform(this.actionSheet, 'translate(0, 0)')
Expand All @@ -139,7 +141,7 @@ export default class ActionSheet {
...this.options,
...options
}

this.lastConfig = config

if (this.hideOpacityTimer) clearTimeout(this.hideOpacityTimer)
Expand Down Expand Up @@ -179,6 +181,8 @@ export default class ActionSheet {

// show
this.el.style.display = 'block'
// set body position fixed style
interactiveHelper().handleAfterCreate()
setTimeout(() => {
this.el.style.opacity = '1'
setTransform(this.actionSheet, 'translate(0, 0)')
Expand Down Expand Up @@ -208,6 +212,8 @@ export default class ActionSheet {

this.hideOpacityTimer = setTimeout(() => {
this.el.style.opacity = '0'
// reset body style as default
interactiveHelper().handleBeforeDestroy()
setTransform(this.actionSheet, 'translate(0, 100%)')
this.hideDisplayTimer = setTimeout(() => { this.el.style.display = 'none' }, 200)
}, 0)
Expand Down
13 changes: 11 additions & 2 deletions packages/taro-h5/src/api/interactive/modal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { inlineStyle } from '../utils'
import { inlineStyle, interactiveHelper } from '../utils'

const noop = function () {}

Expand Down Expand Up @@ -49,7 +49,10 @@ export default class Modal {
'min-height': '40px',
'font-size': '15px',
'line-height': '1.3',
'color': '#808080'
'color': '#808080',
'display': 'flex',
'align-items': 'center',
'justify-content': 'space-around'
},
footStyle: {
'position': 'relative',
Expand Down Expand Up @@ -156,6 +159,8 @@ export default class Modal {

// show immediately
document.body.appendChild(this.el)
// set body fix style
interactiveHelper().handleAfterCreate()
setTimeout(() => { this.el.style.opacity = '1' }, 0)

return new Promise(resolve => (this.resolveHandler = resolve))
Expand Down Expand Up @@ -234,6 +239,8 @@ export default class Modal {

// show
this.el.style.display = 'block'
// set body position fixed style
interactiveHelper().handleAfterCreate()
setTimeout(() => { this.el.style.opacity = '1' }, 0)

return new Promise(resolve => (this.resolveHandler = resolve))
Expand All @@ -245,6 +252,8 @@ export default class Modal {

this.hideOpacityTimer = setTimeout(() => {
this.el.style.opacity = '0'
// reset body style as default
interactiveHelper().handleBeforeDestroy()
this.hideDisplayTimer = setTimeout(() => { this.el.style.display = 'none' }, 200)
}, 0)
}
Expand Down
8 changes: 7 additions & 1 deletion packages/taro-h5/src/api/interactive/toast.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { inlineStyle } from '../utils'
import { inlineStyle, interactiveHelper } from '../utils'

const noop = function () {}

Expand Down Expand Up @@ -135,6 +135,8 @@ export default class Toast {

// show immediately
document.body.appendChild(this.el)
// set body position fixed style
interactiveHelper().handleAfterCreate()
setTimeout(() => { this.el.style.opacity = '1' }, 0)
this.type = config._type

Expand Down Expand Up @@ -192,6 +194,8 @@ export default class Toast {

// show
this.el.style.display = 'block'
// set body position fixed style
interactiveHelper().handleAfterCreate()
setTimeout(() => { this.el.style.opacity = '1' }, 0)
this.type = config._type

Expand All @@ -212,6 +216,8 @@ export default class Toast {

this.hideOpacityTimer = setTimeout(() => {
this.el.style.opacity = '0'
// reset body style as default
interactiveHelper().handleBeforeDestroy()
this.hideDisplayTimer = setTimeout(() => { this.el.style.display = 'none' }, 100)
}, duration)
}
Expand Down
81 changes: 77 additions & 4 deletions packages/taro-h5/src/api/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ function serializeParams (params) {
}
return Object.keys(params)
.map(key => (
`${encodeURIComponent(key)}=${typeof (params[key]) ==="object" ?
encodeURIComponent(JSON.stringify(params[key])):
encodeURIComponent(params[key])}`))
`${encodeURIComponent(key)}=${typeof (params[key]) === 'object'
? encodeURIComponent(JSON.stringify(params[key]))
: encodeURIComponent(params[key])}`))
.join('&')
}

Expand Down Expand Up @@ -236,6 +236,78 @@ const getTimingFunc = (easeFunc, frameCnt) => {
}
}

/**
* use closure function to store document.body.style in memory when loaded
*/
const bodyStatusClosure = (() => {
let hasCalculated
let bodyStyle
// use object copy to prevent document.body style read issue
const bodyCopy = Object.assign({}, document.body.style)
if (!hasCalculated) {
bodyStyle = bodyCopy
}
hasCalculated = true
return {
getInlineStyle: () => bodyStyle && bodyStyle.cssText,
hasCalculated
}
})()

/**
* get scrollTop and compact for all possible browser
*
* @returns scrollTop
*/
function getScrollTop () {
if (document.scrollingElement) {
return document.scrollingElement.scrollTop
} else {
return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
}
}

/**
* compact for scrollTop
*
* for more info @see: https://www.zhangxinxu.com/wordpress/2019/02/document-scrollingelement/
* @param scrollTop scrollTop which needs to be reset
*/
function setScrollTop (scrollTop) {
if (document.scrollingElement) {
document.scrollingElement.scrollTop = scrollTop
} else {
document.documentElement.scrollTop = scrollTop
document.body.scrollTop = scrollTop
}
}

let scrollTop = 0

/**
* interactive helper to provide position fixed when modal/toast/actionSheet open.
* And reset body style as default when close.
*/
const interactiveHelper = () => {
return {
handleAfterCreate: () => {
scrollTop = getScrollTop()
const bodyFixStyle = {
'position': 'fixed',
'width': '100%',
'overflow': 'hidden',
'top': `${-scrollTop}px`
}
document.body.setAttribute('style', inlineStyle(bodyFixStyle))
},
handleBeforeDestroy: () => {
const bodyInlineStyle = bodyStatusClosure.getInlineStyle() || {}
document.body.style = bodyInlineStyle
setScrollTop(scrollTop)
}
}
}

export {
shouleBeObject,
getParameterError,
Expand All @@ -254,5 +326,6 @@ export {
processOpenapi,
findRef,
easeInOut,
getTimingFunc
getTimingFunc,
interactiveHelper
}

0 comments on commit 698c057

Please sign in to comment.