本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP

要做微信小程序首先要对htmlcssjs有一定的基础,还有对微信小程序的API也要非常熟悉

我将该教程分为以下三篇

  1. 微信小程序开发日记——高仿知乎日报(上)
  2. 微信小程序开发日记——高仿知乎日报(中)
  3. 微信小程序开发日记——高仿知乎日报(下)

三篇分别讲不同的组件和功能块

这篇要讲

  • API分析
  • 启动页
  • 轮播图
  • 日报列表
  • 浮动按钮
  • 侧滑菜单

API分析

以下是使用到的具体API,更加详细参数和返回结构可参照网上网友分享的 知乎日报-API-分析 ,在此就不做再次分析了。

启动界面图片

http://news-at.zhihu.com/api/4/start-image/{size}

参数 说明
size 图片尺寸,格式:宽*高。例如: 768*1024

获取刚进入应用时的显示封面,可以根据传递的尺寸参数来获取适配用户屏幕的封面。

获取最新日报

http://news-at.zhihu.com/api/4/news/latest

返回的数据用于日报的首页列表,首页的结构有上下部分,上部分是图片滑动模块,用于展示热门日报,下部分是首页日报列表,以上接口返回的数据有热门日报和首页日报

获取日报详细

http://news-at.zhihu.com/api/4/news/{id}

参数 说明
id 日报id

在点击日报列表也的日报项时,需要跳转到日报详情页展示日报的具体信息,这个接口用来获取日报的展示封面和具体内容。

历史日报

http://news.at.zhihu.com/api/4/news/before/{date}

参数 说明
date 年月日格式时间yyyyMMdd,例如:20150903、20161202

这个接口也是用与首页列表的日报展示,但是不同的是此接口需要传一个日期参数,如20150804格式。获取最新日报接口只能获取当天的日报列表,如果需要获取前天或者更久之前的日报,则需要这个接口单独获取。

日报额外信息

http://news-at.zhihu.com/api/4/story-extra/{id}

参数 说明
id 日报id

在日报详情页面中,不仅要展示日报的内容,好需要额外获取此日报的评论数目和推荐人数等额外信息。

日报长评

http://news-at.zhihu.com/api/4/story/{id}/long-comments

参数 说明
id 日报id

日报的评论页面展示长评用到的接口(没有找到分页参数,分页没有做)

日报短评

http://news-at.zhihu.com/api/4/story/{id}/short-comments

参数 说明
id 日报id

日报的评论页面展示段评用到的接口(没有找到分页参数,分页没有做)

主题日报栏目列表

http://news-at.zhihu.com/api/4/themes

主页的侧边栏显示有主题日报的列表,需要通过这个接口获取主题日报栏目列表

主题日报具体内容列表

http://news-at.zhihu.com/api/4/theme/{themeId}

参数 说明
themeId 主题日报栏目id

在主页侧栏点击主题日报进入主题日报的内容页,需要展示此主题日报下的日报列表。

启动页

作为一个仿制知乎日报的伪APP,高大上的启动封面是必须的,哈哈。启动页面很简单,请求一个应用启动封面接口,获取封面路径和版权信息。当进入页面,在onLoad事件中获取屏幕的宽和高来请求适合尺寸的图片,在onReady中请求加载图片,在请求成果之后,延迟2s进入首页,防止页面一闪而过。

onLoad: function( options ) {
var _this = this;
wx.getSystemInfo( {
success: function( res ) {
_this.setData( {
screenHeight: res.windowHeight,
screenWidth: res.windowWidth,
});
}
});
}, onReady: function() {
var _this = this;
var size = this.data.screenWidth + '*' + this.data.screenHeight;
requests.getSplashCover( size, ( data ) => {
_this.setData( { splash: data });
}, null, () => {
toIndexPage.call(_this);
});
} /**
* 跳转到首页
*/
function toIndexPage() {
setTimeout( function() {
wx.redirectTo( {
url: '../index/index'
});
}, 2000 );
}

轮播图

首页顶部需要用到轮播图来展示热门日报,小程序中的Swipe组件可以实现。

<swiper class="index-swiper" indicator-dots="true" interval="10000">
<block wx:for="{{sliderData}}">
<swiper-item data-id="{{item.id}}" bindtap="toDetailPage">
<image mode="aspectFill" src="{{item.image}}" style="width:100%" />
<view class="mask"></view>
<view class="desc"><text>{{item.title}}</text></view>
</swiper-item>
</block>
</swiper>

