1***@qq.com
1***@qq.com
  • 发布:2023-03-04 15:19
  • 更新:2023-03-04 15:19
  • 阅读:271

【报Bug】微信小程序自定义组件,编译成app报错。有bind开头的事件,有双引号包裹的,如wxs场景的,不需要编译成$self()包裹

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: macOS 13

HBuilderX类型: 正式

HBuilderX版本号: 3.7.3

手机系统: iOS

手机系统版本号: iOS 16

手机厂商: 苹果

手机机型: iPhone 14 Pro

页面类型: vue

vue版本: vue2

打包方式: 云端

项目创建方式: HBuilderX

示例代码:

wxml

````  
    <!-- slide-view/slide-view.wxml -->  
    <wxs module="handler" src="./slideview.wxs"></wxs>  
    <view class="weui-slideview weui-movable-view {{icon ? 'weui-slideview_icon' : ''}} {{extClass}}" style="width: 100%;height: 100%;">  
        <view bindtransitionend="{{handler.transitionEnd}}"  
        show="{{show}}" change:show="{{handler.showChange}}"  
        rebounce="{{rebounce}}" change:rebounce="{{handler.rebounceChange}}"  
        duration="{{duration}}" change:duration="{{handler.durationChange}}"  
        change:disable="{{handler.disableChange}}" disable="{{disable}}"  
        change:prop="{{handler.sizeReady}}" prop="{{size}}"  
        bindtouchstart="{{handler.touchstart}}" bindtouchmove="{{handler.touchmove}}" bindtouchend="{{handler.touchend}}" class="weui-slideview__left left" style="width:100%;">  
        <slot></slot>  
        </view>  
        <view class="weui-slideview__right right">  
        <view class="weui-slideview__buttons" style="height:100%;width:100%;" wx:if="{{buttons && buttons.length}}">  
            <view wx:for="{{buttons}}" wx:key="index" class='btn weui-slideview__btn__wrp {{item.className}}'>  
            <view  
                bindtap="{{handler.hideButton}}"  
                data-data="{{item.data}}"  
                data-index="{{index}}"  
                class='weui-slideview__btn {{item.extClass}}'  
                aria-role="button"  
            >  
                <text wx:if="{{!icon}}">{{item.text}}</text>  
                <image class="weui-slideview__btn__icon" wx:else src="{{item.src}}"/>  
            </view>  
            </view>  
        </view>  
        </view>  
    </view>  

````     

WXS

