無html
該小程序代碼已開源,點擊可查看源碼,可隨意 star。也能夠先掃描下方的小程序碼直接體驗。node
前段時間寫了一個簡單的小程序 QuietWeather,源碼在這裏,具體實現相關可查看這篇文章:兩天擼一個天氣應用微信小程序。可是這個 小程序 和 QuietWeather 徹底不是一個數量級的。so,該文章梳理內容會有那麼一點兒多,想跳過的能夠直接拉到最下面。。。android
這裏先上效果圖,感興趣的也能夠 查看源碼 。實際體驗可掃描👆上面的小程序碼。git
PC
開發者工具錄製,會有些卡頓
文章數據入口調整了,也保留了動畫,請酌情忽略
gif
卡頓
在 filter
目錄下建立了一個 wxs
,裏面是用到的過濾器,須要注意的是,wxs
的語法只能是 es5
,並且部分 js
語法是不支持的,具體支持的語法可查看微信小程序開發文檔。github
細分的話,細分的話目前總共寫了 8 個組件:web
empty
item
組件 feidianItem
:分爲上半部分 feidianItemTop
和下半部分組件 feidianItemBottom
,會在沸點、贊過的沸點等相關頁面複用item
:有兩種展示樣式,這裏寫了獨立的兩個組件:postItemOne
、postItemTwo
item
tagItem
:會在標籤管理等相關頁面複用item
xiaoceItem
:會在小冊 tab
、購買的小冊等相關頁面複用組件相對比較簡單,基本上是以展示爲主,並無太多交互,可下載源碼 在微信開發者工具調試查看相關效果。小程序
HOME
頁主要展示兩部分:頂部熱門文章推薦和下面的推薦文章列表,使用了兩個上面提到的組件: postItemOne
、postItemTwo
。且未登陸時,會有一個登錄提示。實現以下:微信小程序
<wxs module='filters' src='../../filter/filter.wxs'></wxs> <view class='container'> <navigator url='/pages/login/login' wx:if='{{!logined}}'> <view class='card guide'> <view class='l'> <view class='t'>登陸帳號</view> <view class='c'>收藏文章,同步閱讀記錄,數據永不丟失</view> </view> <view class='r'>登陸</view> </view> </navigator> <view class='hot card' wx:if='{{hotRecomment.length && hotRrecommendShow}}'> <view class='btitle'> <view class='l'> <image class='icon' src='/img/ic_hot_home.png'></image> <view>熱門推薦</view> </view> <view class='r'> <image catchtap='refreshHot' class='refresh {{rotate}}' src='/img/refresh_icon.png'></image> <image catchtap='closeHot' class='close' src='/img/chart_close.png'></image> </view> </view> <postItemOne list='{{hotRecomment}}' graphics='{{true}}'></postItemOne> </view> <view class='timeline'> <postItemTwo list='{{timeline}}'></postItemTwo> </view> </view>
其中,頂部熱門推薦的刷新會有如下的實現效果,這裏須要稍微注意下:api
熱門推薦點擊刷新,將當前的 3 條文章 objectId 以 id|id|id 的格式發送請求,而後從新拉取熱門推薦列表看抓包,熱門推薦只返回 20 條,刷新一次移除三條,因此簡單處理的話,user_filter_entry 以後直接將熱門推薦數組的前三條移除便可;上面方式更精確,以防服務端以後又有什麼返回呢數組
同時,搜索 tab
的頂部 banner
列表也是在這個頁面預先請求,而後保存到本地。實現以下:
getBannerImgList() { const auth = this.data.auth wx.request({ url: `${config.bannerRequestUrl}/get_banner`, data: { position: 'explore', page: 0, pageSize: 20, platform: 'android', device_id: auth.clientId, client_id: auth.clientId, token: auth.token, src: 'android', }, success: (res) => { let data = res.data if (data.s === 1) { let bannerImgList = (data.d && data.d.banner) || [] wx.setStorage({ key: 'bannerImgList', data: bannerImgList, }) } else { wx.showToast({ title: data.m.toString(), icon: 'none', }) } }, fail: () => { wx.showToast({ title: '網路開小差,請稍後再試', icon: 'none', }) }, }) },
而後配合下拉刷新 onPullDownRefresh
從新獲取數據。
其餘具體細節這裏再也不贅述可查看源碼。
搜索 tab
頁兩部分組成:頂部的 swiper
和下面的熱門文章列表,這裏複用 postItemOne
組件便可。頂部的 swiper
在首頁已經預先獲取過了(見上面),這裏直接讀取便可。實現以下:
<wxs module='filters' src='../../filter/filter.wxs'></wxs> <view class='container'> <swiper autoplay circular interval="3500" duration="500" wx:if='{{bannerImgList.length}}' style='height:{{swiperHeight}}'> <block wx:for="{{bannerImgList}}" wx:key="{{index}}"> <swiper-item> <image src='{{item.screenshot}}' class="banner" mode='widthFix'></image> </swiper-item> </block> </swiper> <view class='hot card'> <view class='btitle'> <view class='l'> <image class='icon' src='/img/pin_hot.png'></image> <view>熱門文章</view> </view> </view> <recommendItem list='{{rankList}}' graphics='{{false}}'></recommendItem> </view> </view>
該頁面複用的組件是 feidianItem
,頂部的熱門沸點是使用的 swiper
實現的。
該頁面有一個小細節須要稍微注意下:若是頁面保持在頂部,那麼切換 tab
後須要從新刷新獲取新數據,若是頁面已經往下滑動了,那麼切換 tab
後就不須要刷新獲取新數據。實現以下:
wxml
:
<view class='container'> <view class='recommendList'> <swiper autoplay='{{false}}' circular='{{false}}' duration="500" wx:if='{{recommendList.length}}' next-margin='100rpx' style='height:{{swiperHeight}}'> <block wx:for="{{recommendList}}" wx:key="{{index}}"> <swiper-item> <view class='item'> <view class='title' wx:if='{{item.isRecommend}}'> <image class='icon' src='/img/ic_topic_star.png'></image> <text>編輯推薦</text> </view> <view class='title' wx:else> <image class='icon' src='/img/pin_hot.png'></image> <text>熱門沸點</text> </view> <view class='content'> <view class='text'>{{item.content}}</view> <view class='img' wx:if='{{item.pictures && item.pictures.length}}'> <image mode='aspectFill' src='{{item.pictures[0]}}'></image> </view> </view> </view> </swiper-item> </block> </swiper> </view> <view class='pinList'> <feidianItem item='{{item}}' wx:for='{{list}}' wx:key='{{index}}'></feidianItem> </view> </view>
js
:
const config = getApp().globalData.config const utils = require('../../utils/utils.js') Page({ data: { COUNT: 30, swiperHeight: 'auto', recommendList: [], list: [], auth: {}, scrollTop: 0, }, onShow () { // 若是 scrollTop 爲 0,也 reload if (utils.pageReload(this.data.auth, [this.data.list]) || !this.data.scrollTop) { this.init() } }, onPullDownRefresh() { this.init() }, init() { wx.showLoading({ title: '數據加載中', }) this.setData({ auth: {}, }) let auth = utils.ifLogined() this.setData({ auth, }) this.initSwiper() this.getHotRecommendList() this.pinListRecommend(true) }, initSwiper() { wx.getSystemInfo({ success: (res) => { this.setData({ swiperHeight: `${(res.windowWidth || res.screenWidth) / 375 * 135}px` }) }, }) }, // 熱門推薦列表 getHotRecommendList() { const auth = this.data.auth wx.request({ url: `${config.shortMsgMsRequestUrl}/getHotRecommendList`, data: { uid: auth.uid, device_id: auth.clientId, client_id: auth.client_id, token: auth.token, src: 'web', }, success: (res) => { let data = res.data if (data.s === 1) { this.setData({ recommendList: (data.d && data.d.list) || [], }) } else { wx.showToast({ title: data.m.toString(), icon: 'none', }) } }, fail: () => { wx.showToast({ title: '網路開小差,請稍後再試', icon: 'none', }) }, }) }, // 沸點列表 pinListRecommend(reload) { const auth = this.data.auth let list = this.data.list if (utils.isEmptyObject(list) || reload) { list = [{ createdAt: '' }] } let createdAt = (list.slice(-1)[0].createdAt) || '' wx.request({ url: `${config.shortMsgMsRequestUrl}/pinList/recommend`, data: { uid: auth.uid, device_id: auth.clientId, token: auth.token, src: 'web', limit: this.data.COUNT, before: createdAt, }, success: (res) => { let data = res.data if (data.s === 1) { wx.hideLoading() let list = (data.d && data.d.list) || [] this.setData({ list: reload ? list : this.data.list.concat(list), }) } else { wx.showToast({ title: data.m.toString(), icon: 'none', }) } }, fail: () => { wx.showToast({ title: '網路開小差,請稍後再試', icon: 'none', }) }, }) }, onReachBottom() { this.pinListRecommend() }, onPageScroll (e) { this.setData({ scrollTop: e.scrollTop, }) }, onShareAppMessage(res) { return {} }, })
小冊頁面基本上沒有什麼可說的,只有小冊展示。。。組件複用 xiaoceItem
,實現以下:
<view class='lists'> <xiaoceItem list='{{xiaoceList}}'></xiaoceItem> </view>
該頁面以簡單的數目展示(未讀消息條數、收藏集數目、閱讀過的文章數)和跳轉爲主,調用相關的 API
便可,沒有什麼難度。實現以下:
wxml
:
<view class='wrapper'> <view class='card profile' catchtap='navigatItem' data-url='/pages/personal/personal'> <view class='info'> <image class='avatar' src='{{userInfo.avatarLarge}}' wx:if='{{userInfo.avatarLarge}}'></image> <image class='avatar' src='/img/empty_avatar_user.png' wx:else></image> <view class='text'> <view class='name'>{{userInfo.username || '登陸/註冊'}}</view> <view>{{userInfo.jobTitle || '添加職位'}} @ {{userInfo.company || '添加公司'}}</view> </view> </view> <view class='more'> <view class='reddot' wx:if='{{auth && !userInfo.company}}'></view> <image src='/img/profile_arrow.png'></image> </view> </view> <view class='card items'> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/infoCenter/infoCenter'> <view class='title'> <image src='/img/ic_notification.png'></image> <view>消息中心</view> </view> <view class='count reddot' wx:if='{{userNotificationNum}}'>{{userNotificationNum}}</view> </view> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/favorate/favorate'> <view class='title'> <image src='/img/ic_heart_entry_bottom_full.png'></image> <view>我喜歡的</view> </view> <view class='count'>{{userInfo.collectedEntriesCount || 0}}篇</view> </view> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/collectionSet/collectionSet'> <view class='title'> <image src='/img/ic_collection_set.png'></image> <view>收藏集</view> </view> <view class='count'>{{userInfo.collectionSetCount || 0}}個</view> </view> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/purchasedXiaoce/purchasedXiaoce'> <view class='title'> <image src='/img/user_buy.png'></image> <view>已購小冊</view> </view> <view class='count'>{{userInfo.purchasedBookletCount || 0}}本</view> </view> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/myPins/myPins?liked=1'> <view class='title'> <image src='/img/user_liked_pin.png'></image> <view>贊過的沸點</view> </view> <view class='count'>{{userInfo.likedPinCount || 0}}個</view> </view> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/readHistory/readHistory'> <view class='title'> <image src='/img/view.png'></image> <view>閱讀過的文章</view> </view> <view class='count'>{{userInfo.viewedEntriesCount || 0}}篇</view> </view> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/manageTag/manageTag'> <view class='title'> <image src='/img/tag.png'></image> <view>標籤管理</view> </view> <view class='count'>{{userInfo.subscribedTagsCount || 0}}個</view> </view> </view> <view class='card items'> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/feedback/feedback' data-open='true'> <view class='title'> <image src='/img/icon_feed_back.png'></image> <view>意見反饋</view> </view> </view> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/setting/setting' data-open='true'> <view class='title'> <image src='/img/settings.png'></image> <view>設置</view> </view> </view> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/miniqrcode/miniqrcode' data-open='true'> <view class='title'> <image src='/img/qrcode.png' style='width:28rpx;height:28rpx;padding:10rpx'></image> <view>小程序碼</view> </view> </view> </view> </view>
js
:
const utils = require('../../utils/utils.js') const config = getApp().globalData.config Page({ data: { userInfo: {}, userNotificationNum: 0, auth: {}, }, onShow () { let auth = utils.ifLogined() this.setData({ auth, }) if (auth) { this.getUserInfo() this.userNotificationNum() } else { this.setData({ userInfo: {}, userNotificationNum: 0, }) } }, navigatItem (e) { return utils.navigatItem(e) }, // 獲取用戶信息 getUserInfo() { const auth = this.data.auth wx.request({ url: `${config.apiRequestUrl}/getUserInfo`, data: { src: 'web', device_id: auth.clientId, uid: auth.uid, token: auth.token, current_uid: auth.uid, }, success: (res) => { let data = res.data if (data.s === 1) { this.setData({ userInfo: data.d, }) } else { wx.showToast({ title: data.m.toString(), icon: 'none', }) } }, fail: () => { wx.showToast({ title: '網路開小差,請稍後再試', icon: 'none', }) }, }) }, // 消息中心消息條數 userNotificationNum() { const auth = this.data.auth wx.request({ url: `${config.notifyRequestUrl}/getUserNotificationNum`, data: { src: 'web', uid: auth.uid, token: auth.token, }, success: (res) => { let data = res.data if (data.s === 1) { this.setData({ userNotificationNum: data.d && data.d.notification_num, }) } else { wx.showToast({ title: data.m.toString(), icon: 'none', }) } }, fail: () => { wx.showToast({ title: '網路開小差,請稍後再試', icon: 'none', }) }, }) }, })
文章詳情頁返回的數據是整篇文章的 html
格式,若是是瀏覽器的話,直接顯示便可,小程序裏這裏使用的是 wxParse
解析的。實現以下:
<wxs module='filters' src='../../filter/filter.wxs'></wxs> <import src="../../wxParse/wxParse.wxml"/> <view class='container'> <image wx:if='{{postInfo.screenshot}}' style='width:100%;height:340rpx;' mode='aspectFill' src='{{postInfo.screenshot}}'></image> <view class='content'> <view class='user'> <view class='avatar' catchtap='toPersonal'> <image mode='aspectFill' src='{{(postInfo.user && postInfo.user.avatarLarge) || "/img/default_avatar.png"}}'></image> </view> <view class='info'> <view class='name'>{{postInfo.user && postInfo.user.username}}</view> <view class='others'> <text class='time'>{{postInfo.createdAt}}</text> <text>閱讀 {{postInfo.viewsCount}}</text> </view> </view> </view> <view class='title'>{{postInfo.title}}</view> <template is="wxParse" data="{{wxParseData:article.nodes}}"/> </view> </view>
至於評論相關的,尚未寫。。。
我的中心頁和個人頁面展示差很少,也是顯示條目和頁面跳轉爲主,調用相關的 API
便可,再也不贅述。實現以下:
<view class='wrapper'> <view class='card profile'> <view class='info'> <image class='avatar' mode='aspectFill' src='{{userInfo.avatarLarge}}' wx:if='{{userInfo.avatarLarge}}'></image> <image class='avatar' src='/img/empty_avatar_user.png' wx:else></image> <view class='text'> <view class='name'>{{userInfo.username}}</view> <view class='jobtitle'>{{userInfo.jobTitle}}</view> <view class='others'>{{userInfo.selfDescription }}</view> </view> </view> <view class='bottom'> <view class='l'> <view class='action'> <view>{{userInfo.followeesCount}}</view> <view class='key'>關注</view> </view> <view class='action'> <view>{{userInfo.followersCount}}</view> <view class='key'>關注者</view> </view> </view> <!-- <view class='edit'>編輯</view> --> <image src='/img/ic_dynamic_vote.png' class='trend' catchtap='showDataTrend'></image> </view> </view> <view class='card items'> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/dynamic/dynamic?thirduid={{thirduid}}' data-open='true'> <view class='title'> <view>動態</view> </view> </view> </view> <view class='card items'> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/myPins/myPins?thirduid={{thirduid}}' data-open='true'> <view class='title'> <view>沸點</view> </view> <view class='count'>{{userInfo.pinCount || 0}}</view> </view> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/originalPost/originalPost?thirduid={{thirduid}}' data-open='true'> <view class='title'> <view>原創文章</view> </view> <view class='count'>{{userInfo.postedPostsCount}}</view> </view> <view class='item' wx:if='{{userInfo.postedEntriesCount}}' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/sharePost/sharePost?thirduid={{thirduid}}' data-open='true'> <view class='title'> <view>分享文章</view> </view> <view class='count'>{{userInfo.postedEntriesCount}}</view> </view> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/collectionSet/collectionSet?thirduid={{thirduid}}' data-open='true'> <view class='title'> <view>收藏集</view> </view> <view class='count'>{{userInfo.collectionSetCount}}</view> </view> </view> <view class='card items'> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/favorate/favorate?thirduid={{thirduid}}' data-open='true'> <view class='title'> <view>喜歡的文章</view> </view> <view class='count'>{{userInfo.collectedEntriesCount}}</view> </view> <view class='item' hover-class='hover-class' catchtap='navigatItem' data-url='/pages/subscribedTag/subscribedTag?thirduid={{thirduid}}' data-open='true'> <view class='title'> <view>關注的標籤</view> </view> <view class='count'>{{userInfo.subscribedTagsCount}}</view> </view> </view> <view class='card items'> <view class='item' wx:if='{{userInfo.community && userInfo.community.weibo && userInfo.community.weibo.username}}'> <view class='title'> <image src='/img/icon_profile_weibo.png'></image> <view class='val'>{{userInfo.community.weibo.username}}</view> </view> </view> <view class='item' wx:if='{{userInfo.blogAddress}}'> <view class='title'> <image src='/img/icon_profile_blog.png'></image> <view class='val'>{{userInfo.blogAddress}}</view> </view> </view> </view> </view>
文章數據頁就是顯示你的文章得到了多少收藏、多少評論、多少閱讀相關的數據,該頁面主要是數字滾動動畫的實現。這裏的實現思路是這樣的:
將數字從 0 到 N 縱向排列,而後 translateY
到相應的數字便可,主要的實現以下:
<view class='countInner' style='transform:translateY(-{{100*(item.length-1)/item.length}}%)' wx:for='{{filters.strToNumArr(userInfo.totalCollectionsCount)}}' wx:key='{{index}}' wx:for-item='item' wx:for-index='index'> <view wx:for='{{item}}' wx:key='{{idx}}' wx:for-item='i' wx:for-index='idx'>{{i}}</view> </view> // 按照長度生成 0 字符串 generateZeroArr (len) { Array.apply(null, Array(len)).map(function (item, i) { return 0 }) }
其餘細節再也不贅述,可查看源碼。
消息中心有兩個 tab
,能夠點擊、滑動切換,這裏的實現是 swiper
。這裏須要注意的是:消息分爲不一樣的 category
,不一樣的 category
展示的內容是不同的,因此這裏須要區分下,目前我獲取到的 category
只有幾種,是否所有覆蓋全部的 category
只能等遇到沒有覆蓋的時候隨手補上了。。。實現以下:
<wxs module='filters' src='../../filter/filter.wxs'></wxs> <view class='container'> <view class='top tabs'> <view class='inner'> <view class='tab {{currentSwiper === "0" ? "active" : ""}}' data-index='0' catchtap='switchSwiper'>用戶消息</view> <view class='tab {{currentSwiper === "1" ? "active" : ""}}' data-index='1' catchtap='switchSwiper'>系統消息</view> </view> <view class='bar' style='left:{{currentSwiper*50}}%'></view> </view> <swiper class='swiper' autoplay='{{false}}' indicator-dots='{{false}}' bindchange='swiperChanged' current='{{currentSwiper}}'> <swiper-item item-id='0'> <scroll-view scroll-y bindscrolltolower='getMoreUserNotification'> <view class='item' wx:for='{{list}}' wx:key='{{index}}'> <view class='avatar' data-id='{{item.users[0].objectId}}' catchtap='toPersonal'> <image mode='aspectFill' src='{{item.users[0].avatarLarge || "/img/default_avatar.png"}}'></image> </view> <view class='content' wx:if='{{item.category==="collection"}}'> <view>{{item.users[0].username}}等{{item.count}}人 喜歡了你的文章 <text data-id='{{item.entry && item.entry.objectId}}' catchtap='toPostDetail'>{{item.entry && item.entry.title}}</text></view> <view class='time'>{{filters.timeBefore(item.updatedAtString)}}</view> </view> <view class='content' wx:elif='{{item.category==="comment"}}'> <view>{{item.users[0].username}}回覆了你在文章 <text data-id='{{item.entry && item.entry.objectId}}' catchtap='toPostDetail'>{{item.entry && item.entry.title}}</text> 的評論</view> <view class='comment'>{{(item.reply && item.reply.content) || (item.comment && item.comment.content)}}</view> <view class='time'>{{filters.timeBefore(item.updatedAtString)}}</view> </view> <view class='content' wx:elif='{{item.category==="follow"}}'> <view>{{item.users[0] && item.users[0].username}} 關注了你</view> <view class='time'>{{item.users[0] && item.users[0].jobTitle}}</view> </view> <view class='content' wx:elif='{{item.category==="comment-like"}}'> <view>{{item.users[0] && item.users[0].username}} 讚了你在 <text>{{item.entry && item.entry.title}}</text> 的評論</view> </view> <view class='content' wx:elif='{{item.category==="pin-like"}}'> <view>{{item.users[0] && item.users[0].username}} 讚了你的 <text>沸點</text></view> <view class='time'>{{filters.timeBefore(item.updatedAtString)}}</view> </view> <view class='content' wx:elif='{{item.category==="pin-comment"}}'> <view>{{item.users[0] && item.users[0].username}} 回覆了你的 <text>沸點</text></view> <view class='comment'>{{(item.reply && item.reply.content) || (item.pinComment && item.pinComment.content)}}</view> <view class='time'>{{filters.timeBefore(item.updatedAtString)}}</view> </view> <view class='content' wx:else>未知狀態,可提交給開發者</view> </view> </scroll-view> <empty wx:if='{{!list.length}}' tip='暫無消息'></empty> </swiper-item> <swiper-item item-id='1'> <view wx:if='{{systemInfoList.length}}'> 很差意思,我沒有系統消息,因此看不到系統消息 API 的數據結構,也看不到樣式。。。 </view> <empty wx:if='{{!systemInfoList.length}}' tip='暫時沒有系統通知'></empty> </swiper-item> </swiper> </view>
動態頁也須要稍微注意一點,動態頁分不一樣的 category
,這裏覆蓋的有 follow
、collection
、subscribe
,若是遇到未覆蓋的只能順手補上。實現以下:
<wxs module='filters' src='../../filter/filter.wxs'></wxs> <view class='container'> <view class='item' wx:for='{{list}}' wx:key='{{index}}'> <view class='inner' wx:if='{{item.category === "follow"}}'> <view class='top'> <view class='l'> <image mode='widthFix' src='/img/ic_dynamic_user.png'></image> <view>關注了:</view> </view> <view class='r'>{{filters.timeBefore(item.createdAtString)}}</view> </view> <view class='bottom'> <view class='tagcard'> <image mode='aspectFill' src='{{item.users[0].avatarLarge || "/img/entry_image_default.png"}}'></image> <view class='others'> <view class='title'>{{item.users && item.users[0].username}}</view> <view class='info' wx:if='{{item.users && item.users[0].jobTitle && item.users[0].company}}'>{{item.users && item.users[0].jobTitle}} @ {{item.users && item.users[0].company}}</view> </view> </view> </view> </view> <view class='inner' wx:if='{{item.category === "collection"}}'> <view class='top'> <view class='l'> <image mode='widthFix' src='/img/ic_dynamic_collect.png'></image> <view>喜歡了:</view> </view> <view class='r'>{{filters.timeBefore(item.createdAtString)}}</view> </view> <view class='bottom'> <view class='tagcard' data-id='{{item.entry && item.entry.objectId}}' catchtap='toPostDetail'> <image mode='aspectFill' src='{{item.entry.screenshotUrl || "/img/entry_image_default.png"}}'></image> <view class='others'> <view class='title'>{{item.entry && item.entry.title}}</view> </view> </view> </view> </view> <view class='inner' wx:if='{{item.category === "subscribe"}}'> <view class='top'> <view class='l'> <image mode='widthFix' src='/img/ic_dynamic_tag.png'></image> <view>關注了 {{item.tags && item.tags[0].title}} 等 {{item.tags && item.tags.length}} 個標籤</view> </view> <view class='r'>{{filters.timeBefore(item.createdAtString)}}</view> </view> <view class='bottom'> <view class='imglist'> <image mode='aspectFill' wx:for='{{item.tags}}' wx:key='{{idx}}' wx:for-index='idx' wx:for-item='i' src='{{i.icon}}'></image> </view> </view> </view> </view> </view>
這個頁面的 tab
也是用 swiper
實現的,複用的組件是 tagItem
。實現以下:
<view class='container'> <view class='top tabs'> <view class='inner'> <view class='tab {{currentSwiper === "0" ? "active" : ""}}' data-index='0' catchtap='switchSwiper'>已關注標籤</view> <view class='tab {{currentSwiper === "1" ? "active" : ""}}' data-index='1' catchtap='switchSwiper'>全部標籤</view> </view> <view class='bar' style='left:{{currentSwiper*50}}%'></view> </view> <swiper class='swiper' autoplay='{{false}}' indicator-dots='{{false}}' bindchange='swiperChanged' current='{{currentSwiper}}'> <swiper-item item-id='0'> <view> <tagItem list='{{tagList}}'></tagItem> </view> <empty wx:if='{{!tagList.length}}' tip='暫無消息'></empty> </swiper-item> <swiper-item item-id='1'> <scroll-view scroll-y bindscrolltolower='getMoreRecommendTags'> <view class='hot' wx:if='{{hotTagList.length}}'> <view class='title'>推薦標籤</view> <tagItem list='{{hotTagList}}'></tagItem> </view> <view class='suggest' wx:if='{{recommendTagList.length}}'> <view class='title'>你可能感興趣的標籤</view> <tagItem list='{{recommendTagList}}'></tagItem> </view> </scroll-view> <empty wx:if='{{!hotTagList.length && recommendTagList.length}}' tip='暫時沒有系統通知'></empty> </swiper-item> </swiper> </view>
這幾個頁面都是組件的複用,沒有太多要說的。
這兩個頁面只是一個關於頁面而已。。。
APP
裏面的東西實在是很多,包括頁面和交互,要徹底照抄實現確實須要一些時間和精力,UI
之類的都是簡單測量+肉眼調試實現的,下面列出頁面和交互的完成度,這裏應該只是列出了絕大部分(仍是上面那句話,APP
裏面的東西實在是很多),未列出、未實現的後續會根據時間、精力來實現。
實際完成度請以代碼爲主(線上小程序也會持續更新)。
貌似不支持 markdown
待辦事宜寫法?QAQ
[ ] HOME TAB
[x] 首頁
[ ] 搜索 TAB
[ ] 收藏集
[ ] 活動
[ ] 沸點 TAB
[ ] 推薦
[ ] 小冊 TAB
[ ] 個人 TAB
[ ] 我的主頁
[x] 收藏集
[x] 關注的標籤
[x] 標籤管理
[x] 全部標籤
[ ] 設置
評論、留言、關注、添加到收藏集、喜歡、發表沸點等暫時均沒有實現,由於 APP 裏面的東西實在是很多......
API
域名(二級)真是多啊,小程序後臺域名白名單最多隻能配 20
個,如今已經佔了 16
個了,感受要完整APP
版小程序,配額不夠啊。不行的話,就只能搭個 server
代理了;APP
用到了,請求字段須要按照 web
的略做調整;個別接口也要設置對應的 header
;html
格式的 content
,這裏使用的是開源的 wxParse 進行富文本解析;url
不能在 webview
中打開,因此文章裏面的外鏈能點開算我輸;tab
頁,若是已經滑到了頂部,onShow
獲取新數據,不然,不刷新;未登陸時,首頁 APP
調用的 API 是 get_recommended_entry
,get_entry_by_timeline
;其餘的不一一贅述,詳情可 查看源碼;API
須要天時地利人和,部分 API
返回的數據格式沒有拿到,因此對應的頁面也沒有寫,好比:系統消息頁面(最近一直沒有系統消息)等;category
有 collection
、comment
、follow
、comment-like
、pin-like
、pin-comment
,可能還會有其餘消息類型,遇到了會一一補上;還有動態頁,也是一樣的問題;可能還有其餘沒有徹底覆蓋的數據;illegal token
,亦或文章沒有正常顯示出來,應該是請求參數須要略做調整,或者文章類型須要判斷。相似這樣的小問題,後續會調整補充;APP
的 100%
的複製版,這樣會顯得比較臃腫,此處應該有 but
,該小程序僅僅是出於學習交流的目的,因此這個問題不在咱們的考慮範圍內;轉載請註明出處