关于逻辑拆分传递值

来源:12-5 城市列表页改造(构建更好的可复用性)

见信

2020-10-22

<template>
    <div class="wrap" ref="wrap">
        <div 
            @touchstart="handleTouchStart"
            @touchmove="handleTouchMove"
            @touchend="handleTouchEnd"
            :ref="elem => list = elem"
        >
            <div class="pulldown-wrapper">
                <div v-if="beforePullDown" key="beforePullDown">
                    <span>下拉刷新页面</span>
                </div>
                <div v-show="!beforePullDown" key="pullDown">
                    <div v-show="isPullingDown" key="loading">
                        <span>正在加载数据</span>
                    </div>
                    <div v-show="!isPullingDown" key="loadingSuccess">
                        <span>加载成功</span>
                    </div>
                </div>
            </div>
            <!-- 新闻列表 -->
            <div class="container">
                <universalItem v-for="item of data.data" :key="item.uniquekey" :data="item">{{item}}</universalItem>
            </div>
            <!-- 上拉提示 -->
            <div class="pullup-tips">
                <div v-if="!isPullUpLoad" class="before-trigger">
                    <span class="pullup-txt">上拉加载更多</span>
                </div>
                <div v-else class="after-trigger">
                    <span class="pullup-txt">Loading...</span>
                </div>
            </div>
        </div>
        <!-- 返回顶部按钮 -->
        <back-top-btn ref="backToTop" @click="handleBack"/>
    </div>
</template>

<script>
import Bscroll, { PullUpLoad } from 'better-scroll'
import { ref, onMounted ,computed, reactive, watch} from 'vue'
import { useStore } from "vuex"
import universalItem from 'common/universalItem/index'
import backTopBtn from 'common/backTopBtn'
import {
        getRem,
        getScrollTop,
        getScrollHeight,
        getWindowHeight,
        handleScroll,
        getPageWidth,
        useGetData
        } from'tools/LJXtools'
export default {
    name:"universalPage",
    components:{
        universalItem,
        backTopBtn
    },
    setup(props){
        const store = useStore()
        const currentCategory = store.state.currentCategory.char
        const list = ref(null)
        const data = reactive({
                        data:[]
                    })
        // 获取数据
        function getData() {
            const params = {
                    type:currentCategory,
                    key:"6f9bb8b1a8bcfd390aa50b125314010c"
                }
            // const url = '/toutiao/index'
            const url = '/api/'+currentCategory+'.json'
            return useGetData(url,params)            
        }

        // 数据初始化
        getData()
        .then((res)=>{
            data.data = res.data.result.data
            console.log("新闻条数:"+data.data.length)
            const length = data.data.length
            console.log(data.data[length-1])
            return res
        })

        // touch行为
        const { handleTouchStart,handleTouchEnd,handleTouchMove } = useHandleTouchLogic(store)
        // better-scroll行为
        const { beforePullDown,isPullingDown,isPullUpLoad,wrap,bs } = useBetterScrollLogic(data,getData,currentCategory)
        
        // 回到顶部逻辑
        function handleBack(){
            console.log(bs) //bs在mounted之前,未被赋值,依旧为null
        }

        return { 
                beforePullDown,isPullingDown,isPullUpLoad,wrap,
                handleTouchStart,handleTouchMove,handleTouchEnd,
                list,data,handleBack
                }
    }
}

// touch行为逻辑
function useHandleTouchLogic(store){
    let pageWidth = getPageWidth()
    let touchStatus = false
    let startX = 0
    let isLoading = false
    let timer = null
    function handleTouchStart (e) {
        touchStatus = true
        startX = e.touches[0].clientX
    }

    function handleTouchEnd () {
        touchStatus = false
        isLoading = false
    }
    function handleTouchMove (e) {
        const scrollTop = getScrollTop()
        if(isLoading) return
        if (touchStatus) {
            if (timer) {
                clearTimeout(timer)
                timer = null
            }
            
            timer = setTimeout(() => {
                // 当横向滚动超过多少时执行
                    // 左滑切页
                if(startX-e.touches[0].clientX>pageWidth*0.4){
                    console.log("左滑")
                    store.commit('prevCategory')
                }else if(e.touches[0].clientX-startX>pageWidth*0.4){
                    // 右滑切页
                    isLoading = true
                    console.log("右滑")
                    store.commit('nextCategory')
                }
                // console.log("startX:"+startX,"touches:"+e.touches[0].clientX,startX-e.touches[0].clientX)
                // console.log(startX)
            }, 8)
        }            
    }
    return { handleTouchStart,handleTouchEnd,handleTouchMove }
}

