零基础开发『仿知乎』小程序具体步骤
来源:互联网 发布:中南民族大学网络 编辑:程序博客网 时间:2024/05/23 15:46
有多少人想开发个小程序,结果发现自己的基础为0.
今天,给大家分享一个励志案例:一个读大气科学、自学前端开发的妹子,因为喜欢逛知乎,自己做出了一款「仿知乎」小程序。
希望她的开发经验,能帮大家轻松愉悦地迈出小程序开发的第一步。
作者 | Rebecca Han
WEB 前端/不靠谱天气预报员/想做代码小仙女
从微信小程序开始内测到现在,我终于把自己的微信小程序 demo 完成了。
真的是墨迹完的,连我自己都佩服自己的拖延症了(懒癌少女已弃疗 ヾ(´A`)ノ゚) 总之,算是基本完成了(明明有很多组件啊、API 啊根本都没用好嘛 →_→)以及从来不写 blog 的我也出来码字啦 (ノ◕ヮ◕)ノ:・゚✧
之前有很长一段时间,我算是知乎重度依赖。所以,这次 demo 的模仿对象选择的是知乎(但是写到一半发现我这个决定坑了,这是后话)。
Demo 的界面设计以及交互设计,均来自于知乎 Android 版本。
- 工具:使用的是微信 web 开发者工具,这个工具已经全面对非邀请内测用户开放,且在持续更新中(我码代码的过程中就更新了两版,所以开发时 IDE 版本不唯一)。其实,忍受了半个小时微信的开发者工具之后,我就改在 Webstorm 中编辑了,微信工具成了运行预览的工具。不过听说 IDE 中预览的效果,也不能保证与真机一样哦~
- 设计和功能:参照的是知乎安卓版本非常之简易版,为了防止版权问题,Demo 中的 fake 数据使用的是我自己的回答。
文件构建
1. 基础文件
app.json:
{ "pages": [ "pages/index/index", "pages/discovery/discovery", "pages/notify/notify", "pages/chat/chat", "pages/more/more", "pages/answer/answer", "pages/question/question" ], "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#0068C4", "navigationBarTitleText": "知乎", "navigationBarTextStyle": "white", "enablePullDownRefresh": true }, "tabBar": { "color": "#626567", "selectedColor": "#2A8CE5", "backgroundColor": "#FBFBFB", "borderStyle": "white" "list": [{ "pagePath": "pages/index/index", "text": "", "iconPath": "images/index.png", "selectedIconPath": "images/index_focus.png" }, { "pagePath": "pages/discovery/discovery", "text": "", "iconPath": "images/discovery.png", "selectedIconPath": "images/discovery_focus.png" }, { "pagePath": "pages/notify/notify", "text": "", "iconPath": "images/ring.png", "selectedIconPath": "images/ring_focus.png" }, { "pagePath": "pages/chat/chat", "text": "", "iconPath": "images/chat.png", "selectedIconPath": "images/chat_focus.png" }, { "pagePath": "pages/more/more" "text": "" "iconPath": "images/burger.png" "selectedIconPath": "images/burger_focus.png" }] }, "networkTimeout": { "request": 10000, "downloadFile": 10000 }, "debug": true}
app.jso
n
文件中是对整个小程序的全局配置,主要用到的字段有pages
,window
,tabBar
,networkTimeout
。
pages
字段:所有小程序的页面都要在该字段中注册,该字段数组中的第一个 page 默认为小程序首页(设置 tab 除外),没有在 pages 字段注册过的页面貌似不能够进行有效的编译(之前版本的编辑器没有这个限制,只是会影响配置文件等的生效,编辑器更新后会报未注册的错误)。window
字段:大多是关于小程序顶部 navigationbar 的一些设置。tabBar
字段:如果你需要首页底部带 tabbar 的样式,那么就在 tabBar 字段中设置每个 tab 对应的页面,按顺序对应左至右,包括路径、tab 文字、tab 图标和选中状态图标。networkTimeout
:设置网络超时时间。d
ebug
:开启 debug 模式。
app.wxss
文件中为全局样式,也就是说这个文件中的样式在所有的 pages 中均可使用。若其他页面文件的 WXSS 中定义了与该样式文件中相同的属性,则该文件中的样式被覆盖,规则与 CSS 优先规则大致相通。
app.js
用于调用 login
接口、回调、周期函数、本地存储等等逻辑代码。
2. 页面文件
页面文件由四部分组成。
例如,我们有一个首页叫做 index
,则需要在 pages
文件夹下创建文件名相同的三个必要文件:
index.wxml
index.wxss
index.js
另外 index.json
文件为可选,功能与 app.json
相同,为该页面的配置文件,但定义功能有限。
3. UI
跟平时开发一样,最开始当然是码 UI。
除了需要依照微信的一些新的标签和样式规则,其他与平时码 UI 并没有太大的不同。
而且需要强调的是,flex
布局在微信小程序中 hin~~~~好用
不过,同时作为女生和程序员,不挑刺可就不是我了,所以下面列举了一些我遇上的坑,其中有些也许不正确(多多包涵啦\(//∇//)\),有些也许已在 IDE 更新中修正:
- 有一些 CSS 样式在微信 IDE 中不支持,例如
font-weight
、letter-spacing
(以及调整字间距的样式)等; <text/>
不支持嵌套,<text/>
两层嵌套的结构下,内层中的内容会连续显示两次(在 IDE 后续更新中已修正);- 若
<
view/>
与<text/>
同级,则在实际使用中,<view />
会遮住<text />
。为了防止内容相叠,必须使用<view/>
相并列。所以并不像某些地方说的,可以完全地把<view/>
当做<div>
去使用! - 元素之前有垂直相邻 margin 的时候,在微信小程序中会 double 显示,即两个元素的 margin 均摊开,不遵循 margin 折叠规则;
- 标签
hidden
属性无效(v0.10.101400 中已修正); - 部分情况下,平级元素标签优先级会出现问题。比如, 平级标签 A 与 B,当 B 通过某些调整向 A 元素位置相叠的时候,微信 IDE 解析出的效果是 A 的内容和背景色会覆盖 B 元素与之重叠的部分(普通浏览器解析应该是 B 覆盖 A);
- 如果用模板+列表渲染的方式来渲染数据的话,在模板中使用列表渲染的
{{item}}
是无效的,无法被正确识别。所以,列表渲染的时候,要把复用的部分写在列表渲染的代码块内(属于数据渲染部分,后面会提到)。
在后来,微信 IDE 的迭代中已经将上面清单中的一些问题修正了,所以这份清单有可能是过时的。大家也可以根据实际情况,自行尝试。
接下来,我将对于一些 demo 中写到用到的部分进行说明。
开始实战开发
1. 列表式的数据渲染
类似于「首页」以及「发现页」这种标准列表式的数据展现方式,微信提供了很好的方案:列表渲染。
<block wx:for="{{feed}}" wx:for-index="idx" wx:for-item="item" data-idx="{{idx}}"> <view class="feed-item"> <view class="feed-source"> <a class=""> <view class="avatar"> <image src="{{item.feed_source_img}}"> </image> </view> <text> {{item.feed_source_name}} {{item.feed_source_txt}} </text> </a> <image class="item-more" mode="aspectFit" src="../../images/more.png"></image> </view> <view class="feed-content"> <view class="question" qid="{{question_id}}" bindtap="bindQueTap"> <a class="question-link"> <text>{{item.question}}</text> </a> </view> <view class="answer-body"> <view bindtap="bindItemTap"> <text class="answer-txt" aid="{{answer_id}}"> {{item.answer_ctnt}} </text> </view> <view class="answer-actions" bindtap="bindItemTap"> <view class="like dot"> <a>{{item.good_num}} 赞同 </a> </view> <view class="comments dot"> <a>{{item.comment_num}} 评论 </a> </view> <view class="follow-it"> <a>关注问题</a> </view> </view> </view> </view> </view></block>
可以直观地看出,就是 for
循环用重复的结构渲染一组数据:
for="{{}}
“中的内容是想要循环的一组数据,最外层为数组结构for-item
指定数组中当前元素的变量名for-index
指定数组中当前元素下标变量名
同样也使用了 for
渲染的,还有顶部的发现页和通知页等顶部的自定义 tabbar。
2. 顶部 Tabbar 实现
微信只提供了底部 tabbar,所以顶部的要自己写喽~
顶部 tab bar 的实现在于 for
列表渲染以及 JS 配合。
实例 WXML 代码:
<view class="top-tab flex-wrp flex-tab "> <view class="toptab flex-item {{currentNavtab==idx ? 'active' : ''}}" wx:for="{{navTab}}" wx:for-index="idx" wx:for-item="itemName" data-idx="{{idx}}" bindtap="switchTab"> {{itemName}} </view></view><scroll-view scroll-y="true" class="container discovery withtab" bindscrolltoupper="upper" bindscrolltolower="lower" scroll-into-view="{{toView}}" scroll-top="{{scrollTop}}"> <view class="ctnt0" hidden="{{currentNavtab==0 ? '' : true}}"> </view> <view class="ctnt1 placehold" hidden="{{currentNavtab==1 ? '' : true}}"> <text>圆桌</text> </view> <view class="ctnt2 placehold" hidden="{{currentNavtab==2 ? '' : true}}"> <text>热门</text> </view> <view class="ctnt3 placehold" hidden="{{currentNavtab==3 ? '' : true}}"> <text>收藏</text> </view></scroll-view>
JS 代码:
//discovery.jsPage({ data: { navTab: ["推荐", "圆桌", "热门", "收藏"] , currentNavtab: "0" } , onLoad: function () { console.log('onLoad') } , switchTab: function (e) { this.setData({ currentNavtab: e.currentTarget.dataset.idx }); }});
由于微信不支持使用 DOM 访问对象,也就是不支持 dom
和 window
对象,所以 tab bar 的实现依赖于微信提供的视图层的展示逻辑,以及视图与数据之间的绑定机制。
绑定点击事件,通过改变一个 data-
属性的值,来控制元素的类的改变(从而改变样式等)。
3. 轮播图
以下是实现的 WXML 代码:
<swiper class="activity" indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}"> <block wx:for="{{imgUrls}}"> <swiper-item> <image src="{{item}}" class="slide-image" width="355" height="155" /> </swiper-item> </block></swiper>
JS 代码:
imgUrls: [ '../../images/24213.jpg' , '../../images/24280.jpg' , '../../images/1444983318907-_DSC1826.jpg'] , indicatorDots: false , autoplay: true , interval: 5000 , duration: 1000 , feed: [] , feed_length: 0
轮播图的实现使用的是微信提供的 swiper 组件,该组件贴心的提供了各种属性选择,常用的包括 autoplay
,interval 时间 duration
等
swiper-item
中包含的是所有轮播的图片,为了方便修改图片数据,同样采用 for
渲染绑定 data
的方式。
4. 下拉刷新,上拉加载,以及数据请求
刷新及继续加载的动作,依靠的是 scroll-view
标签,及配套的 upper
和 lower
事件。
标签的属性提供了 bindscrolltoupper
和 bindscrolltolower
来绑定滚动到顶部及底部所触发的事件,同时 upper-threshold
和 lower-threshold
能够调整触发时距边界的距离。
除上述之外,小程序的 API 还提供横向滚动、滚动触发事件、设置滚动条位置等接口。
<scroll-view scroll-y="true" class="container" bindscrolltoupper="upper" upper-threshold="10" lower-threshold="5" bindscrolltolower="lower" scroll-into-view="{{toView}}" scroll-top="{{scrollTop}}"> <block wx:for="{{feed}}" wx:for-index="idx" wx:for-item="item" data-idx="{{idx}}"> <view class="feed-item"> <view class="feed-source"> <a class=""> <view class="avatar"> <image src="{{item.feed_source_img}}"> </image> </view> <text> {{item.feed_source_name}} {{item.feed_source_txt}} </text> </a> <image class="item-more" mode="aspectFit" src="../../images/more.png"> </image> </view> <view class="feed-content"> <view class="question" qid="{{question_id}}" bindtap="bindQueTap"> <a class="question-link"> <text>{{item.question}}</text> </a> </view> <view class="answer-body"> <view bindtap="bindItemTap"> <text class="answer-txt" aid="{{answer_id}}"> {{item.answer_ctnt}} </text> </view> <view class="answer-actions" bindtap="bindItemTap"> <view class="like dot"> <a>{{item.good_num}} 赞同 </a> </view> <view class="comments dot"> <a>{{item.comment_num}} 评论 </a> </view> <view class="follow-it"> <a>关注问题</a> </view> </view> </view> </view> </view> </block></scroll-view>
滚动至顶或至底时,触发的加载数据的事件,本应该调用微信提供的网络请求 API 来获取数据。
但是比较坑的是,我在选择写仿知乎 demo 的时候没有注意到知乎不提供开放 API,而微信的 API 不支持直接对 JSON 文件进行本地请求。
无奈之下,选择在 JS 文件中伪造一段数据,用 module.exports
抛出,来 fake 数据请求:
upper: function () { wx.showNavigationBarLoading() this.refresh(); console.log("upper"); setTimeout(function () { wx.hideNavigationBarLoading(); wx.stopPullDownRefresh(); }, 2000);}, lower: function (e) { wx.showNavigationBarLoading(); var that = this; setTimeout(function () { wx.hideNavigationBarLoading(); that.nextLoad(); }, 1000); console.log("lower")}, //scroll: function (e) {// console.log("scroll")//},//网络请求数据, 实现刷新refresh0: function () { var index_api = ''; util.getData(index_api).then(function (data) { //this.setData({ // //}); console.log(data); });}, //使用本地 fake 数据实现刷新效果refresh: function () { var feed = util.getDiscovery(); console.log("loaddata"); var feed_data = feed.data; this.setData({ feed: feed_data , feed_length: feed_data.length });}, //使用本地 fake 数据实现继续加载效果nextLoad: function () { var next = util.discoveryNext(); console.log("continueload"); var next_data = next.data; this.setData({ feed: this.data.feed.concat(next_data) , feed_length: this.data.feed_length + next_data.length });}
由于是 fake 的数据,所以这个 demo 并没有做真实的带参跳转,查询等功能。
加载数据的同时,使用微信提供的加载动画 wx.showNavigationBarLoading();
。
5. 其他
- 为了实现点击跳转页面,使用了
wx.navigateTo
进行页面跳转以及点击事件绑定; - 部分常用组件的模块化;
input
、image
组件等的使用。
6. 后续
其实还有大量的组件和 API 还没有用过,这个 demo 也许后续还会有更新呦,这取决于懒癌少女的病情严重程度了。
一点感受
其实作为一个小前端,由于工作中的原因,使用 MVVM 其实是非常少的。
不过,写了这个微信小程序 demo 之后,更加把这方面的思维理顺了。当然,写完之后回头看,还是有超多的不足,明明好些地方能再换一种写法的。
这毕竟是我第一次尝试用新鲜热乎的东西写小 demo,也是第一次尝试写教程……或者算是记录?whatever~~
Anyway~ 希望除了写代码之外,还能在码文字的道路上也多走走吧,毕竟我是要做代码小仙女的人呀\(≧∀≦)ゞ
- 零基础开发『仿知乎』小程序具体步骤
- 小M开发_java零基础
- 小M开发_MySql零基础_day170628
- 小M开发_MySQL零基础_day170629
- 小M开发_java零基础_dya170703
- 零基础python入门:从一个小程序开始
- 小程序自学系列(零基础学小程序)---实现底部导航栏和顶部导航栏及微信开发工具常用快捷键
- 零基础小白应该怎么入门编程开发
- 小M开发_java零基础(字母金字塔案例)
- 从零学习小程序开发遇到的坑
- 【学习笔记】零基础C#窗口程序开发入门
- 小程序自学系列(零基础学小程序)---小程序实现简单的倒计时效果
- 小程序自学系列(零基础学小程序002)---小程序实现电商秒杀倒计时效果
- 零基础学小程序008----小程序列表实现+本地json数据解析渲染到小程序列表
- 零基础微信小程序视频教程
- 零基础学小程序007----小程序轮播图,自动轮播,循环轮播,定时轮播
- 小程序自学笔记(零基础学小程序汇总)---史上最全的微信小程序学习笔记,笔记看我你也就学会小程序了
- Java零基础:一步步教你如何使用eclipse创建项目及编写小程序实例
- ORACLE 查询多行转单行数据,并且用逗号分隔展示方法
- 数据结构:单链表(三)输出链表值最大的节点
- Python基础学习之函数(1)
- iOS 加速计 摇一摇
- SVD奇异值分解
- 零基础开发『仿知乎』小程序具体步骤
- 手势响应事件优先级
- j2ee打包后,ROOT
- 双向链表
- Java lock 简述
- ideallij使用备忘
- Windows和document的用法区别
- java_web 学习记录(五):ServletContext
- Java程序员修炼之道—并发编程