````  
    /* eslint-disable */  
    var touchstart = function(event, ownerInstance) {  
        var ins = event.instance  
        var st = ins.getState()  
        if (st.disable) return // disable的逻辑  
        // console.log('touchstart st', JSON.stringify(st))  
        if (!st.size) return  
        // console.log('touchstart', JSON.stringify(event))  
        st.isMoving = true  
        st.startX = event.touches[0].pageX  
        st.startY = event.touches[0].pageY  
        st.firstAngle = 0  
    }  
    var touchmove = function(event, ownerInstance) {  
        var ins = event.instance  
        var st = ins.getState()  
        if (!st.size || !st.isMoving || st.disable) return  
        // console.log('touchmove', JSON.stringify(event))  
        var pagex = event.touches[0].pageX - st.startX  
        var pagey = event.touches[0].pageY - st.startY  
        // 左侧45度角为界限,大于45度则允许水平滑动  
        if (st.firstAngle === 0) {  
            st.firstAngle = Math.abs(pagex) - Math.abs(pagey)  
        }  
        if (st.firstAngle < 0) {  
            return  
        }  
        var movex = pagex > 0 ? Math.min(st.max, pagex) : Math.max(-st.max, pagex)  
        // 往回滑动的情况  
        if (st.out) {  
            // 已经是划出来了,还要往左滑动,忽略  
            if (movex < 0) return  
            ins.setStyle({  
                'transform': 'translateX(' + (st.transformx + movex) + 'px)',  
                'transition': ''  
            })  
            var btns = ownerInstance.selectAllComponents('.btn')  
            var transformTotal = 0  
            var len = btns.length  
            var i = len - 1;  
            for (;i >= 0; i--) {  
                var transform = st.size.buttons[i].width / st.max * movex  
                var transformx = st.size.buttons[i].max - Math.min(st.size.buttons[i].max, transform + transformTotal)  
                btns[i].setStyle({  
                    'transform': 'translateX(' + (-transformx) + 'px)',  
                    'transition': ''  
                })  
                transformTotal += transform  
            }  
            return false  
        }  
        if (movex > 0) movex = 0  
        ins.setStyle({  
            'transform': 'translateX(' + movex + 'px)',  
            'transition': ''  
        })  
        st.transformx = movex  
        var btns = ownerInstance.selectAllComponents('.btn')  
        var transformTotal = 0  
        var len = btns.length  
        var i = len - 1;  
        for (;i >= 0; i--) {  
            var transform = st.size.buttons[i].width / st.max * movex  
            var transformx = Math.max(-st.size.buttons[i].max, transform + transformTotal)  
            btns[i].setStyle({  
                'transform': 'translateX(' + transformx + 'px)',  
                'transition': ''  
            })  
            st.size.buttons[i].transformx = transformx  
            transformTotal += transform  
        }  
        return false // 禁止垂直方向的滑动  
    }  
    var touchend = function(event, ownerInstance) {  
        var ins = event.instance  
        var st = ins.getState()  
        if (!st.size || !st.isMoving || st.disable) return  
        // 左侧45度角为界限,大于45度则允许水平滑动  
        if (st.firstAngle < 0) {  
            return  
        }  
        var duration = st.duration / 1000  
        st.isMoving = false  
        // console.log('touchend', JSON.stringify(event))  
        var btns = ownerInstance.selectAllComponents('.btn')  
        var len = btns.length  
        var i = len - 1  
        // console.log('len size', len)  
        if (Math.abs(event.changedTouches[0].pageX - st.startX) < st.throttle || event.changedTouches[0].pageX - st.startX > 0) { // 方向也要控制  
            st.out = false  
            ins.setStyle({  
                'transform': 'translate3d(0px, 0, 0)',  
                'transition': 'transform ' + (duration) + 's'  
            })  
            for (;i >= 0; i--) {  
                btns[i].setStyle({  
                    'transform': 'translate3d(0px, 0, 0)',  
                    'transition': 'transform ' + (duration) + 's'  
                })  
            }  
            ownerInstance.callMethod('hide')  
            return  
        }  
        showButtons(ins, ownerInstance, duration)  
        ownerInstance.callMethod('show')  
    }  
    var REBOUNCE_TIME = 0.2  
    var showButtons = function(ins, ownerInstance, withDuration) {  
        var st = ins.getState()  
        if (!st.size) return  
        var rebounceTime = st.rebounce ? REBOUNCE_TIME : 0  
        var movex = st.max  
        st.out = true  
        var btns = ownerInstance.selectAllComponents('.btn')  
        var rebounce = st.rebounce || 0  
        var len = btns.length  
        var i = len - 1  
        ins.setStyle({  
            'transform': 'translate3d(' + (-movex - rebounce) + 'px, 0, 0)',  
            'transition': 'transform ' + (withDuration) + 's'  
        })  
        st.transformx = -movex  
        var transformTotal = 0  
        for (;i >= 0; i--) {  
            var transform = st.size.buttons[i].width / st.max * movex  
            var transformx = (-(transform + transformTotal))  
            btns[i].setStyle({  
                'transform': 'translate3d(' + transformx + 'px, 0, 0)',  
                'transition': 'transform ' + (withDuration ? withDuration + rebounceTime : withDuration) + 's'  
            })  
            st.size.buttons[i].transformx = transformx  
            transformTotal += transform  
        }  
    }  
    var innerHideButton = function(ownerInstance) {  
        var ins = ownerInstance.selectComponent('.left')  
        var st = ins.getState()  
        if (!st.size) return  
        var duration = st.duration ? st.duration / 1000 : 0  
        var btns = ownerInstance.selectAllComponents('.btn')  
        var len = btns.length  
        var i = len - 1  
        ins.setStyle({  
            'transform': 'translate3d(0px, 0, 0)',  
            'transition': 'transform ' + (duration) + 's'  
        })  
        st.transformx = 0  
        st.out = false  
        for (;i >= 0; i--) {  
            btns[i].setStyle({  
                'transform': 'translate3d(0px, 0, 0)',  
                'transition': 'transform ' + (duration) + 's'  
            })  
            st.size.buttons[i].transformx = 0  
        }  
    }  
    var hideButton = function(event, ownerInstance) {  
        innerHideButton(ownerInstance)  
        ownerInstance.callMethod('buttonTapByWxs', {index: event.currentTarget.dataset.index, data: event.currentTarget.dataset.data})  
        return false  
    }  
    var sizeReady = function(newVal, oldVal, ownerInstance, ins) {  
        var st = ins.getState()  
        // st.disable = newVal && newVal.disable  
        if (newVal && newVal.button && newVal.buttons) {  
            st.size = newVal  
            st.transformx = 0  
            // var min = newVal.button.width  
            var max = 0  
            var len = newVal.buttons.length  
            var i = newVal.buttons.length - 1;  
            var total = 0  
            for (; i >= 0; i--) {  
                max += newVal.buttons[i].width  
                // if (min > newVal.buttons[i]) {  
                //     min = newVal.buttons[i].width  
                // }  
                total += newVal.buttons[i].width  
                newVal.buttons[i].max = total  
                newVal.buttons[i].transformx = 0  
            }  
            st.throttle = st.size.throttle || 40 // 固定值  
            st.rebounce = st.size.rebounce  
            st.max = max  
            ownerInstance.selectComponent('.right').setStyle({  
                'line-height': newVal.button.height + 'px',  
                left: (newVal.button.width) + 'px',  
                width: max + 'px'  
            })  
            // console.log('st size', JSON.stringify(newVal))  
            if (!st.size.disable && st.size.show) {  
                showButtons(ins, ownerInstance)  
            }  
        }  
    }  
    var disableChange = function(newVal, oldVal, ownerInstance, ins) {  
        var st = ins.getState()  
        st.disable = newVal  
    }  
    var durationChange = function(newVal, oldVal, ownerInstance, ins) {  
        var st = ins.getState()  
        st.duration = newVal || 400  
    }  
    var showChange = function(newVal, oldVal, ownerInstance, ins) {  
        var st = ins.getState()  
        st.show = newVal  
        if (st.disable) return  
        // console.log('show change')  
        if (st.show) {  
            showButtons(ins, ownerInstance, st.duration)  
        } else {  
            innerHideButton(ownerInstance)  
        }  
    }  
    var rebounceChange = function(newVal, oldVal, ownerInstance, ins) {  
        var st = ins.getState()  
        // console.log('rebounce', st.rebounce)  
        st.rebounce = newVal  
    }  
    var transitionEnd = function(event, ownerInstance) {  
        // console.log('transition')  
        var ins = event.instance  
        var st = ins.getState()  
        // 回弹效果  
        if (st.out && st.rebounce) {  
            // console.log('transition rebounce', st.rebounce)  
            ins.setStyle({  
                'transform': 'translate3d(' + (-st.max) + 'px, 0, 0)',  
                'transition': 'transform ' + REBOUNCE_TIME +'s'  
            })  
        }  
    }  
    module.exports = {  
        touchstart: touchstart,  
        touchmove: touchmove,  
        touchend: touchend,  
        hideButton: hideButton,  
        sizeReady: sizeReady,  
        disableChange: disableChange,  
        durationChange: durationChange,  
        showChange: showChange,  
        rebounceChange: rebounceChange,  
        transitionEnd: transitionEnd  
    }  
