小程序刚出来的第一天,朋友圈被刷屏了,因此趁周末也小玩了一下小程序。其实发觉搭建一个小程序不难,只要给你一个demo,而后本身不断的查看文档,基本就能够入门了,不过对于这种刚出来的东西,仍是挺多坑的,也就是文档说的bug&tipscss
本文只是搭建了cnode的首页和详情页,其余的什么我的中心啊,搜索啊,都是同样的道理,照葫芦画瓢,首页和详情页会了,其余的页面也就会了,因此其余页面我就偷懒没写了。html
为何会想到模仿cnode呢,由于这个网站有公开的API文档,调用起来方便。文档地址在这里:https://cnodejs.org/api前端
接下来,正式开始咱们的微信小程序之旅node
构建过程我这里直接列举一些连接的方式,由于想把主要的篇幅用来写程序的过程。react
一、首先你须要注册一个微信小程序的开发平台: 点这里
git
二、其次你须要完善你的信息,来获取AppID,若是没有AppID的话,微信小程序的有些功能是用不了的,我的的话是没法申请到的,要有企业的验证信息,不过能够看看这篇文章破解:点这里github
三、须要下载一个微信开发者工具:点这里json
四、前面的步骤准备好以后,开始构建咱们的项目,构建过程能够看看这篇文章:点这里小程序
这是咱们完成以后的视图微信小程序
页面分析:
咱们能够看到,页面的页脚有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 }) } })
代码有点长,不过不要紧,咱们来分析一下:
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>
其实跟咱们的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" id="{{item.id}}" >{{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); } }); }, })
咱们怎样来拿到上一个页面传过来的值呢,咱们能够在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的,除了刚出来那会被刷爆朋友圈以外,如今感受冷下来了,并且还有挺多坑没有填完,因此不用急着去玩小程序,搞好咱们前端的基础才是最重要的。