Skip to content

Commit

Permalink
fix(swiper): 优化 swiper 节点刷新方案 (#9907)
Browse files Browse the repository at this point in the history
* fix(swiper): 优化 swiper 节点刷新方案

* fix(reawct-components): 占用节点刷新优化

* fix(components): 测试延时修改

Co-authored-by: chenjiajian <[email protected]>
  • Loading branch information
ZakaryCode and Chen-jj authored Aug 2, 2021
1 parent ba6d8ea commit 741431e
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 22 deletions.
2 changes: 1 addition & 1 deletion packages/taro-components-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"classnames": "^2.2.5",
"intersection-observer": "^0.7.0",
"resolve-pathname": "^3.0.0",
"swiper": "6.7.5",
"swiper": "6.8.0",
"weui": "^1.1.2"
}
}
64 changes: 55 additions & 9 deletions packages/taro-components-react/src/components/swiper/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface SwiperProps {
duration?: number
current?: number
displayMultipleItems?: number
circular?: boolean
vertical?: boolean
spaceBetween?: any
previousMargin?: string
Expand Down Expand Up @@ -70,6 +71,9 @@ class Swiper extends React.Component<SwiperProps, Record<string, unknown>> {
_$height = 0
$el: HTMLDivElement | null
mySwiper: ISwiper
observer: MutationObserver
observerFirst: MutationObserver
observerLast: MutationObserver

componentDidMount () {
const {
Expand Down Expand Up @@ -132,13 +136,6 @@ class Swiper extends React.Component<SwiperProps, Record<string, unknown>> {
if (that.props.autoplay && target.contains(_swiper.$el[0])) {
_swiper.slideTo(that._$current)
}
} else if (className.includes('swiper-wrapper')) {
if (e.addedNodes.length > 0 || e.removedNodes.length > 0) {
// @ts-ignore
_swiper.loopDestroy()
// @ts-ignore
_swiper.loopCreate()
}
}
}
}
Expand All @@ -161,14 +158,22 @@ class Swiper extends React.Component<SwiperProps, Record<string, unknown>> {
setTimeout(() => {
this.mySwiper.update()
}, 500)

if (!this.mySwiper || !this.props.circular) return

const wrapper = this.mySwiper.$wrapperEl[0]
this.observer = new MutationObserver(this.handleSwiperLoopListen)

this.observer.observe(wrapper, {
childList: true
})
}

UNSAFE_componentWillReceiveProps (nextProps) {
if (this.mySwiper) {
const nextCurrent = typeof nextProps.current === 'number' ? nextProps.current : this._$current || 0

;(this.mySwiper as any).loopDestroy()
;(this.mySwiper as any).loopCreate()
this.handleSwiperLoop()
// 是否衔接滚动模式
if (nextProps.circular) {
if (!this.mySwiper.isBeginning && !this.mySwiper.isEnd) {
Expand Down Expand Up @@ -214,6 +219,9 @@ class Swiper extends React.Component<SwiperProps, Record<string, unknown>> {
componentWillUnmount () {
this.$el = null
if (this.mySwiper) this.mySwiper.destroy()
this.observer.disconnect && this.observer.disconnect()
this.observerFirst.disconnect && this.observerFirst.disconnect()
this.observerLast.disconnect && this.observerLast.disconnect()
}

handleOnChange (e: Event) {
Expand All @@ -230,6 +238,33 @@ class Swiper extends React.Component<SwiperProps, Record<string, unknown>> {
return parseFloat(s.replace(/r*px/i, ''))
}

handleSwiperLoopListen = () => {
this.observerFirst?.disconnect && this.observerFirst.disconnect()
this.observerLast?.disconnect && this.observerLast.disconnect()
this.observerFirst = new MutationObserver(this.handleSwiperLoop)
this.observerLast = new MutationObserver(this.handleSwiperLoop)
const wrapper = this.mySwiper.$wrapperEl[0]
const list = wrapper.querySelectorAll('taro-swiper-item-core:not(.swiper-slide-duplicate)')
if (list.length >= 1) {
this.observerFirst.observe(list[0], {
characterData: true
})
} else if (list.length >= 2) {
this.observerLast.observe(list[list.length - 1], {
characterData: true
})
}
}

handleSwiperLoop = debounce(() => {
if (this.mySwiper && this.props.circular) {
// @ts-ignore
this.mySwiper.loopDestroy()
// @ts-ignore
this.mySwiper.loopCreate()
}
}, 500)

render () {
const {
className,
Expand Down Expand Up @@ -277,3 +312,14 @@ class Swiper extends React.Component<SwiperProps, Record<string, unknown>> {
}

export { Swiper, SwiperItem }

function debounce (fn, delay: number) {
let timer: NodeJS.Timeout

return function (...arrs) {
clearTimeout(timer)
timer = setTimeout(function () {
fn(...arrs)
}, delay)
}
}
2 changes: 1 addition & 1 deletion packages/taro-components/__tests__/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export function waitForChange (dom) {
timer = setTimeout(() => {
observer.disconnect()
resolve()
}, 500)
}, 1000)
})

setTimeout(() => {
Expand Down
2 changes: 1 addition & 1 deletion packages/taro-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"intersection-observer": "^0.7.0",
"omit.js": "^1.0.0",
"resolve-pathname": "^3.0.0",
"swiper": "6.7.5",
"swiper": "6.8.0",
"weui": "^1.1.2"
},
"devDependencies": {
Expand Down
66 changes: 56 additions & 10 deletions packages/taro-components/src/components/swiper/swiper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,24 @@ export class Swiper implements ComponentInterface {
}
}

@State() observer: MutationObserver
@State() observerFirst: MutationObserver
@State() observerLast: MutationObserver

componentWillLoad () {
this.isWillLoadCalled = true
}

componentDidLoad () {
this.handleInit()
if (!this.swiper || !this.circular) return

const wrapper = this.swiper.$wrapperEl[0]
this.observer = new MutationObserver(this.handleSwiperLoopListen)

this.observer.observe(wrapper, {
childList: true
})
}

componentWillUpdate () {
Expand All @@ -186,12 +198,42 @@ export class Swiper implements ComponentInterface {
}

componentDidRender () {
if (this.swiper && this.circular) {
;(this.swiper as any).loopDestroy()
;(this.swiper as any).loopCreate()
this.handleSwiperLoop()
}

disconnectedCallback () {
this.observer.disconnect && this.observer.disconnect()
this.observerFirst.disconnect && this.observerFirst.disconnect()
this.observerLast.disconnect && this.observerLast.disconnect()
}

handleSwiperLoopListen = () => {
this.observerFirst?.disconnect && this.observerFirst.disconnect()
this.observerLast?.disconnect && this.observerLast.disconnect()
this.observerFirst = new MutationObserver(this.handleSwiperLoop)
this.observerLast = new MutationObserver(this.handleSwiperLoop)
const wrapper = this.swiper.$wrapperEl[0]
const list = wrapper.querySelectorAll('taro-swiper-item-core:not(.swiper-slide-duplicate)')
if (list.length >= 1) {
this.observerFirst.observe(list[0], {
characterData: true
})
} else if (list.length >= 2) {
this.observerLast.observe(list[list.length - 1], {
characterData: true
})
}
}

handleSwiperLoop = debounce(() => {
if (this.swiper && this.circular) {
// @ts-ignore
this.swiper.loopDestroy()
// @ts-ignore
this.swiper.loopCreate()
}
}, 500)

handleInit () {
const {
autoplay,
Expand Down Expand Up @@ -239,13 +281,6 @@ export class Swiper implements ComponentInterface {
if (that.autoplay && target.contains(_swiper.$el[0])) {
_swiper.slideTo(that.current)
}
} else if (className.includes('swiper-wrapper')) {
if (e.addedNodes.length > 0 || e.removedNodes.length > 0) {
// @ts-ignore
_swiper.loopDestroy()
// @ts-ignore
_swiper.loopCreate()
}
}
}
}
Expand Down Expand Up @@ -313,3 +348,14 @@ export class Swiper implements ComponentInterface {
)
}
}

function debounce (fn, delay: number) {
let timer: NodeJS.Timeout

return function (...arrs) {
clearTimeout(timer)
timer = setTimeout(function () {
fn(...arrs)
}, delay)
}
}

0 comments on commit 741431e

Please sign in to comment.