04. 路由事件

Posted Ruovan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了04. 路由事件相关的知识,希望对你有一定的参考价值。


写在前面

  • 本文写了很多官网的API的相关知识点,可略过直接到官网查看

记第一个小程序DEMO

  • 名称:仿网易云音乐小程序
  • 接口:网易云音乐NodeJS版 API
  • 内容:主要实现轮播图、歌单推荐、排行榜、歌单显示、歌曲播放、歌词显示这几部分功能,其它暂未作考虑

  • 本文主要内容:实现首页排行榜部分、实现歌单点击功能
    在这里插入图片描述

接下来,我们实现排行榜部分,这部分没有新标签,只用了image标签、View标签、text标签

所以我们这里直接进行:请求数据、渲染数据


可以略过代码部分

01. 排行榜部分

  • 布局

    <!-- 歌曲排行榜部分 -->
    <view class="rankContainer">
        <view
              class="rank"
              wx:for="{{ rankData }}"
              wx:key="name"
              bindtap="handleTap"
              data-rankId="{{ item.rankId }}"
              >
            <view class="rank-image">
                <image
                       src="{{ item.rankImg }}"
                       mode="scaleToFill"
                       lazy-load="false"
                       ></image>
            </view>
            <view class="rank-music">
                <view
                      class="music-item"
                      wx:for="{{ item.tracks }}"
                      wx:for-item="musicItem"
                      wx:for-index="musicOrder"
                      wx:key="id"
                      >
                    <text decode>{{ musicOrder + 1 }}.&nbsp;</text>
                    <text>{{ musicItem.musicName }} - {{ musicItem.author }}</text>
                </view>
            </view>
        </view>
    </view>
    
  • 样式

    // 排行榜
    .rankContainer {
        height: 220rpx;
        .rank {
            display: flex;
            flex-direction: row;
            align-items: center;
            height: 100%;
            margin-bottom: 30rpx;
            // 左侧图片
            .rank-image {
                width: 220rpx;
                height: 220rpx;
                image {
                    width: 100%;
                    height: 100%;
                    border-radius: 20rpx;
                }
            }
            // 右侧歌曲排行
            .rank-music {
                flex: 1;
                display: flex;
                flex-direction: column;
                justify-content: space-around;
                padding-left: 20rpx;
                height: 100%;
    
                font-size: 26rpx;
                font-weight: 300;
                .music-item {
                    padding-right: 20rpx;
                    display: -webkit-box;
                    -webkit-box-orient: vertical;
                    -webkit-line-clamp: 1;
                    overflow: hidden;
                    text-overflow: ellipsis;
                }
            }
        }
    }
    
  • 请求

    // 获取排行榜
    getRank() {
        let index = 0
        let rankList = []
        // 只取4个排行榜
        while (index < 4) {
            // idx 表示排行榜的id值
            request('/top/list', { idx: index++ }).then(res => {
                if (res.code === 200) {
                    // 排行榜id--后面根据id获取排行榜数据
                    let rankId = res.playlist.id
                    // 排行榜名称
                    let rankName = res.playlist.name
                    // 排行榜图片
                    let rankImg = res.playlist.coverImgUrl
                    // 排行榜前3的歌曲
                    let tracks = res.playlist.tracks.slice(0, 3)
    
                    // 从歌曲中取出我们想要的数据:歌名、作者
                    let tracksArr = []
                    if (tracks) {
                        tracks.forEach(element => {
                            // ar--歌曲作者,可以有多个,需要拼接
                            let authorArr = []
                            if (element.ar) {
                                for (let item of element.ar) {
                                    authorArr.push(item.name)
                                }
                            }
                            // 这是我们取出的数据
                            let obj = {
                                musicName: element.name, // 歌曲名
                                author: authorArr.join('/'), // 拼接歌曲作者
                            }
                            // 将前3的歌曲存入歌曲数组中
                            tracksArr.push(obj)
                        })
                    }
                    // 这个是我们获取的当前排行榜的名称和前3的歌曲
                    let rankListItem = {
                        rankId,
                        rankName,
                        rankImg,
                        tracks: tracksArr,
                    }
                    // 存入排行榜数组中
                    rankList.push(rankListItem)
                    // console.log(rankList)
                    this.setData({
                        rankData: rankList, // 将排行榜数组数据复制给页面中的数据
                    })
                }
            })
        }
    },
    

然后,我们需要实现的是点击排行榜、点击推荐歌单,可以跳转到相应的歌单页面

所以,我们来看看小程序的路由跳转


02.路由跳转

