微信小程序 Demo - 仿知乎

9,807 阅读8分钟
原文链接: zhuanlan.zhihu.com

从微信小程序开始内测到现在, 已经一个月过去了,终于把我自己的微信小程序 demo 墨迹完成了. 真的是墨迹完的, 连我自己都佩服自己的拖延症了(懒癌少女已弃疗*ヾ(´A`)ノ゚*), 总之算是基本完成了(明明有很多组件啊 API 啊根本都没用好嘛 →_→) 以及从来不写 blog 的我也出来码字啦 (ノ◕ヮ◕)ノ:・゚✧

之前有很长一段时间我算是知乎重度依赖, 所以这次 demo 的模仿对象选择的是知乎(但是写到一半发现我这个决定坑了, 这是后话).

demo 的界面设计以及交互设计均来自于知乎 Android 版本

(我码代码的过程中就更新了两版, 所以开发时 IDE 版本不唯一)

不过其实忍受了半个小时微信的开发者工具之后, 我就改在 webstorm 中编辑了, 微信工具成了运行预览的工具, 不过听说IDE 中预览的效果, 也不能保证与真机一样哦~

  • _设计和功能_: 知乎安卓版本 非常之简易版

  • _数据_: 毕竟是知乎, 为了防止版权问题, 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.json文件中是对整个小程序的全局配置, 主要用到的字段有pages, window, tabBar, networkTimeout.


* pages 字段: 所有小程序的页面都要在该字段中注册, 该字段数组中的第一个page 默认为小程序首页(设置tab 除外), 没有在 pages 字段注册过的页面貌似不能够进行有效的编译(之前版本的编辑器可以,只是会影响配置文件等的生效, 编辑器更新后会报未注册的错误).

* window 字段: 大多是关于小程序顶部 navigationbar 的一些设置

* tabBar字段: 如果你需要首页面底部带tabbar的样式, 那么就在 tabBar 字段中设置每个 tab 对应的页面, 按顺序对应左至右, 包括路径, tab 文字, tab图标和选中状态图标.

* netwoTimeout: 设置网络超时时间.

* debug: 开启 debug 模式.


app.wxss 文件中为全局样式, 也就是说这个文件中的样式在所有的 page 中均可使用, 若其他页面文件的 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 更新中修正

坑们:

1. 有一些 css 样式在微信 IDE 中不支持, 例如 font-weight, letter-spacing(及类似调整字间距的样式)等

2. 不支持嵌套, 两层嵌套的结构下, 内层中的内容会连续显示两次

(在 IDE 后续更新中已修正)

3. 若与在结构上并列的话, 显示上会重合, 感受上类似级别高于, 防止内容相叠, 必须使用相并列. 所以并不能像某些地方说的, 把当做

去使用!

4. 元素之前有垂直相邻 margin 的时候(符合 margin 折叠规则), 在微信小程序中会double 显示, 即两个元素的 margin 均摊开, 不遵循 margin 折叠规则.

5. 标签 hidden 属性无效 ( v0.10.101400 中已修正 )

6. 部分情况下, 平级标签 A 与 B 并列, 当 B 通过某些调整向 A 元素位置相叠的时候, 微信 IDE 解析出的效果是 A 的内容和背景色会覆盖 B 元素与之重叠的部分. ( 普通浏览器解析应该是 B 覆盖 A ).

7. 如果用模板+列表渲染的方式来渲染数据的话, 在模板中使用列表渲染的{ {item}}是无效的, 无法被正确识别, 所以列表渲染的时候要把复用的部分写在列表渲染的代码块内 ( 属于数据渲染部分, 后面会提到 )

( 待续... ... )

后面将对于一些我 demo 中写到用到的部分进行说明

列表式的数据渲染

类似于首页以及发现页这种标准列表式的数据展现方式, 微信提供了很好的方案---列表渲染

可以直观的看出, 就是 for 循环来用重复的结构渲染一组数据

  • for="{{}}"中的内容是想要循环的一组数据, 最外层为数组结构
  • for-item 指定数组中当前元素的变量名
  • for-index 指定数组中当前元素下标变量名

同样也使用了 for 渲染的还有顶部的发现页和通知页等顶部的自定义 tabbar


顶部 tabbar 实现

微信只提供了底部 tabbar, 所以顶部的要自己写喽~

顶部 tabbar 的实现在于 for 列表渲染以及 js 配合

wxml:


  
    {{itemName}}
  


  
  
  
    圆桌
  
  
    热门
  
  
    收藏
  


js:

//discovery.js
Page({
  data: {
    navTab: ["推荐", "圆桌", "热门", "收藏"],
    currentNavtab: "0"
  },
  onLoad: function () {
    console.log('onLoad')
  },
  switchTab: function(e){
    this.setData({
      currentNavtab: e.currentTarget.dataset.idx
    });
  }
});

由于微信不支持任何 dom 和 window 对象, 所以 tabbar的实现依赖于微信提供的视图层的展示逻辑, 以及视图与数据之间的绑定机制.

绑定点击事件, 通过改变一个 data- 属性的值, 来控制元素的类的改变( 从而改变样式等 )


轮播图


 
   
     
   
 


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等

中包含的是所有轮播的图片, 为了方便修改图片数据, 同样采用 for 渲染绑定 data 的方式


下拉刷新, 上拉加载, 以及数据请求

刷新及继续加载的动作, 依靠的是标签, 及配套的upper 和 lower 事件

标签的属性提供了 bindscrolltoupper 和 bindscrolltolower来绑定滚动到顶部及底部所触发的事件, 同时upper-threshold 和 lower-threshold 能够调整触发时距边界的距离

除上述之外, 还提供横向滚动, 滚动触发事件, 及设置滚动条位置等...

滚动至顶或至底时, 触发的加载数据的事件, 本应该调用微信提供的网络请求 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();

其他

  • 绑定点击事件, 进行页面的跳转wx.navigateTo
  • 部分模块化
  • input, image 组件等

后续

其实还有大量的组件和 API 还没有用过, 这个 demo 也许后续还会有更新呦, 这取决于懒癌少女的病情严重程度了


项目地址

传送门: GitHub - RebeccaHanjw/weapp-wechat-zhihu: 微信中的知乎--微信小程序 demo // Zhihu in Wechat


也许算是些感受?

其实作为一个小前端, 由于工作中的原因, 使用 MVVM 其实非常少的, 不过写了这个微信小程序 demo 之后, 更加把这方便的思维理顺了. 当然, 写完之后回头看, 还是有超多的不足, 明明好些地方能再换一种写法的. 不过毕竟是我第一次尝试用新鲜热乎的东西写小 demo, 也是第一次尝试写教程...或者算是记录? whatever~~

还有, 非项目的配图均来自网络哦~~


Anyway~ 希望除了写代码之外, 还能在码文字的道路上也多走走吧, 毕竟我是要做代码小仙女的人呀\(≧∀≦)ゞ