所有的内容都必须要在swiper-item标签中,因为我们的图片不止有一张,而是有多个热门日报信息,需要用循环来展示数据。这里需要指定的是image里的属性mode设置为aspectFill是为了适应组件的宽度,这需要牺牲他的高度,即有可能裁剪,但这是最好的展示效果。toDetailPage是点击事件,触发跳转到日报详情页。在跳转到日报详情页需要附带日报的id过去,我们在循环列表的时候把当前日报的id存到标签的data中,用data-id标识,这有点类似与html5中的data-*API。当在这个标签上发生点击事件的时候,我们可以通过Event.currentTarget.dataset.id来获取data-id的值。

日报列表

列表的布局大同小异,不过这里的列表涉及到分页,我们可以毫不犹豫地使用scroll-view组件,它的scrolltolower是非常好用的,当组件滚动到底部就会触发这个事件。上次的小豆瓣图书也是使用了这个组件分页。不过这次的分页动画跟上次不一样,而是用一个附带旋转动画的刷新图标,使用官方的动画api来实现旋转。

<view class="refresh-block" wx:if="{{loadingMore}}">
<image animation="{{refreshAnimation}}" src="../../images/refresh.png"></image>
</view>

代码中有一个显眼的animation属性,这个属性就是用来控制动画的。

/**
* 旋转上拉加载图标
*/
function updateRefreshIcon() {
var deg = 360;
var _this = this; var animation = wx.createAnimation( {
duration: 1000
}); var timer = setInterval( function() {
if( !_this.data.loadingMore )
clearInterval( timer );
animation.rotateZ( deg ).step();
deg += 360;
_this.setData( {
refreshAnimation: animation.export()
})
}, 1000 );
}

当列表加载数据时,给动画设置一个时长duration,然后按Z轴旋转,即垂直方向旋转rotateZ,每次旋转360度,周期是1000毫秒。

列表的布局跟上次的小豆瓣图书的结构差不多,用到了循环结构wx:for和判断语句wx:if、 wx:else来控制不同的展示方向。

<view class="common-list">
<block wx:for="{{pageData}}">
<view class="list-item {{item.images[0] ? 'has-img': ''}}" wx:if="{{item.type != 3}}" data-id="{{item.id}}" bindtap="toDetailPage">
<view class="content">
<text>{{item.title}}</text>
</view>
<image wx:if="{{item.images[0]}}" src="{{item.images[0]}}" class="cover"></image>
</view>
<view class="list-spliter" wx:else>
<text>{{item.title}}</text>
</view>
</block>
</view>

class="list-spliter"这块是用来显示日期,列表中的日报只要不是同一天的记录,就在中间插入一条日期显示块。在列表项中有一个三元运算判断输出具体的class{{item.images[0] ? 'has-img': ''}},是因为列表中可能没有图片,因此需要判定当前有没有图片,没有图片就不添加class为has-img来控制带有图片列表项的布局。

浮动按钮

因为小程序中没有侧栏组件,无法做到侧滑手势显示侧栏(本人发现touchstart事件和tap事件有冲突,无法实现出手势侧滑判断,所以没有用侧滑手势,可能是本人理解太浅了,没有发现解决方法,嘿嘿…),浮动按钮的样式参照了Android中的FloatAction经典按钮。可以浮动在界面上,还可以滑动到任意位置,背景为稍微透明。

<view class="float-action" bindtap="ballClickEvent" style="opacity: {{ballOpacity}};bottom:{{ballBottom}}px;right:{{ballRight}}px;" bindtouchmove="ballMoveEvent">
</view>
.float-action {
position: absolute;
bottom: 20px;
right: 30px;
width: 50px;
height: 50px;
border-radius: 50%;
box-shadow: 2px 2px 10px #AAA;
background: #1891D4;
z-index: 100;
}

按钮的样式随便弄了一下,宽高用了px是因为后面的移动判断需要获取屏幕的宽高信息,这些信息的单位是px。wxml绑定了点击事件和移动事件,点击事件是控制侧栏弹出,滑动事件是按钮移动。

//浮动球移动事件
ballMoveEvent: function( e ) {
var touchs = e.touches[ 0 ];
var pageX = touchs.pageX;
var pageY = touchs.pageY;
if( pageX < 25 ) return;
if( pageX > this.data.screenWidth - 25 ) return;
if( this.data.screenHeight - pageY <= 25 ) return;
if( pageY <= 25 ) return;
var x = this.data.screenWidth - pageX - 25;
var y = this.data.screenHeight - pageY - 25;
this.setData( {
ballBottom: y,
ballRight: x
});
}

touchmove事件中的会传递一个event参数,通过这个参数可以获取到当前手势滑动到的具体坐标信息e.touches[ 0 ]

侧滑菜单

侧滑菜单是一个经典APP布局方案,小程序中没有提供这个组件,甚是遗憾。不过实现起来也不是很难,但是总感觉有点别扭…

侧滑菜单的样式采用了固定定位的布局position: fixed,默认隐藏与左侧,当点击浮动按钮时弹出,点击遮罩或者侧栏上边的关闭按钮时收回。侧栏的弹出和收回动画采用小程序提供的动画API。