只作简要介绍,详见官网路由

  • wx.navigateTo()

    • 保留页面跳转,会将当前页面推入页面栈中,然后再跳转到目标页面
  • wx.redirectTo()

    • 关闭当前页面,然后跳转到应用内的某个页面。但是不能跳转到 tabbar 页面
  • wx.switchTab()

    • 跳转到Tab栏的页面需要使用这个API,跳转时,会关闭其它所有非tabBar页面
  • wx.relaunch()

    • 关闭所有页面,打开目标页面
  • wx.navigateBack()

    • 关闭当前页面,返回上一页面或多级页面,可用过delta指定返回几层
  • EventChannel

    • 页面间事件通信通道
    • eventChannel.emit():触发一个事件
    • eventChannel.on:持续监听一个事件
    • eventChannel.once():监听一次事件后失效
    • eventChannel.off():取消监听一个事件
  • wx.navigateToMiniProgram()

    • 打开另一个小程序
  • wx.navigateBackMiniProgram()

    • 返回到上一个小程序。只有在当前小程序是被其他小程序打开时可以调用成功
  • wx.exitMiniProgram()

    • 退出当前小程序
  • 示例代码

    • 小程序中直接进行页面的跳转,不需要额外配置路由

      wx.navigateTo({    
          url: '/pages/index/index'
      })
      
    • 路由传参

      • 对参数长度有限制
      wx.navigateTo({    
          url: '/pages/index/index?' + id
      })
      

然后我们再回顾下小程序的事件绑定


04. 事件绑定

详见官网事件

(1)事件类型

  • touchstart:手指开始触摸

  • ``touchmove`:手指触摸后开始移动

  • touchcancel:手指触摸时被打断

  • touchend:手持触摸结束、

  • tap:手指点击

  • longtaplongpress:手指长按,建议使用longpress

    注:以上事件都会冒泡

(2)事件绑定方式

  • 使用bind来绑定事件

  • 也可以用 catch 来绑定事件

    • bind 不同的是, catch 会阻止事件向上冒泡
  • 还可以使用 mut-bind 来绑定事件

    • 所有mut-bind事件是互斥的,有多个时,只会有一个事件被触发
  • 如果需要在捕获阶段监听事件,可以使用capture-bindcapture-catch

关于冒泡:(html类似,应该不会陌生

  • 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。

  • 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。

<view bindtap="handleTap"></view>
<view bind:tap="handleTap"></view>

<view catchtap="handleCatch"></view>
<view catch:tap="handleCatch"></view>

<view mut-bind:tap="handleMutTap"></view>

(3)事件对象

  • type:当前事件类型

  • timeStamp:当前事件触发时间戳

  • target:触发当前事件的源组件的一些属性的集合

  • currentTarget:当前事件绑定的组件的一些属性的集合

    targetcurrentTarget中的dataset可以获取到组件传递的参数

  • mark:标记触发事件的具体的组件的target节点


  • detail:当前事件触发携带的额外信息
  • touches:触摸事件,当前停留在屏幕中的触摸点信息的数组
  • changedTouches:触摸事件,当前变化的触摸点信息的数组

接下来,我们开始给歌单和排行榜加上点击事件,并路由到歌单详情页面


05. 歌单点击事件

  • 这里只举例,具体绑定元素结合实际场景
<view bindtap="handleTap" data-rankId="{{ item.id }}"></view>
  • 这里将id作为参数传递给handleTap事件

注意dataset绑定的参数名,即使是大写的,也会自动转换成小写的

如这里的data-rankId,在事件对象中实际得到的是rankid

而如果要使用这种驼峰命名形式的参数,即有多个单词组成的参数名

需要使用短横线-连接,即data-rank-id

那么,此时在事件对象中得到的值就是 rankId

// 首页歌曲点击事件--获取歌曲id
handleTap(e) {
    console.log(e) // 打印所有事件对象
    // 注意这里的 rankId是 rankid
    let id = e.currentTarget.dataset.rankid // 获取歌单id
    wx.navigateTo({
        url: '/pages/rankList/rankList?id=' + id, // 传递歌单id  
        success: () => {
            console.log('成功传入')
        },
        fail: () => {
            console.log('路由失败')
        },
    })
},

以上是关于04. 路由事件的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段11——vue路由的配置

如何让自定义视图观察包含片段的生命周期事件而不是活动?

04. 路由事件

04. 路由事件

为啥片段中的晶圆厂不响应点击事件?

Express实战 - 应用案例- realworld-API - 路由设计 - mongoose - 数据验证 - 密码加密 - 登录接口 - 身份认证 - token - 增删改查API(代码片段