````     

JS

````  
    Component({  
        options: {  
            addGlobalClass: true,  
            multipleSlots: true  
        },  
        properties: {  
            extClass: {  
                type: String,  
                value: ''  
            },  
            buttons: {  
                type: Array,  
                value: [],  
                observer() {  
                    this.addClassNameForButton();  
                }  
            },  
            disable: {  
                type: Boolean,  
                value: false  
            },  
            icon: {  
                type: Boolean,  
                value: false  
            },  
            show: {  
                type: Boolean,  
                value: false  
            },  
            duration: {  
                type: Number,  
                value: 350  
            },  
            throttle: {  
                type: Number,  
                value: 40  
            },  
            rebounce: {  
                type: Number,  
                value: 0  
            }  
        },  
        data: {  
            size: null  
        },  
        ready() {  
            this.updateRight();  
            this.addClassNameForButton();  
        },  
        methods: {  
            updateRight() {  
                const data = this.data;  
                const query = wx.createSelectorQuery().in(this);  
                query  
                    .select('.left')  
                    .boundingClientRect((res) => {  
                    const btnQuery = wx.createSelectorQuery().in(this);  
                    btnQuery  
                        .selectAll('.btn')  
                        .boundingClientRect((rects) => {  
                        this.setData({  
                            size: {  
                                buttons: rects,  
                                button: res,  
                                show: data.show,  
                                disable: data.disable,  
                                throttle: data.throttle,  
                                rebounce: data.rebounce  
                            }  
                        });  
                    })  
                        .exec();  
                })  
                    .exec();  
            },  
            addClassNameForButton() {  
                const { buttons, icon } = this.data;  
                buttons.forEach((btn) => {  
                    if (icon) {  
                        btn.className = '';  
                    }  
                    else if (btn.type === 'warn') {  
                        btn.className = 'weui-slideview__btn-group_warn';  
                    }  
                    else {  
                        btn.className = 'weui-slideview__btn-group_default';  
                    }  
                });  
                this.setData({  
                    buttons  
                });  
            },  
            buttonTapByWxs(data) {  
                this.triggerEvent('buttontap', data, {});  
            },  
            hide() {  
                this.triggerEvent('hide', {}, {});  
            },  
            show() {  
                this.triggerEvent('show', {}, {});  
            },  
            transitionEnd() { }  
        }  
    });  