<view class="slide-mask" style="display:{{maskDisplay}}" bindtap="slideCloseEvent"></view>
<view class="slide-menu" style="right: {{slideRight}}px;width: {{slideWidth}}px;height:{{slideHeight}}px;" animation="{{slideAnimation}}">
<icon type="cancel" size="30" class="close-btn" color="#FFF" bindtap="slideCloseEvent" />
<scroll-view scroll-y="true" style="height:100%;width:100%">
<view class="header">
<view class="userinfo">
<image src="../../images/avatar.png" class="avatar"></image>
<text>Oopsguy</text>
</view>
<view class="toolbar">
<view class="item">
<image src="../../images/fav.png"></image>
<text>收藏</text>
</view>
<view class="item" bindtap="toSettingPage">
<image src="../../images/setting.png"></image>
<text>设置</text>
</view>
</view>
</view>
<view class="menu-item home">
<text>首页</text>
</view>
<view class="slide-inner">
<block wx:for="{{themeData}}">
<view class="menu-item" data-id="{{item.id}}" bindtap="toThemePage">
<text>{{item.name}}</text>
<image src="../../images/plus.png"></image>
</view>
</block>
</view>
</scroll-view>
</view>
/*slide-menu*/
.slide-mask {
position: fixed;
width: 100%;
top: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, .3);
z-index: 800;
}
.slide-menu {
position: fixed;
top: 0;
background: #FFF;
z-index: 900;
}
/*.slide-menu .slide-inner {
padding: 40rpx;
}*/
.slide-menu .header {
background: #019DD6;
height: 200rpx;
color: #FFF;
padding: 20rpx 40rpx 0 40rpx;
} .userinfo {
height: 80rpx;
line-height: 80rpx;
overflow: hidden;
}
.userinfo .avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
margin-right: 40rpx;
float: left;
}
.userinfo text {
float: left;
font-size: 35rpx;
}
.toolbar {
height: 100rpx;
padding-top: 25rpx;
line-height: 75rpx;
}
.toolbar .item {
width: 50%;
display: inline-block;
overflow: hidden;
text-align: center
}
.toolbar .item text {
display: inline-block;
font-size: 30rpx
}
.toolbar .item image {
display: inline-block;
position: relative;
top: 10rpx;
margin-right: 10rpx;
height: 50rpx;
width: 50rpx;
} .slide-menu .menu-item {
position: relative;
height: 100rpx;
line-height: 100rpx;
padding: 0 40rpx;
font-size: 35rpx;
}
.slide-menu .menu-item:active {
background: #FAFAFA;
}
.slide-menu .menu-item image {
position: absolute;
top: 25rpx;
right: 40rpx;
width: 50rpx;
height: 50rpx;
}
.slide-menu .home {
color: #019DD6
} .slide-menu .close-btn {
position: absolute;
top: 20rpx;
right: 40rpx;
z-index: 1000
}

以上是侧栏的一个简单的布局和样式,包含了侧栏中的用户信息块和主题日报列表。当然这些信息是需要通过js的中网络请求来获取的。侧栏结构上边有一个class为slide-mask的view,这是一个遮罩元素,当侧栏弹出的时候,侧栏后边就有一层轻微透明的黑色遮罩。侧栏的高度和宽度初始是不定的,需要在进入页面的时候,马上获取设备信息来获取屏幕的高度宽度调整侧栏样式。

//获取设备信息,屏幕的高度宽度
onLoad: function() {
var _this = this;
wx.getSystemInfo( {
success: function( res ) {
_this.setData( {
screenHeight: res.windowHeight,
screenWidth: res.windowWidth,
slideHeight: res.windowHeight,
slideRight: res.windowWidth,
slideWidth: res.windowWidth * 0.7
});
}
});
}

宽度我取了屏幕宽度的70%,高度一致。侧栏的弹出收回动画使用内置动画API

//侧栏展开
function slideUp() {
var animation = wx.createAnimation( {
duration: 600
});
this.setData( { maskDisplay: 'block' });
animation.translateX( '100%' ).step();
this.setData( {
slideAnimation: animation.export()
});
} //侧栏关闭
function slideDown() {
var animation = wx.createAnimation( {
duration: 800
});
animation.translateX( '-100%' ).step();
this.setData( {
slideAnimation: animation.export()
});
this.setData( { maskDisplay: 'none' });
}

侧栏弹出的时候,遮罩的css属性display设置为block显示,侧栏通过css动画transform来想右侧移动了100%的宽度translateX(100%),侧栏收回时,动画恰好与弹出的相反,其实这些动画最后都会翻译为css3动画属性,这些API只是css3动画的封装。为了点击遮罩收回侧栏,遮罩的tap事件也要绑定slideCloseEvent

