微信小程序之scroll-view swiper swiper-item

微信小程序之入门篇:粘性定位,json-server,scroll-view、swiper、swiper-item

前言

本文将会去探索微信小程序的三个标签scroll-viewswiperswiper-item的用途,将它们搭配起来使用做成视频和直播等软件常见的业务场景,效果如图所示。源码地址:github。(大佬可跳过)

效果图

页面部分

1、scroll-view

scroll-view一般用于可滚动视图区域,所以广泛用于导航菜单栏等业务场景。

<scroll-view class="hy-unlogin-navbar" enable-flex="true" scroll-x="true" scroll-left="{{navScrollLeft}}" scroll-with-animation="true" scroll-anchoring="true">
        <block wx:for="{{navtabs}}"
        wx:for-index="id"
        wx:key="index">
            <view class="navbar-item {{currentTab == id ?'active':''}}" 
            data-current="{{id}}"
            bindtap="switchNav"
            >
                {{item.nameText}}
            </view>
        </block>
 </scroll-view>

2、swiper与swiper-item

swiper与swiper-item是一对标签,一般搭配使用用于轮播图等业务场景。

<swiper class="tab-box" style="height: {{conHeight}}rpx;" current="{{currentTab}}" bindchange="switchTab" skip-hidden-item-layout="true">
      <swiper-item class="tab-express" wx:for="{{navCont}}" wx:key="index">
                <view class="hy-allLives-content">
                    <view class="hy-allLives-content-small" wx:for="{{navCont[index]}}" wx:key="index" data-id="{{item.id}}" bindtap="gotoDetail">
                        <image src="{{item.image}}"></image>
                        <view class="hy-allLives-content-text">
                            <text>{{item.descText}}</text>
                        </view>
                    </view>
                </view>
      </swiper-item>
</swiper>

js部分

数据放在.js文件中,用module.exports抛出,在index.js中用require引入。

const navCont = require('../../assets/db/tabs2')

通过点击事件引起currentTab的值变化从而改变swiper标签的current属性值变化,从而实现导航栏与之对应内容之间的切换。这是实现导航栏切换的其中一种方式,另外一种实现方式是采用WeUI(一套同微信原生视觉体验一致的基础样式库)的Navbar的思想。想体验一下weui的视觉效果,请点击WeUI,Navbar的wxml源码

注意:由于weui最近更新了版本至v2.3.0,上述Navbar所涉及的版本是v2.0.1。

另一种实现具体代码如下

<scroll-view id="navfix" scroll-x="true" scroll-with-animation="true" enable-flex="true" scroll-left="{{navScrollLeft}}"
    class="hy-navbar {{isfixed ? 'hy-navbar-fix' : ''}}">
        <block wx:for="{{navtabs}}" wx:key="index">
            <view data-id="{{item.id}}" data-index="{{index}}" bindtap="switchTab" 
            class="hy-navbar__item {{curId === item.id ? 'on' : ''}}">
                <view class="hy-navbar__tilte">{{item.nameText}}</view>
            </view>
        </block>
</scroll-view>
<view class="hy-allLives">
        <view class="hy-allLives-content">
            <view class="hy-allLives-content-small" wx:for="{{allLives}}" 
            hidden="{{curId == 'all' ? '' : (curId != item.categoryId)}}" 
            bindtap="gotoDetail" data-id="{{item.id}}">
                <image src="{{item.image}}"></image>
                <view class="hy-allLives-content-text">
                    <text>{{item.descText}}</text>
                </view>
            </view>
        </view>
</view>

这种实现方式的原理就是不是此分类页面下的内容就隐藏掉。但此方式并不能实现滑动切换菜单(可能是我太菜了,可根据需求选择),因此采用第一种方式通过给swiper绑定bindchange属性添加change事件,每当用户水平滑动页面时,触发change事件,监听change事件从事件参数中获取current值,并赋值给currentTab,从而达到滑动切换菜单的效果。

可能会踩的“坑”

在你使用scroll-view和swiper时,会出现swiper-item中的内容超出可视范围,无法上下滑动的问题,如何解决呢?首先想到的是swiper高度自适应

const conHeight = Math.ceil(navCont[idx].length / 2) * 290

idx是从事件参数中获取的值,并且会赋值给currentTab。Math.ceil()是向上取整的方法,Math.round()四舍五入的方法并不合适,因为(navCont[idx].length / 列数)只要除不尽就得往上加1。

高亮(被选中)菜单始终在可视区域内

