手把手撸一个SF思否小程序

283 阅读5分钟

最近开始将自己写的一些小程序开源到GitHub上面,为的是更好检验自己的编程能力,为自己后面的开源项目走出一条新的道路。

我们先看看我的小程序首页效果图



主要功能:我的订阅和近期热门和最新内容支持左右滑动,模仿SF思否app交互式,嵌入一个swiper和N个scroll-view这样我们就可以分开视图滚动和切换视图。

以下是核心代码

<view class='index_swiper'>
    <swiper bindchange="changSwiper" current="{{ indexValue }}" style="height:calc(100vh - {{paddingValue}}px)">
      <block wx:for="{{ containerData }}" wx:key="container{{ index }}">
        <swiper-item>
          <scroll-view scroll-y style="height:inherit" bindscrolltolower="scrolltolower" data-index='{{ index }}'>
            <view class='index_swiper_box' id="{{ item.name }}">
              <block wx:for="{{ item.data }}" wx:key="item{{ index }}">
                <homeModule></homeModule>
              </block>
           </view>
          </scroll-view>
        </swiper-item>
      </block>
    </swiper>
  </view>

height:calc(100vh - {{paddingValue}}px)的意思是获取屏幕高度减去头部搜索加选择的头部就可以得出我们swiper的高度,由于我们想做到多个滑动视图,我们需要去通过数据进行配置

  tabData: [{
        text: "我的订阅"
      },
      {
        text: "近期热门"
      },
      {
        text: "最新内容"
      },
    ],

这个是配置选择的头部

 containerData: [{
        name: 'subscribe',
        data: [1, 2, 3]
      },
      { 
       name: 'hot', 
       data: [1, 2, 3, 5, 6, 5, 6, 5]
      },
      {
        name: 'newest',
        data: [1, 2, 3, 6, 5]
      }
    ]
  },

这个是配置scroll-view的数量 name:求换到第几个的id类似于锚点  data是数据,因为我们没有服务端,就只能写一个组件通过data去渲染数据。

核心js代码:

  selectOne: function(e) {
    //用于用户用户使用滑动切换触发头部对用位置更新
    this.setData({
      indexValue: e.currentTarget.dataset.index,
    });
  },//用于点击选择的头部切换到相应的位置

  changSwiper: function(res) {
    if (res.detail.source == "touch") {
      this.setData({ 
       // 获取到当前侧滑的索引
        indexValue: res.detail.current,
      });
    }
  }, 

  scrolltolower:function(res){
    //用于scroll-view模拟用户滚动到底部,加载更多,因为我这边没有服务器,就只能用数组去模拟从服务器获取到数据
    var index = res.currentTarget.dataset.index;
    var data = [...this.data.containerData[index].data, ...[2, 5, 6, 8]]
    var name = `containerData[${index}].data`;
    console.log(name);
    this.setData({
      [name]: data
    })
  } 

这样我们就可以实现类似于掘金小程序上首页滑动切换视图


我的发现模块主要是一些组件嵌入进去,比较麻烦就是轮播图那块,我已经将他写成一个组件,为下个讲堂模块复用,这一块相信大家都可以实现的,我也把代码上传到GitHub上面,有兴趣的可以上去看看。

我们主要看看顶部那块标题,他的交互是根据你的滚动的位置去控制标题的字体大小和位置

我们看核心代码

<view class='navigation' style=' background-color:{{ color }}'>
  <view class='navigation_box'>
    <view class='navigation_box_return' bindtap='callBack'>
      <image src='./image/return.svg'></image>
    </view>
    <view class='navigation_box_image' bindtap='showSearch' wx:if="{{ search }}">
      <image src='./image/search.svg'></image>
    </view>
    <view class='navigation_box_image narrow' bindtap='showEdit' wx:if="{{ edit }}">
      <image src='./image/edit.svg'></image> 
   </view>
  </view>
  <view class='navigation_text' style='font-size:{{ defaultFace }}px;margin-top:{{ marginTop }}px; margin-left: {{ marginLeft }}px'>
    <text>{{ title }}</text>
  </view></view>

  properties: {
    title: {
      //接收传过来的标题名称
      type: String 
   },
    searchValue: {
      //接收传过来是否显示搜索按钮
      type: String,
      observer: function(newVal) {
        var flag = newVal == "false" ? false : true;
        this.setData({
          search: flag
        });
      }
    },
    editValue: {
      //接收传过来是否显示编辑按钮
      type: String,
      observer: function(newVal) {
        var flag = newVal == "false" ? false : true;
        this.setData({ 
         edit: flag
        }); 
     }
    }, 
   top: { 
     //接收传过来是否滚动的值 
     type: Number,
     observer: function(newVal, oldVal, changedPath) {
     this.setData({
          currentValue: newVal
        });
        var deviation = newVal - oldVal; //向下滚动的偏差值
        var devContrary = oldVal - newVal; //向上滚动的偏差值
        if (deviation > 0) {
          var mt = this.data.marginTop - deviation / 4 <= -25 ? -25 : this.data.marginTop - deviation / 4;
          var ml = this.data.marginLeft + deviation / 2.5 >= 50 ? 50 : this.data.marginLeft + deviation / 2.5;
          var faceValue = this.data.defaultFace - deviation / 10 <= 20 ? 20 : this.data.defaultFace - deviation / 10;
          if (this.data.currentValue <= 125) {            var colorValue = "transparent";
          } else {
            var colorValue = "#fff";
          }
       } else {
          if (this.data.currentValue <= 125) {
            var mt = this.data.marginTop + devContrary / 4 >= 10 ? 10 : this.data.marginTop + devContrary / 4;
            var ml = this.data.marginLeft + deviation / 2.5 <= 0 ? 0 : this.data.marginLeft + deviation / 2.5;
            var faceValue = this.data.defaultFace + devContrary / 10 >= 30 ? 30 : this.data.defaultFace + devContrary / 10;
            var colorValue = "transparent";
          } else {
            var mt = -25;
            var ml = 50;
            var faceValue = 20;
            var colorValue = "#fff";
          }
        } 
       this.setData({
          marginTop: mt,
          marginLeft: ml,
          defaultFace: faceValue,
          color: colorValue
        })
      }
    },    bgColor: {
      //接收传过来的背景颜色
      type: String,
      observer: function(newVal) {
        this.setData({
          color: newVal
        });
      }
    }
  },

我们通过接收值的方式,拿到相应导航栏的配置,接收滚动的位置,通过老值和新值相减来知道是向下滚动还是向上滚动,这样我们通过三元表达式来知道是否超出我们规定的一个值,因为我们滚动的值会越来越大,我们需要去除以一个整数来使得这个标题的变化更明显。


讲堂这个模块也是如此,好多的复用组件插入进来,这个部分很简单




消息模块是一个静态页面,由于时间问题,我现在没有开发


这是我的模块,里面大多数功能我已经实现好了,主要逻辑也是组件,文件配置等,这部分我会下章为大家详细讲解,由于开发周期才差不多一个月好多东西我都没有弄好,抱歉,能力有限,在后面的时间我会完善这些功能项目差不多有20多个页面和10几个组件,我觉得在这个项目中学到好多小程序的知识,特意写这篇文章给大家分享一下。

最后,附上项目的GitHub地址:SF思否小程序

文章转载请联系我:qq:652165177,请不要用于商业用途,如有版权问题请联系我!