````     

操作步骤:

将上面的代码,写成js原生组件的形式,json和wxss不重要
编译成app,看编译成的vue组件里面的模板

预期结果:

有bind开头的事件,有双引号包裹的,如wxs场景的,不需要编译成$self()包裹

实际结果:
<template>  
<uni-shadow-root class="weui-components-slideview-slideview"><view :class="'weui-slideview weui-movable-view '+(icon ? 'weui-slideview_icon' : '')+' '+(extClass)" style="width: 100%;height: 100%;">  
    <view @transitionend="_$self[(handler.transitionEnd)||'_$noop']($event)" :show="show" :change:show="handler.showChange" :rebounce="rebounce" :change:rebounce="handler.rebounceChange" :duration="duration" :change:duration="handler.durationChange" :change:disable="handler.disableChange" :disable="disable" :change:prop="handler.sizeReady" :prop="size" @touchstart="_$self[(handler.touchstart)||'_$noop']($event)" @touchmove="_$self[(handler.touchmove)||'_$noop']($event)" @touchend="_$self[(handler.touchend)||'_$noop']($event)" class="weui-slideview__left left" style="width:100%;">  
      <slot></slot>  
    </view>  
    <view class="weui-slideview__right right">  
      <view class="weui-slideview__buttons" style="height:100%;width:100%;" v-if="buttons && buttons.length">  
        <view v-for="(item,index) in (buttons)" :key="item.index" :class="'btn weui-slideview__btn__wrp '+(item.className)">  
          <view @click="_$self[(handler.hideButton)||'_$noop']($event)" :data-data="item.data" :data-index="index" :class="'weui-slideview__btn '+(item.extClass)" aria-role="button">  
            <text v-if="(!icon)">{{item.text}}</text>  
            <image class="weui-slideview__btn__icon" v-else :src="item.src"></image>  
          </view>  
        </view>  
      </view>  
    </view>  
</view></uni-shadow-root>  
</template>  
<wxs module="handler" src="./slideview.wxs"></wxs>

bug描述:

小程序自定义组件,用了wxs,注册了一些事件[bind开头],需要用双引号包起来;这导致uni编译成app端的时候,多了一些@click="$self[(handler.hideButton)||'$noop']($event)" 导致事件就没有触发了!

2023-03-04 15:19 负责人:无 分享
已邀请:

要回复问题请先登录注册