微信小程序.jpg
## 微信小程序
> 小程序是一种新的开放能力,开发者可以快速地开发一个小程序。小程序可以在微信内被便捷地获取和传播,同时具有出色的使用体验。
> 本人是一名忠实的Android研发,没有出过轨,对于css html js等仅仅是一知半解,这是在业余之际觉得想接触一下web,其实刚出来小程序那时候就尝试过,不过由于工作较忙,中途放弃了,如今小程序发展的还是挺快的,还是特别想学下前端知识.一是总结,二是分享给有需要的人,节省时间,少百度一些.
不说废话,直接说有用的,开始吧.
------
#### 申请帐号
1. 注册:[小程序注册](https://mp.weixin.qq.com/wxopen/waregister?action=step1)(不能是微信开放平台的邮箱)
2. 登录后, 我们可以在菜单 “设置”-“开发设置” 看到小程序的 **AppID** 。

#### 安装开发工具
1. 前往 [开发者工具下载页面](https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html?t=2018327) ,根据自己的操作系统下载对应的安装包进行安装.
2. 打开小程序开发者工具,用微信扫码登录开发者工具
3. 选择**小程序**项目类型

4. 填入你申请的APPID 会自动生成一个QuickStart Project 直接进入即可看到一个简单的小程序

5. 看看项目结构 挺清晰的.

6. 至此,第一个小程序已经呈现在你面前,开发工具顶部栏有预览,你可以用手机扫描体验一下.
------
#### 编辑器选择
> 经过一顿百度和前端的朋友咨询,发现了目前网上流行的几款: 微信开发工具、VSCode、Subline、webstom......说多无益,我们就选朋友推荐的VSCode 其他的没用过,暂时不进行对比了.
- 当然了 我们是进行微信小程序开发,而且是没有前端基础的,所以建议先在微信开发工具中进行开发
- 如果喜欢其他编辑器也可以[下载 VScode](https://code.visualstudio.com/) 里面有插件商店,提供各种插件,挺好的,主要是免费.
#### UI组件库使用
这里说明下为什么要有使用这个,正所谓站在前人的肩膀上,能够看的更远,看到的东西更多,省去了你在造轮子了,
为了更快更好的开放一款自己的小程序,对于UI有强烈要求的就要用到别人写好的组件库了,不为什么,因为我不懂前端,让我自己写要学基础好几天,不过话说回来,基础还是要学的,这里只是想最快速度了解前端和小程序开发整体
- 原生组件库 微信本身提供的一套基础组件 官方教程有详细文档
- WeUI 同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信 Web 开发量身设计
- MinUI 第三方基于规范的小程序组件库,简洁、易用、工具化,并支持wepy和组件化方案等
- ZanUI 第三方的一个颜值高、好用、易扩展的微信小程序 UI 库
#### 立项
> 如果你有其他语言的开发基础,那么可以直接进行开发,别怕,我们边做边学,我用了一个星期搞定,你也可以3天或者1天.下面拿我的练习项目为例 《[学安卓](https://github.com/jingyc0305/wxsmalldemo)》数据来源 鸿洋大神的网站API 《[玩安卓](http://www.wanandroid.com/)》用于搜集安卓技术文章及众多实用工具的,很方便,详细API可以查看[玩安卓的API文档](http://www.wanandroid.com/blog/show/2)
下面我们就开始第一个页面的开发 这是效果图 功能很简单,banner+列表
##{% image https://user-gold-cdn.xitu.io/2018/4/2/16284f63e0a70d6f?w=399&h=710&f=png&s=111591 '1.png' '' %}
#### 页面的生命周期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| Page({ /** * 页面的初始数据 */ data: {}, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) {}, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () {}, /** * 生命周期函数--监听页面显示 */ onShow: function () {}, /** * 生命周期函数--监听页面隐藏 */ onHide: function () {}, /** * 生命周期函数--监听页面卸载 */ onUnload: function () {}, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () {}, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () {}, /** * 用户点击右上角分享 */ onShareAppMessage: function () {} })
|
#### 首页
##### 1.首页banner
1 2 3 4
| http://www.wanandroid.com/banner/json 方法:GET 参数:无
|
可直接点击查看示例:<http://www.wanandroid.com/banner/json>
##### 2.首页文章列表
1 2 3 4
| http://www.wanandroid.com/article/list/0/json 方法:GET 参数:页码,拼接在连接中,从0开始。
|
可直接点击查看示例:<http://www.wanandroid.com/article/list/1/json>。
注意:页码从0开始,拼接在链接上。
其中有两个易混淆的字段:
1 2
| "superChapterId": 153, "superChapterName": "framework", // 一级分类的名称
|
superChapterId其实不是一级分类id,因为要拼接跳转url,内容实际都挂在二级分类下,所以该id实际上是一级分类的第一个子类目的id,拼接后故可正常跳转。
------
**附上index.wxml参考代码:**

**附上index.js参考代码:**
- data里是数据绑定的关键,即布局中定义的变量和这里都是对应的,当这里的值被赋值或变更,影响页面更新.
- 使用方法 变量名:默认值 如:imgUrls: []
- `imgUrls:[] 为banner的数组来源,在布局wxml中可以找到 在wxml中一定是{{}}双层大括号才可以.`
- block为块 具体查看文档介绍
- wx:for为循环列表对应的数据源 在小程序中即为数组对象
- wx:key 为每个item的唯一标识
- `item变量代指为循环列表默认的其中的元素对象 也可以指定名称 如:wx:for-item="{{banner_item}}"`

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
| //获取应用实例 var app = getApp() Page({ data: { imgUrls: [], mode: 'aspectFill', indicatorDots: true, autoplay: true, interval: 3000, duration: 1000, articals: [], curPage: 1, perPageSize: 20, pageCount: 59, isHideLoadMore: false, loadingMoreHidden: true, dir:'top', item_content_dir:'between', likesrc:'../images/index/like_normal.png' }, //进入文章详细页面 goToArticalDetail: function (e) { var that = this var item_index = parseInt(e.currentTarget.dataset.index) console.log("item_index = " + item_index) wx.navigateTo({ url: '../index-detail/index-detail?title=' + that.data.articals[item_index].title + '&link=' + that.data.articals[item_index].link }) }, onLoad: function () { console.log('onLoad') //显示标题菊花 wx.showNavigationBarLoading() //获取轮播图 this.getBanners() //默认加载第0页 var curPage = 0 //获取文章列表 this.getArticals(curPage) }, onPullDownRefresh: function () { this.data.curPage = 0 this.getArticals(0) console.log('下拉刷新') }, onReachBottom: function () { console.log('加载更多') if (!this.data.loadingMoreHidden) { } else { this.getArticals(this.data.curPage) } this.setData({ loadingMoreHidden: true }) }, showAddItem: function () { this.setData({ addVlue: !this.data.addVlue }) }, getArticals: function (artical_pageindex) { var that = this wx.request({ url: 'http://www.wanandroid.com/article/list/' + artical_pageindex + '/json', data: { }, method: 'GET', header: { 'content-type': 'application/json' }, success: function (res) { wx.hideNavigationBarLoading() that.setData({ perPageSize: res.data.data.size, curPage: res.data.data.curPage, pageCount: res.data.data.pageCount }) var articalsTemp = that.data.articals if (that.data.curPage == 1) { articalsTemp = [] } var articals = res.data.data.datas if (articals.length < that.data.perPageSize) { console.log('没有更多了') that.setData({ articals: articalsTemp.concat(articals), loadingMoreHidden: false }) } else { console.log('有更多可加载') that.setData({ articals: articalsTemp.concat(articals), loadingMoreHidden: true, curPage: that.data.curPage + 1 }) } } }) }, getBanners: function () { var that = this wx.request({ url: 'http://www.wanandroid.com/banner/json', data: { }, method: 'GET', header: { 'content-type': 'application/json' }, success: function (res) { wx.stopPullDownRefresh() that.setData({ imgUrls: res.data.data }) } }) }, //添加文章到我的收藏 onClickAddLike: function(){ } })
|
**index.wcss参考GitHub源代码:**
**附上index.json参考代码:**
说明: 我项目中的UI组件库引用了MinUI和WeUI,具体使用参照
[MinUI组件库仓库地址]: https://github.com/meili/minui
[Min-Cli使用手册地址]: https://meili.github.io/min/docs/install/index.html
1 2 3 4 5 6 7 8 9
| { "navigationBarTitleText": "玩安卓", "usingComponents": { "wxc-toast": "../../dist/packages/@minui/wxc-toast/dist/index", "wxc-icon": "../../dist/packages/@minui/wxc-icon/dist/index", "wxc-label": "../../dist/packages/@minui/wxc-label/dist/index", "wxc-flex": "../../dist/packages/@minui/wxc-flex/dist/index" } }
|
[WeUI组件库仓库地址]: https://github.com/Tencent/weui


将下载的weui.wxss文件放至项目的根目录下 在app.wxss文件中 @import 'weui.wxss'即可使用了.
------
#### 底部tabBar
在app.json中配置即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| "tabBar": { "selectedColor": "#69C3AA", "list": [ { "pagePath": "pages/index/index", "text": "首页", "iconPath": "pages/images/nav/home_normal.png", "selectedIconPath": "pages/images/nav/home_select.png" }, { "pagePath": "pages/nav/nav", "text": "导航", "iconPath": "pages/images/nav/nav_normal.png", "selectedIconPath": "pages/images/nav/nav_select.png" }, { "pagePath": "pages/project/project", "text": "项目", "iconPath": "pages/images/nav/project_normal.png", "selectedIconPath": "pages/images/nav/project_select.png" }, { "pagePath": "pages/hierarchy/hierarchy", "text": "体系", "iconPath": "pages/images/nav/tool_normal.png", "selectedIconPath": "pages/images/nav/tool_select.png" }, { "pagePath": "pages/mine/mine", "text": "我", "iconPath": "pages/images/nav/mine_normal.png", "selectedIconPath": "pages/images/nav/mine_select.png" } ] }
|
#### 网络请求
示例代码
说明:
- url:为请求接口
- data:请求参数
- method: 请求方式
- header:请求头
- success:function(res){}请求回调函数 一般在这里进行数据绑定赋值 达到页面更新
- that.setData{()} 赋值data中的变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| wx.request({ url: 'http://www.wanandroid.com/banner/json', data: { }, method: 'GET', header: { 'content-type': 'application/json' }, success: function (res) { wx.stopPullDownRefresh() that.setData({ imgUrls: res.data.data }) } })
|
#### 页面跳转及参数传递
示例代码
说明:
`item_index:e.currentTarget.dataset.index 获取item下标索引 对应wxml中 data-index="{{index}}"`
wx.navigateTo({})页面跳转
url:'path?xxx=xxx&xxx=xxx....' 页面路径+参数拼接
options.xxx 参数接收 在onload中
1 2 3 4 5 6 7 8 9
| //进入文章详细页面 goToArticalDetail: function (e) { var that = this var item_index = parseInt(e.currentTarget.dataset.index) console.log("item_index = " + item_index) wx.navigateTo({ url: '../index-detail/index-detail?title=' + that.data.articals[item_index].title + '&link=' + that.data.articals[item_index].link }) },
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var that = this var title = options.title var link = options.link that.setData({ artical_title: title, artical_link : link }) //动态设置页面标题---文章标题 wx.setNavigationBarTitle({ title: that.data.artical_title }) },
|
#### 下拉刷新/上拉加载更多
1.在app.json中加入开关 只有打开开关 生命周期函数才会被调用
> 在这里说明一个容易犯错的就是创建page的时候会自动生成四个文件,js文件中也会自动生成模板代码 生命周期函数都会自动生成,千万不要自己去在写一个 否则不报错 也不触发.
1 2 3 4 5 6 7 8 9 10 11
| "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#69C3AA", "navigationBarTitleText": "玩安卓", "navigationBarTextStyle": "white", <!--打开下拉刷新--> "enablePullDownRefresh": true, <!--打开上拉加载更多--> "onReachBottomDistance": true, "backgroundColor": "#69C3AA" },
|
1 2 3 4 5
| onPullDownRefresh: function () { this.data.curPage = 0 this.getArticals(0) console.log('下拉刷新') },
|
1 2 3 4 5 6 7 8 9 10 11
| onReachBottom: function () { console.log('上拉加载更多') if (!this.data.loadingMoreHidden) { } else { this.getArticals(this.data.curPage) } this.setData({ loadingMoreHidden: true }) },
|
2.主要的上拉加载逻辑控制在getArticals()f方法里处理的 我们慢慢分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| getArticals: function (artical_pageindex) { var that = this <!--请求文章列表数据--> wx.request({ url: 'http://www.wanandroid.com/article/list/' + artical_pageindex + '/json', data: { }, method: 'GET', header: { 'content-type': 'application/json' }, success: function (res) { wx.hideNavigationBarLoading() that.setData({ perPageSize: res.data.data.size, curPage: res.data.data.curPage, pageCount: res.data.data.pageCount }) <!--上拉加载更多的关键处理--> <!--定义一个新的文章对象数组 用于装载拼接所有页的数据--> var articalsTemp = that.data.articals <!--当前如果处于第一页 那么清空这个对象数组 只装载第一页数据即可--> if (that.data.curPage == 1) { articalsTemp = [] } <!--定义一个新的文章对象数组 赋值于请求返回对应页码的文章数据--> var articals = res.data.data.datas <!--判断,如果返回的某页的数据长度小于每页的数据长度 说明当前加载的页是最后一页了--> if (articals.length < that.data.perPageSize) { console.log('没有更多了') that.setData({ <!--contcat 意思是向articalsTemp数组中添加数组 --> articals: articalsTemp.concat(articals), loadingMoreHidden: false }) } else { <!-否则 当前不是最后一页,向articalsTemp数组中添加数组 --> console.log('有更多可加载') that.setData({ articals: articalsTemp.concat(articals), loadingMoreHidden: true, <!--当前页码增加1 依次类推--> curPage: that.data.curPage + 1 }) } } }) },
|
#### 自定义组件
- 创建自定义组件 与创建普通页面类似 也包含.js .json .wxml .wxcss四个文件
- 修改.json文件组件属性
1 2 3 4
| { "component": true, "usingComponents": {} }
|
- 编写wantab.js 附上wantab.js源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| // dist/wantab.js Component({ /** * 组件的属性列表 */ properties: { //标题列表 tablist: { type: Array, value: [] }, currentTab: { type: Number, value: 0, observer: function (newVale, oldVal) { this.setData({ currentTab: newVale }) } }, tabname: { type: String, value: '' }, tabtype: { type: Number, value: '' } }, /** * 组件的初始数据 */ data: { }, /** * 组件的方法列表 */ methods: { onClickNavBar: function (e) { this.triggerEvent('changeTab', { currentNum: e.currentTarget.dataset.current }) } } })
|
- 编写wantab.wxml 附上wantab.wxml 模板代码
- 编写wantab.js 附上wantab.wxcss 组件样式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| /* dist/wantab.wxss */ .scroll-view-x{ background-color: #fff; white-space: nowrap; position:fixed; z-index:10; top:0 } .scroll-view-x .scroll-view-item{ display:inline-block; margin:0 35rpx; line-height: 33px; cursor: pointer; } .on{ border-bottom: 2px solid #69C3AA; color: #69C3AA }
|
以上就可以完成一个组件的定义了,下面贴出使用方法
1 2 3 4 5 6
| { "navigationBarTitleText": "项目", "usingComponents": { "wantab":"../../dist/component/wantab/wantab" } }
|
> 使用方式与其他第三方的组件引入一致,在页面的.json文件中加入以上代码即可 注意路径根据项目而改变
------
#### 效果图展示
最后放上其他页面的效果图 实现过程基本差不多 刚接触web 所以多做了些重复的工作,为了更熟悉使用这些组件和交互





------
#### 完结
感谢阅读,如有不对地方请见谅.