//浮动球点击 侧栏展开
ballClickEvent: function() {
slideUp.call( this );
}, //遮罩点击 侧栏关闭
slideCloseEvent: function() {
slideDown.call( this );
}

效果图

微信小程序开发日记——高仿知乎日报(上)的更多相关文章

  1. 微信小程序开发日记——高仿知乎日报(中)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该教 ...

  2. 微信小程序开发日记——高仿知乎日报(下)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP 要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该 ...

  3. [干货教程]仿网易云课堂微信小程序开发实战经验

    本篇文章想跟大家分享下:我们公司“湖北诚万兴科技”最近刚帮客户定制开发.目前已上线的“哎咆课堂”微信小程序的开发经验分享.首先大概介绍下这个小程序所涉及到的主要技术点:微信登录.微信支付.微信小程序F ...

  4. 微信小程序开发学习资料

    作者:初雪链接:https://www.zhihu.com/question/50907897/answer/128494332来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  5. 《腾讯游戏人生》微信小程序开发总结

    为打通游戏人生擂台赛与线下商家的O2O衔接,同时响应时下日臻火热的微信小程序,项目团队决定也开发一款针对性的微信小程序,以此方便商家在我们平台入驻并进行擂台赛事的创建和奖励的核销,进一步推广擂台赛的玩 ...

  6. 微信小程序开发心得

    微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受. 首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司 ...

  7. 微信小程序开发工具使用与设计规范(二)

    [未经作者本人同意,请勿以任何形式转载] 上一篇文章主要分析了微信小程序应用场景和优劣势.本篇你可以学习到: 如何使用小程序开发工具写一个Hello World 微信小程序设计规范 微信小程序项目结构 ...

  8. 微信小程序开发心得--动画机制

    微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受.首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司认 ...

  9. 微信小程序开发06-一个业务页面的完成

    前言 接上文:微信小程序开发05-日历组件的实现 github地址:https://github.com/yexiaochai/wxdemo 这里来说一说我们的理念,我们也学习小程序开发有一周多了,从 ...

随机推荐

  1. NodeJs在Linux下使用的各种问题

    环境:ubuntu16.04 ubuntu中安装NodeJs 通过apt-get命令安装后发现只能使用nodejs,而没有node命令 如果想避免这种情况请看下面连接的这种安装方式: 拓展见:Linu ...

  2. Windows2012R2备用域控搭建

    Windows2012R2备用域控搭建 前置操作 域控主域控的主dns:自己的ip,备dns:备域控的ip备域控的主dns:自己的ip,备dns:主域控的ip 客户端主dns:主域控的ip,备dns: ...

  3. React 入门教程

    React 起源于Facebook内部项目,是一个用来构建用户界面的 javascript 库,相当于MVC架构中的V层框架,与市面上其他框架不同的是,React 把每一个组件当成了一个状态机,组件内 ...

  4. DBImport V3.7版本发布及软件稳定性(自动退出问题)解决过程分享

    DBImport V3.7介绍: 1:先上图,再介绍亮点功能: 主要的升级功能为: 1:增加(Truncate Table)清表再插入功能: 清掉再插,可以保证两个库的数据一致,自己很喜欢这个功能. ...

  5. ABP文档 - Mvc 控制器

    文档目录 本节内容: 简介 AbpController基类 本地化 其它 过滤 异常处理和结果包装 审计日志 验证 授权 工作单元 反伪造 模型绑定器 简介 ABP通过nuget包Abp.Web.Mv ...

  6. runtime梳理。

    一.runtime简介 RunTime简称运行时.OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制. 对于C语言,函数的调用在编译的时候会决定调用哪个函数. 对于OC的函数,属于 ...

  7. 协议森林16 小美的桌号(DHCP协议)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 转载请先与我联系. DHCP协议用于动态的配置电脑的网络相关参数,如主机的IP地址,路由器出口地址.DNS域名服务器地 ...

  8. ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之目录导航

    ASP.NET MVC with Entity Framework and CSS是2016年出版的一本比较新的.关于ASP.NET MVC.EF以及CSS技术的图书,我将尝试着翻译本书以供日后查阅. ...

  9. ZKWeb网页框架1.2正式发布

    发行日志 https://github.com/zkweb-framework/ZKWeb/blob/master/ReleaseNotes/ReleaseNote.1.2.md 主要改动 更新 ZK ...

  10. [EasyUI美化换肤]更换EasyUi图标

    前言 本篇文章主要是记录一些换EasyUI皮肤的过程,备忘.也欢迎美工大神各路UI给点好意见,EasyUI我就不介绍了,自行百度吧..(So..所以别问我是不是响应式..本身EasyUI就不是响应式. ...