bug
jiangping
2023-11-07 64b432916af9c9218ab3f3eca614e26c542142ae
minipro_standard/uni_modules/uview-ui/components/u-transition/transition.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,157 @@
// å®šä¹‰ä¸€ä¸ªä¸€å®šæ—¶é—´åŽè‡ªåŠ¨æˆåŠŸçš„promise,让调用nextTick方法处,进入下一个then方法
const nextTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 50))
// nvue动画模块实现细节抽离在外部文件
import animationMap from './nvue.ani-map.js'
// #ifndef APP-NVUE
// å®šä¹‰ç±»åï¼Œé€šè¿‡ç»™å…ƒç´ åŠ¨æ€åˆ‡æ¢ç±»åï¼Œèµ‹äºˆå…ƒç´ ä¸€å®šçš„css动画样式
const getClassNames = (name) => ({
    enter: `u-${name}-enter u-${name}-enter-active`,
    'enter-to': `u-${name}-enter-to u-${name}-enter-active`,
    leave: `u-${name}-leave u-${name}-leave-active`,
    'leave-to': `u-${name}-leave-to u-${name}-leave-active`
})
// #endif
// #ifdef APP-NVUE
// å¼•å…¥nvue(weex)的animation动画模块,文档见:
// https://weex.apache.org/zh/docs/modules/animation.html#transition
const animation = uni.requireNativePlugin('animation')
const getStyle = (name) => animationMap[name]
// #endif
export default {
    methods: {
        // ç»„件被点击发出事件
        clickHandler() {
            this.$emit('click')
        },
        // #ifndef APP-NVUE
        // vue版本的组件进场处理
         vueEnter() {
            // åŠ¨ç”»è¿›å…¥æ—¶çš„ç±»å
            const classNames = getClassNames(this.mode)
            // å®šä¹‰çŠ¶æ€å’Œå‘å‡ºåŠ¨ç”»è¿›å…¥å‰äº‹ä»¶
            this.status = 'enter'
            this.$emit('beforeEnter')
            this.inited = true
            this.display = true
            this.classes = classNames.enter
            this.$nextTick(async () => {
            // #ifdef H5
            await uni.$u.sleep(20)
            // #endif
                // æ ‡è¯†åŠ¨ç”»å°šæœªç»“æŸ
                this.$emit('enter')
                this.transitionEnded = false
            // ç»„件动画进入后触发的事件
                this.$emit('afterEnter')
                // èµ‹äºˆç»„ä»¶enter-to类名
                this.classes = classNames['enter-to']
            })
        },
        // åŠ¨ç”»ç¦»åœºå¤„ç†
        vueLeave() {
            // å¦‚果不是展示状态,无需执行逻辑
            if (!this.display) return
            const classNames = getClassNames(this.mode)
            // æ ‡è®°ç¦»å¼€çŠ¶æ€å’Œå‘å‡ºäº‹ä»¶
            this.status = 'leave'
            this.$emit('beforeLeave')
            // èŽ·å¾—ç±»å
            this.classes = classNames.leave
            this.$nextTick(() => {
               // åŠ¨ç”»æ­£åœ¨ç¦»åœºçš„çŠ¶æ€
               this.transitionEnded = false
               this.$emit('leave')
                // ç»„件执行动画,到了执行的执行时间后,执行一些额外处理
                setTimeout(this.onTransitionEnd, this.duration)
                this.classes = classNames['leave-to']
            })
        },
        // #endif
        // #ifdef APP-NVUE
        // nvue版本动画进场
        nvueEnter() {
            // èŽ·å¾—æ ·å¼çš„åç§°
            const currentStyle = getStyle(this.mode)
            // ç»„件动画状态和发出事件
            this.status = 'enter'
            this.$emit('beforeEnter')
            // å±•示生成组件元素
            this.inited = true
            this.display = true
            // åœ¨nvue安卓上,由于渲染速度慢,在弹窗,键盘,日历等组件中,渲染其中的内容需要时间
            // å¯¼è‡´å‡ºçŽ°å¼¹çª—å¡é¡¿ï¼Œè¿™é‡Œè®©å…¶ä¸€å¼€å§‹ä¸ºé€æ˜ŽçŠ¶æ€ï¼Œç­‰ä¸€å®šæ—¶é—´æ¸²æŸ“å®ŒæˆåŽï¼Œå†è®©å…¶éšè—èµ·æ¥ï¼Œå†è®©å…¶æŒ‰æ­£å¸¸é€»è¾‘å‡ºçŽ°
            this.viewStyle = {
                opacity: 0
            }
            // ç­‰å¾…弹窗内容渲染完成
            this.$nextTick(() => {
                // åˆå¹¶æ ·å¼
                this.viewStyle = currentStyle.enter
                Promise.resolve()
                    .then(nextTick)
                    .then(() => {
                        // ç»„件开始进入前的事件
                        this.$emit('enter')
                        // nvue的transition动画模块需要通过ref调用组件,注意此处的ref不同于vue的this.$refs['u-transition']用法
                        animation.transition(this.$refs['u-transition'].ref, {
                            styles: currentStyle['enter-to'],
                            duration: this.duration,
                            timingFunction: this.timingFunction,
                            needLayout: false,
                            delay: 0
                        }, () => {
                            // åŠ¨ç”»æ‰§è¡Œå®Œæ¯•ï¼Œå‘å‡ºäº‹ä»¶
                            this.$emit('afterEnter')
                        })
                    })
                    .catch(() => {})
            })
        },
        nvueLeave() {
            if (!this.display) {
                return
            }
            const currentStyle = getStyle(this.mode)
            // å®šä¹‰çŠ¶æ€å’Œäº‹ä»¶
            this.status = 'leave'
            this.$emit('beforeLeave')
            // åˆå¹¶æ ·å¼
            this.viewStyle = currentStyle.leave
            // æ”¾åˆ°promise中处理执行过程
            Promise.resolve()
                .then(nextTick) // ç­‰å¾…几十ms
                .then(() => {
                    this.transitionEnded = false
                    // åŠ¨ç”»æ­£åœ¨ç¦»åœºçš„çŠ¶æ€
                    this.$emit('leave')
                    animation.transition(this.$refs['u-transition'].ref, {
                        styles: currentStyle['leave-to'],
                        duration: this.duration,
                        timingFunction: this.timingFunction,
                        needLayout: false,
                        delay: 0
                    }, () => {
                        this.onTransitionEnd()
                    })
                })
                .catch(() => {})
        },
        // #endif
        // å®Œæˆè¿‡æ¸¡åŽè§¦å‘
        onTransitionEnd() {
            // å¦‚果已经是结束的状态,无需再处理
            if (this.transitionEnded) return
            this.transitionEnded = true
            // å‘出组件动画执行后的事件
            this.$emit(this.status === 'leave' ? 'afterLeave' : 'afterEnter')
            if (!this.show && this.display) {
                this.display = false
                this.inited = false
            }
        }
    }
}