【原】小寫了一個cnode的小程式
小程式剛出來的第一天,朋友圈被刷屏了,所以趁週末也小玩了一下小程式。其實發覺搭建一個小程式不難,只要給你一個demo,然後自己不斷的檢視文件,基本就可以入門了,不過對於這種剛出來的東西,還是挺多坑的,也就是文件說的bug&tips
本文只是搭建了cnode的首頁和詳情頁,其他的什麼個人中心啊,搜尋啊,都是一樣的道理,照葫蘆畫瓢,首頁和詳情頁會了,其他的頁面也就會了,所以其他頁面我就偷懶沒寫了。
為什麼會想到模仿cnode呢,因為這個網站有公開的API文件,呼叫起來方便。文件地址在這裡:https://cnodejs.org/api
接下來,正式開始我們的微信小程式之旅
構建準備工作
構建過程我這裡直接列舉一些連結的方式,因為想把主要的篇幅用來寫程式的過程。
1、首先你需要註冊一個微信小程式的開發平臺:點這裡
2、其次你需要完善你的資訊,來獲取AppID,如果沒有AppID的話,微信小程式的有些功能是用不了的,個人的話是無法申請到的,要有企業的驗證資訊,不過可以看看這篇文章破解:點這裡
3、需要下載一個微信開發者工具:點這裡
4、前面的步驟準備好之後,開始構建我們的專案,構建過程可以看看這篇文章:點這裡
正是開始搭建
這是我們完成之後的檢視
頁面分析:
我們可以看到,頁面的頁尾有3個導航按鈕,分別是首頁、搜尋、我的。
首頁的話有5個tab切換,分別是全部、精華、分享、問答、招聘,當我們點選文章標題的時候,可以跳轉到對應的詳情頁,按返回,可以回到上一級頁面。上拉,可以載入更多。接下來我們就來完成這些功能。
小程式的開發文件在這裡,可以跟著文件來看下面的程式碼:文件
我們的目錄結構如下:
pages/
pages/index/index.wxml
pages/index/index.js
pages/index/index.wxss
pages/detail/detail.wxml
pages/detail/detail.js
pages/detail/detail.wxss
app.js
app.json
app.wxss
首先是使用app.json
檔案來對微信小程式進行全域性配置,決定頁面檔案的路徑、視窗表現、設定網路超時時間、設定多 tab 等。
{ "pages": [ "pages/index/index","pages/my/my", "pages/search/search", "pages/detail/detail" ], "window": { "navigationBarBackgroundColor":"#2b2e33", "navigationBarTextStyle": "white", "navigationBarTitleText": "cnode", "backgroundColor": "#fff", "backgroundTextStyle": "#dark" }, "tabBar": { "color": "#74777e", "selectedColor": "#f06000", "borderStyle": "white", "backgroundColor": "#fff", "list": [{ "pagePath": "pages/index/index", "iconPath": "image/wp.png", "selectedIconPath": "image/wpselect.png", "text": "首頁" }, { "pagePath": "pages/search/search", "iconPath": "image/ss.png", "selectedIconPath": "image/ssselect.png", "text": "搜尋" },{ "pagePath": "pages/my/my", "iconPath": "image/my.png", "selectedIconPath": "image/myselect.png", "text": "我的" }] }, "networkTimeout": { "request": 10000, "connectSocket": 10000, "uploadFile": 10000, "downloadFile": 10000 }, "debug": true }
我們在app.json中的pages來設定我們的設定頁面路徑,陣列的第一項代表小程式的初始頁面,我們的首頁是初始頁,所以在page中的第一個。小程式中新增/減少頁面,都需要對 pages 陣列進行修改。檔名不需要寫檔案字尾,因為框架會自動去尋找路徑.json
,.js
,.wxml
,.wxss
的四個檔案進行整合。
在app.json中的list中,我們從來設定tab列表,也即是頁面中底部的導航欄,該list最少2個,最多5個。並且設定了對應頁面路徑、tab按鈕的文字、icon路徑,選中之後的圖片路徑等。
其他的配置內容可以看看文件,因為不可能全域性介紹完,否則內容太多了。
注意點:
當我們跳轉到詳情頁的時候,因為詳情頁是新增頁面,但是底部的導航欄是沒有詳情這個選項的,所以我們需要在app.json中pages陣列中增加詳情頁的路徑,但是在list陣列中不需要增加,否則會報錯。
配置檔案搞好了,接下來開始書寫我們的首頁
一個小程式頁面由四個檔案組成,分別是:js、wxml(相當於html)、wxss(相當於css)、json(頁面配置),這四個檔案必須具有相同的路徑與檔名。
所以我們首頁結構是:
pages/index/index.js
pages/index/index.wxml
pages/index/index.wxss
index.js如下:
/* * @Author: xianyulaodi * @Date: 2017-01-16 17:33:45 */ //建立精選頁面物件 Page({ data: { loading: false, loadtxt: '正在載入', currentTab: 'all', dataList:[], page:1, section: [ {name : '全部',tab : 'all'}, {name : '精華',tab : 'good'}, {name : '分享',tab : 'share'}, {name : '問答',tab : 'ask'}, {name : '招聘',tab : 'job'} ] }, /* *@param {Number} page 頁數 *@param {String} tab 主題分類。目前有 ask share job good *@param {Number} limit 每一頁的主題數量 *@param {String} mdrender 當為 false 時,不渲染。預設為 true,渲染出現的所有 markdown 格式文字。 */ onLoad: function(){ var self=this;//這裡需要注意 wx.request({ url: 'https://cnodejs.org/api/v1/topics', data: { 'page':self.data.page, 'tab':self.data.currentTab, 'limit':10, 'mdrender':true, }, header: { 'content-type': 'application/json' }, success: function(rs) { var dataArr=rs.data.data; console.log(dataArr); var dataList=self.data.dataList; //合併陣列,用於上拉載入更多,沒有append方法,我這種方法不是很好,因為到後面陣列會很大 var renderArr=self.data.page==1 ? dataArr : dataList.concat(dataArr); self.setData({ loading: true, loadtxt: '資料載入完成', dataList: renderArr }) } }) }, // 頁面上拉觸底事件的處理函式,用於上拉記載更多 onReachBottom:function(e){ var page=this.data.page; // 控制一下,最多顯示十頁的資料 if(page<10){ this.setData({ page: page+1 }); this.onLoad(); } return false; }, handleTap: function(e){ //console.log(e); let tab = e.currentTarget.id; if(tab){ this.setData({ currentTab: tab, page:1 //重置page為1 }) this.onLoad(); } }, /* 使用wx.navigateTo或者直接使用它的元件navigator要注意: 在app.json裡面也需要pages裡面的配置裡要寫上跳轉的路徑,但是在app.json裡面不需要寫上這個跳轉的路徑。 */ goToDetail:function(e){ var id=e.target.id; console.log(id); // wx.navigateTo,是保留當前頁面,調到應用內某個頁面,使用wx.navigateBack可以返回 wx.navigateTo({ url: '../detail/detail?id='+id }) } })View Code
程式碼有點長,不過沒關係,我們來分析一下:
Page()
函式用來註冊一個頁面。接受一個 object 引數,其指定頁面的初始資料、生命週期函式、事件處理函式等。
Page()裡面有很多的引數,不過我們只用到了其中的三個,onLoad和onReachBottom,data。
onLoad是監聽頁面的載入,也就是說頁面一載入完成就會執行。 onReachBottom是頁面上拉觸底事件的處理函式,我們這裡用來做上拉載入更多的操作,也就是上拉一次,請求的頁碼引數就加1;data是頁面初始資料。
那麼獲取到的資料怎樣傳給頁面呢,可以通過page()中的data引數,它是頁面的初始資料。如果你想改變初始資料,比如頁面請求完成了,可以通過this.setData來對初始資料進行修改。
還有對於請求引數的修改,我們不是直接傳到onLoad裡面,而是通過this.setData()來對初始引數就行修改,從而達到修改引數目的,比如首頁上面的五個tab切換,後者是上拉載入更多的實現,都是通過這種方式來進行傳值的。
除此之外,我們還註冊了兩個事件,一個是handleTap,控制首頁(index頁)的tab切換,每次切換我們要拿到該tab對應的tab值,從而拿到該tab對應的資料。在page定義中的相應事件處理函式,引數是event。我們來看看下面的程式碼:
handleTap: function(event){ console.log(event); let tab = event.currentTarget.id; if(tab){ this.setData({ currentTab: tab, page:1 //重置page為1 }) this.onLoad(); } }
我們console.log(event)的內容如下:
我們註冊的另一個事件是goToDetail,用來跳轉到詳情頁,並傳入一個id過去:
goToDetail:function(e){ var id=e.target.id; // wx.navigateTo,是保留當前頁面,調到應用內某個頁面,使用wx.navigateBack可以返回 wx.navigateTo({ url: '../detail/detail?id='+id }) }
這裡我們呼叫小程式裡面提供的wx.navigateTo來跳轉到詳情頁,它會保留當前頁面,當你返回的時候可以返回上一級頁面。也可以這麼理解,wx.navigateTo相當於在當前頁面上方加了一層遮罩,這個遮罩就是你要跳轉頁面,當你點選返回時,這層遮罩消失,因此你又回到了當前頁。
接下來我們介紹index.wxml
程式碼如下:
<import src="../../common/template.wxml"/> <view class="index"> <view class="nav-scroll"> <scroll-view class="scroll-view_H" scroll-x="true" style="width: 100%"> <text wx:for="{{section}}" wx:key="tab" id="{{item.tab}}" catchtap="handleTap" class="nav-name {{item.tab == currentTab ? 'nav-hover' : ''}}">{{item.name}}</text> </scroll-view> </view> <view class="mod-item" wx:for="{{dataList}}" wx:key="{{index}}"> <image src="{{item.author.avatar_url}}" class="image-item"></image> <view class="text" catchtap="goToDetail" id="{{item.id}}" >{{item.title}}</view> <!-- 下面的寫法也可以跳轉到詳情頁: <navigator class="text" url="../detail/detail?id={{item.id}}" open-type="navigate" hover-class="other-navigator-hover"> {{item.title}} </navigator> --> </view> <template is="loadings" data="{{loading,loadtxt}}" /> </view>View Code
其實跟我們的html差不錯,不過它又不是html,因為在這裡你不可以使用html的語法,否則會報錯,而是要使用文件中規定的那些標籤。可以看看文件中元件部分。
我們對裡面的內容進行分析:
在WXML中,小程式提供了模板(template),可以在模板中定義程式碼片段,然後在不同的地方呼叫。
我們的index.wxml中也引入了一個loading的模板,我們來看看common/template.wxml裡面的內容
<!-- loading模板 --> <template name="loadings"> <view class="tips {{loading ? 'hide': ''}}"> <image src="../../image/loading.gif" mode="aspectFit" /> <text>{{loadtxt}}...</text> </view> <loading hidden="{{loading}}"> {{loadtxt}}... </loading> </template>
我們定義的是一個loading的模板,這樣的話在需要用到loading的地方都可以用到。不過有個前提,呼叫它的地方要提供和模板裡面一樣的資料結構。
如何使用呢,使用 is 屬性,宣告需要的使用的模板,然後將模板所需要的 data 傳入,如:
<template is="loadings" data="{{loading,loadtxt}}" />
注意點:在模本里面的檔案路徑是相應於引用它的頁面的路徑,如果圖片路徑被寫在一個js檔案A裡,而B引用了這個js檔案,那麼圖片的路徑必須是相對於B的相對路徑。所以,最好在公共的js檔案裡使用絕對路徑。
繼續我們的頁面分析,頁面的資料那裡來的呢,來自於index.js的app()裡面的data引數裡,比如我們的data裡面有section這個陣列,可以用來渲染首頁的tab切換,data裡面有dataList這個陣列,用來渲染請求返回的資料。在元件上使用wx:for
控制屬性繫結一個數組,即可使用陣列中各項的資料重複渲染該元件。
前面我們也說了我們handleTap和goToDetail兩個事件,怎樣繫結在頁面上呢,可以用bindTap
或catchTap的方式,不過catchTap不會冒泡,使用方法是這樣:
<view class="text" catchtap="goToDetail" >{{item.title}}</view>
注意點:
當你的小程式可以正常執行的時候,應該會有這樣的一個報錯;
解決方法:開啟小程式微信公眾平臺設定小程式開發設定,配置伺服器合法域名(必須是https),如下圖
這樣,我們的首頁基本就完成了。因為css部分和正常的css一樣,沒啥好說的。分析一下首頁的程式碼,發覺小程式有點借鑑react的思想,比如資料初始化還有一些page上提供的事件。如果你之前玩過react,入門起來會快很多。如果你有用騰訊的artTemplate這個js模板引擎的話,就更好理解一些。
接下來說一說詳情頁:
我們在首頁中,通過wx.navigateTo跳轉到了詳情頁,並傳入了詳情頁需要的id
goToDetail:function(e){ var id=e.target.id; wx.navigateTo({ url: '../detail/detail?id='+id }) }
我們來分析一下詳情頁的一些內容,首先來分析它的js,也就是pages/detail/detail.js
/* * @Author: xianyulaodi * @Date: 2017-01-16 17:33:45 */ // 引入這個是為了解析詳情頁的html var WxParse = require('../../wxParse/wxParse.js'); Page({ data:{ title:'', loading: false, loadtxt: '正在載入', data:{} }, onLoad: function(params){ console.log(params); //這裡是上一個跳轉頁面傳過來的引數,可以直接獲取 var id=params.id; var self=this;//這裡需要注意 wx.request({ url: 'https://cnodejs.org/api/v1/topic/'+id, header: { 'content-type': 'application/json' }, success: function(rs) { console.log(rs); var data=rs.data.data; var content=data.content; self.setData({ loading: true, loadtxt: '資料載入完成', data: data }); /** * WxParse.wxParse(bindName , type, data, target,imagePadding) * 1.bindName繫結的資料名(必填) * 2.type可以為html或者md(必填) * 3.data為傳入的具體資料(必填) * 4.target為Page物件,一般為this(必填) * 5.imagePadding為當圖片自適應是左右的單一padding(預設為0,可選) * 可參考此文:https://weappdev.com/t/wxparse-version0-2-html-markdown/326 --> */ WxParse.wxParse('content', 'html', content, self,5); } }); }, })View Code
我們怎樣來拿到上一個頁面傳過來的值呢,我們可以在onLoad時間中寫一個引數,這個引數就是獲取url上傳過來的值,它是一個物件
onLoad: function(params){ console.log(params); //這裡是上一個跳轉頁面傳過來的引數,可以直接獲取 }
這是控制檯列印的內容,這樣的話,根據獲取的id,我們就可以傳給後臺請求到對應的詳情頁了。
詳情頁和首頁的原理基本差不多,不過詳情頁content欄位返回的是html結構,微信小程式暫時還沒有富文字html、md解析元件。所以如果直接渲染content的話,會直接把html標籤頁顯示出來。
那怎麼辦呢,我們需要引入一個外部的從來解析html的元件wxParse,連結地址在這裡:https://weappdev.com/t/wxparse-version0-2-html-markdown/326
這樣的話,html的富文字就可以在頁面上正常顯示了。這樣,我們的任務也就完成了
專案已上傳到github: https://github.com/xianyulaodi/cnodeLittleProgram
總結:因為獲取的AppID是沒有交錢的,所以不能正常的釋出。不過可以用來上手。總體下來, 小程式入門不難,大部分時間還是看文件為主,最好的學習方式是把對著demo來看文件,或者對著文件來看demo,然後自己再模仿寫一個。可以模板cnode,豆瓣,知乎日報這些,因為這些有開放的API可以拿來用。
不過怎麼說呢, 個人覺得,小程式還是不能取代原生app的,除了剛出來那會被刷爆朋友圈之外,現在感覺冷下來了,而且還有挺多坑沒有填完,所以不用急著去玩小程式,搞好我們前端的基礎才是最重要的。