// 基于better-scroll的滚动加载与下拉刷新
function useBetterScrollLogic(data,useGetData) {
    let beforePullDown = ref(true)
    let isPullingDown = ref(false)
    let isPullUpLoad = ref(false)
    let htmlRem = getRem()
    const wrap = ref(null)
    let bs = null
    let backToTop = ref(null)
    let loadingState = false
    onMounted(() => {
        console.log("rem:"+htmlRem)
        bs = new Bscroll(wrap.value, {
            click: true,
            pullUpLoad:true,
            scrollY:true,
            scrollbar:true,
            bounceTime:800,
            pullDownRefresh:{
                threshold:150,
                stop:70
            }
        })
        // 上拖加载更多
        bs.on('pullingUp',pullingUpHandler)
        async function pullingUpHandler() {
            console.log("trigger pullUp")
            // 显示:上拉加载更多
            isPullUpLoad.value = true
            await pullingUpRequestData()
            bs.finishPullUp()
            bs.refresh()
            // 显示:loading
            isPullUpLoad.value = false
        }
        async function pullingUpRequestData() {
            try {
                pullingUpAjaxGet(/* url */)
            } catch (err) {
                // handle err
                console.log(err)
            }
        }
        function pullingUpAjaxGet(/* url */) {
            useGetData()
            .then((res)=>{
                setTimeout(()=>{
                    data.data = data.data.concat(res.data.result.data)
                    console.log("新闻条数:"+data.data.length)
                    const length = data.data.length
                    console.log(data.data)
                },1000)
            })
            .catch((err)=>{
                alert(err)
                return
            })
        }
        // 下拉刷新
        bs.on('pullingDown',pullingDownHandler)
        async function pullingDownHandler() {
            console.log('trigger pullDown')
            beforePullDown.value = false
            isPullingDown.value = true
            await pullingDownRequestData()
            isPullingDown.value = false
            finishPullDown()
        }
        async function finishPullDown() {
            await new Promise(resolve => {
                bs.finishPullDown()
                resolve()
            })
            setTimeout(() => {
                beforePullDown.value = true
                bs.refresh()
            },2000)
        }
        async function pullingDownRequestData() {
            pullingDownAjaxGet()
        }
        function pullingDownAjaxGet(/* url */) {
            useGetData()
            .then((res)=>{
                data.data = [...res.data.result.data]
                console.log("新闻条数:"+data.data)
                return res
            })
        }
        console.log(bs) //在mounted内,bs已被赋值,能正确获取到bs
    })
    console.log(bs) //在mounted外面获取到的bs为null,mounted此时还未被执行
    return { beforePullDown,isPullingDown,isPullUpLoad,wrap,bs }
}
</script>

<style lang="stylus" scoped>
    .wrap
        position absolute
        top 4.05rem
        left 0
        right 0
        bottom 0
        overflow hidden
        font-size 1.25rem
        .pulldown-wrapper
            position absolute
            width 100%
            padding 0.5rem 0.5rem 0 0.5rem
            box-sizing border-box
            transform translateY(-100%) translateZ(0)
            text-align center
            color #999
        .pullup-tips
            width 100%
            box-sizing border-box 
            padding 0.5rem
            text-align center
            color #999
        .container
            min-height 37.5rem
</style>

我把代码都复制上来了,现在betterScroll运行良好,我想要在setup里完成handleBack逻辑,该怎么做?如果我要把这个点击逻辑拆分出去又该怎么做?
setup毕竟是组件初始化调用 ,然后mounted后bs才被赋值,如果我将handleBack逻辑放在mounted里,setup里return handleBack的话,此时由于mounted还未被执行,handleBack是找不到的,是引用错误的。
这方面涉及到了程序运行时,我需要保持bs能时时更新,试过了watch bs,但是依然是null,该如何处理?

写回答

2回答

Dell

2020-10-31

在 setup里面,你可以写 mount 钩子,你可以在那个钩子里把betterScroll创建出来

onMount()

0
0

Dell

2020-10-25

你把 initBscroll 里面的代码,都先放回setup中,看下正常了没,然后贴图我告诉你继续怎么改

0
1
见信
老师,我修改了一下,把我的代码放上来了
2020-10-25
共1条回复

Vue2.5-2.6-3.0开发去哪儿网App 零基础入门到实战

课程紧跟Vue3版本迭代,企业主流版本Vue2+Vue3全掌握

10675 学习 · 8191 问题

查看课程