/**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    let w = wx.getSystemInfoSync().windowWidth // 获取窗口宽度
    console.log(w)
    this.setData({
      windowWidth: w
    })
  }
  switchNav (e) {
    // console.log(e)
    let idx = e.currentTarget.dataset.current
    var singleNavWidth = this.data.windowWidth / 8
    this.setData({
      currentTab: idx,
      navScrollLeft: (idx - 1) * singleNavWidth
    })
  }
  switchTab (e) {
    // console.log(e)
    var singleNavWidth = this.data.windowWidth / 8
    if (e.detail.source == 'touch') {
      this.setData({
        currentTab: e.detail.current,
        navScrollLeft: (e.detail.current - 1) * singleNavWidth
      })
    }
  }

导航栏粘性定位

1、监听scroll事件
// 实时监控滚动距离顶部的位置
  onPageScroll: function (e) {
    // console.log(e)
    this.setData({
      scrollTop: e.scrollTop
    })
    var that = this // this作用域不会改变,可不指定
    if (e.scrollTop >= that.data.topheight + that.data.height) {
      that.setData({
        isfixed: true
      })
    } else if (e.scrollTop < that.data.topheight + that.data.height) {
      that.setData({
        isfixed: false
      })
    }
  }

通过实时监控距离顶部的位置当大于某一临界值时,就让导航栏通过position:fixed属性固定在某一位置,从而达到粘性定位效果。(添加类名实现,否则则取消。缺点:不是太顺滑,会闪现一下,需要优化

临界值你可以根据自己需要定义,也可以用微信小程序自带的方法获取。wx.createSelectorQuery().select()选取所需要定位的元素节点,然后分别获取当前元素节点距离页面顶部的高度以及自身的高度。

/**
   * 生命周期函数--监听页面显示
   */
onShow: function () {
  wx.createSelectorQuery().select('#navfix')
    .boundingClientRect( rect =>{
      // console.log(rect) 
      this.setData({
        topheight: rect.top,
        height: rect.height
      })
    }).exec();
}
2、CSS3新属性position:sticky

在所需要定位的元素节点的css中加上position:sticky;top:0;

top指的是当前元素节点定位时距离页面顶部的高度(位置),但此属性有个缺点,兼容性不太好,但在微信小程序中还是可以的。有关更多此属性的兼容性问题和“坑”,请看 position: sticky 详解(防坑指南)这篇文章。

提出问题


以上两种方法虽然实现了所需的导航菜单栏效果,但是数据这一块都是全部一次性请求回来,然后根据数组下标或隐藏来实现相关内容的切换效果。但是一旦数据过于庞大,一次性请求全部数据回来就会造成浏览器性能消耗过大甚至页面卡顿,显然在实际情况中这是不可行的。实际情况中肯定是页面切换到哪个菜单就会向后端去请求哪个菜单的相应数据回来,那没有服务器又该咋实现呢?


使用json-server

本文采用了一种“投机取巧”的办法,使用json-server这个Node模块来模拟一下数据的请求,json-server可以直接把一个json文件直接托管成一个简易的web服务器。具体操作流程如下:

  1. 新建一个文件夹,然后npm install json-server安装这个模块。
  2. 在此文件夹下新建一个.json格式的文件。


    内容格式
  3. 启动该服务,把package.json中的scripts改成"dev": "json-server db.json",然后使用命令npm run dev启动即可(默认启动在3000端口上),如果此命令失效,换成.\node_modules.bin\json-server .\db.json,这个命令是一定有效的,db是文件名。
"scripts": {
    "dev": "json-server db.json"
}

至此,一个简易的模拟服务器就搭建而成了,此时去前端页面请求数据即可。

/**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    wx.request({
      url: 'http://localhost:3000/navData', //菜单选项
      success: (res) => {
        // console.log(res.data)
        this.setData({
          navtabs: res.data
        })
      }
    })
  },
/**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.requestCart(this.data.currentTab) // 默认显示菜单
    let w = wx.getSystemInfoSync().windowWidth // 获取窗口宽度
    console.log(w)
    this.setData({
      windowWidth: w
    })
  },
switchNav (e) {
    let idx = e.currentTarget.dataset.current
    var singleNavWidth = this.data.windowWidth / 8
    this.setData({
      currentTab: idx,
      navScrollLeft: (idx - 1) * singleNavWidth
    })
    this.requestCart(idx)
  },
  switchTab (e) {
    var singleNavWidth = this.data.windowWidth / 8
    if (e.detail.source == 'touch') {
      this.setData({
        currentTab: e.detail.current,
        navScrollLeft: (e.detail.current - 1) * singleNavWidth
      })
    }
    this.requestCart(e.detail.current)
  },
  requestCart(idx) { // 模拟向后端接口发起请求
    wx.request({
      url: `http://localhost:3000/${idx}`,
      success: (res) => {
        // console.log(res.data)
        const conHeight = Math.ceil(res.data.length / 2) * 290
        this.setData({
          allLiveCont: res.data,
          conHeight: conHeight
        })
      }
    })
  }

注意:这里可能会遇到数据请求不回来,这时一般是遇到了跨域问题。在详情=>本地设置=>勾选不校验合法域名即可解决。附:前端常见跨域解决方案

解决跨域

结语

本文(第一次写)是一篇随笔,算是微信小程序的入门篇,希望对各位有所帮助。如果文中有什么错误或者不足之处,欢迎大家斧正!如果各位对某处知识点有什么更好的建议,欢迎留言,前端小白在线求教^^!

如果你喜欢这篇文章或者可以帮到你,不妨点个赞吧!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容