Words Of Life

我所理解的小程序

  • 摘要:Hackathon的见闻与微信小程序的真机初体验


前言

  • 之前一直都很想参加一场真正的黑客马拉松,奈何大部分的国内黑客马拉松都在北上杭,而我作为穷苦的学生党,没有额外的资金买车票去远方追求理想与梦想。所幸,2016年第一场在广州举办的黑客马拉松,我有幸坑了两个朋友(后端玩家Samray、Web前端玩家Nomad),一同参与其中,一天多的专注,让我有幸体验了一下未来的小程序,感触颇多,因记此文。文章前半部分叙述Hackathon相关的内容,后半部分叙述小程序相关的内容,读者若对前半部分不感兴趣,跳过即可。


    Hackathon

    Hackathon Place: GuangZhou TIT iFanr

    Hackathon Date: 2016.10.7 10:00 - 2016.10.8 15:00

    Hackathon Topic: The Future WeChat App

  • Hackathon Pre:

    • 本次Hackathon的主题要求是“未来、实用”。我个人感觉这个主题范围十分宽。思考一个多小时后,我们队伍最终选择的Hackathon Project是Pig Raising,创意参考了Forest:“在一定时间内,限制人们不能触碰手机,否则任务失败”。之所以想到这个创意,是因为我们认为小程序的弊端在于开启小程序后,微信就不能切换到聊天界面(即微信与微信小程序只能保留一个界面)。我们希望通过Pig Raising将这个弊端消除,使用Pig Raising时,目标就是不使用其他程序,所以即使保留一个界面也无妨。
    • 在开始项目前,我们三人只阅读了官方文档,而且我与另外一位朋友(Samray)都没有JavaScript的编程经验,甚至连部分语法都不太清楚,所以这个项目对我们的速学能力有蛮大的要求。
    • 最后我们决定由Nomad负责WXSS、WXML的页面部分编写,我负责JSON、JavaScript的逻辑部分编写,因为项目不需要后端环境,所以Samray负责美工及路演相关的准备。
  • Hackathon In:

    • Hackathon Environment
      • 感觉我们队伍使用的Hackathon工具相比其他队伍而言,还是比较有优势的,因此稍作讨论,希望能够给其他Hackathon Team稍作参考
        • 编程环境:macOS Sierra 10.12 + 微信Web开发者工具 + Egret Wing Verison 3.2.0
        • 同步环境:Resilio Sync Version 2.4.0 + Github
        • 环境使用:微信Web开发者工具用于动作调试,Egret Wing 3用于代码编辑 + 界面预览(官方的IDE代码编辑能力实在太差:-( )。为了省去合并的烦恼,我和Nomad是同时编辑同一个项目下的不同文件(eg:Nomad编辑index.wxss、index.wxml,我编辑index.json、index.js)。也许你会问,不用git/svn,如何同步合并代码?我们使用了Resilio Sync这个小工具。它能够在电脑上创建一块共享盘,供有同步Key的朋友访问。相比于其他工具,它的同步的速度十分快,我们把项目放在了共享盘中,基本上Nomad一编辑完wxss/wxml后几秒,我这边的项目文件中已经能看到最新的代码了。这样的短延迟完全不影响我们的编码,也省去了事后合并的烦恼。Github在我们团队中主要用来存放了一些请求资源,没有起到项目代码控制的作用。
        • 建议:在能够面对面编程的小团队(3-5人)中,感觉直接使用Resilio Sync合并代码更加有优势
    • Hackathon Coding
      • Coding:编程过程是比较枯燥的,Hackathon中后期基本完成主体功能后就感觉十分困了,后期思路也没有前期的清晰。这个项目的难点主要在于主界面的圆圈倒计时上,其次是Pig Farm界面的随机位置选择上,花了不少时间,其他部分都比较容易。编码对于我这个JavaScript小白而言,就是查文档(微信小程序文档 + JavaScript文档 + w3school资料),感觉项目的实现还是比较容易的。
  • Hackathon After:

    • 很遗憾,项目没有荣获什么奖。但是我们的队员收获都挺大的,由于iFanr提供了App ID供我们测试,因此我们也有幸感受到微信小程序的未来,以及认识了一群大神。我个人技术的提升,大概可以说是24小时JavaScript从入门到抢月饼 :-)。感觉不错,但是深感自己的JavaScript代码写的很丑,还是得多多阅读实践方可。
  • Pig Raising项目已经开源,有兴趣的朋友可以前往一试 => 传送门

    Group Photo


Wechat App

  • 小程序的开发

    • 小程序的开发成本总体而言还是比较低的,即使是像我这样不会Web前端的iOS码农,甚至对JavaScript只是一知半懂的iOS码农也能快速在1~2天内开发出一个小程序(当然,看文档时间另算)。
    • 小程序的权限目前而言感觉还是比较收的比较紧的,很多数据都不能够获取,这也暂时限制了微信小程序的应用前景,希望以后会有所放开。
  • 小程序的真机体验

    • 测试环境

      • iPhone 6S Plus
      • iOS 10
      • 中速偏慢的Wifi环境
    • 谈谈体验:总体而言,真机体验和模拟器体验是不一样的。我个人总结为以下几点:

      • 模拟器没有显示微信自动生成的导航栏
      • 模拟器的适配布局有偏移(eg:同样是iPhone 6S Plus,模拟器6SP上的(x, y)坐标与真机6SP上的(x, y)坐标有区别,有少量的偏移)
      • IDE有部分Bug,模拟器上跑的程序正常,但真机上跑的程序可能会出现Bug
      • 微信小程序1M的真机代码大小限制
    • 真机调试的坑

      • 调试的方法

        • 真机调试上也有一个类似模拟器中的控制台,同行们同样可以通过console.log()进行调试。二分法调试(注释 + 输出)应该是目前真机小程序的最好方法了。
      • 真机运行图

        • 目前真机调试的流程:在微信Web开发者工具中上传代码 => 官方自动生成一个二维码 => 只有绑定了该App ID的微信用户能够扫描该二维码 => 扫描后自动在微信中打开小程序
        • 微信导航栏左上角按钮点击后直接返回微信,右上角按钮点击后出现菜单,菜单包含(控制台,推出,取消等按钮)
        App
      • 第一次将应用弄到手机上跑的时候,主要遇到了几个神奇的Bug,在此分享一下,避免同行入坑

        • Bug 1 - IDE Bug - this.data.status

          • Bug 1 Code

            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            const STATUS_WAITING = 0 // 应用开始时状态
            const STATUS_RUNNING = 1 // 应用计时状态
            const STATUS_COMPLETED = 2 // 应用完成状态
            Page({
            data: {
            // 计时状态 - 动态
            status: STATUS_WAITING
            },
            startTimer: function (e) {
            if (status !== STATUS_RUNNING) {
            // Something
            } else {
            // Something
            }
            }
            })
        • Bug 1 Code Review

          • 这段代码仔细分析后,应该可以看出是status写错了,应该使用this.data.status获取。这其实是一个比较简单的小问题,为什么我要抽出来说呢?主要是因为这段在模拟器上是能够正常使用的(即IDE通过编译,运行也是正常的,能够触发后续事件)。但是在真机就会出现明显的Bug(卡死,即无反应)。一般而言,官方IDE在我们没有写this.data时,都是会提醒的,但是不排除像我这种特殊情况。所以,当真机调试出现迷之Bug时,不妨看看是不是这个问题。
        • Bug 1 Correct Code

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          const STATUS_WAITING = 0 // 应用开始时状态
          const STATUS_RUNNING = 1 // 应用计时状态
          const STATUS_COMPLETED = 2 // 应用完成状态
          Page({
          data: {
          // 计时状态 - 动态
          status: STATUS_WAITING
          },
          startTimer: function (e) {
          if (this.data.status !== STATUS_RUNNING) {
          // Something
          } else {
          // Something
          }
          }
          })

        • Bug 2 - Layout Change - e.target.offsetTop

          • Bug 2 Code
          1
          2
          3
          4
          5
          6
          7
          <action-sheet hidden="{{actionSheetHidden}}" bindchange="actionSheetChange">
          <block wx:for="{{actionSheetItems}}">
          <action-sheet-item class="item" bindtap="bindItemTap" data-name="{{item}}">{{item}}
          </action-sheet-item>
          </block>
          <action-sheet-cancel class="cancel">Cancel</action-sheet-cancel>
          </action-sheet>
          1
          2
          3
          4
          5
          6
          7
          8
          bindItemTap: function (e) {
          let idx = e.target.offsetTop / 38
          // 使用idx去判断点击了actionSheet中哪一个按钮
          this.setData({
          selectedTime: PIG_TIME[PIG_NAME_ARR[idx]],
          showTime: PIG_TIME[PIG_NAME_ARR[idx]] + ":00"
          })
          }
        • Bug 2 Code Review

          • 这段代码同样在模拟器上跑的好好的,但是一到真机上就出现Bug(卡死)。后来分析过后主要发现是布局不一样。同样是iPhone 6S Plus,模拟器6SP上的(x, y)坐标与真机6SP上的(x, y)坐标有区别,有少量的偏移。所以,得到的offSet不能被38整除。使用浮点数值作为数组下标值,结果可想而知。actionSheet按钮判断应使用id判断actionSheet的按钮。
        • Bug 2 Correct Code

          1
          2
          3
          4
          5
          6
          7
          <action-sheet hidden="{{actionSheetHidden}}" bindchange="actionSheetChange">
          <block wx:for="{{actionSheetItems}}">
          <action-sheet-item id="{{index}}" class="item" bindtap="bindItemTap" data-name="{{item}}">{{item}}
          </action-sheet-item>
          </block>
          <action-sheet-cancel class="cancel">Cancel</action-sheet-cancel>
          </action-sheet>
          1
          2
          3
          4
          5
          6
          7
          8
          bindItemTap: function (e) {
          let idx = e.currentTarget.id
          // 使用idx去判断点击了actionSheet中哪一个按钮
          this.setData({
          selectedTime: PIG_TIME[PIG_NAME_ARR[idx]],
          showTime: PIG_TIME[PIG_NAME_ARR[idx]] + ":00"
          })
          }

        • Bug 3 - 真机代码大小限制
          • 微信小程序限制了小程序大小为1M以内。而由于我们队伍的小程序有许多资源(音频、图片)等,所以项目文件夹的大小是远远超过了1M的。那怎么办?只有把资源文件放在后端,再进行资源请求。我们把资源放在了Github,然后在使用过程对资源进行了请求,请求后进行缓存,避免二次加载。这样做后,项目文件立刻降到了400多Kb。我觉得代码限制,这个点也是跑模拟器的时候不会注意到的。而对于部分开发者(如打算把Native app完全迁移的朋友),哪怕除去资源文件,我的纯代码就是这么大,微信不给上传,怎么办?我觉得解决方案应该能够参考iOS的热更新,把部分程序放在后端,在实际用到页面后再进行请求。

  • 小程序的应用前景

    • 作为一个希望有产品思维的iOS码农,我觉得小程序未来在部分领域是十分有潜力的,下图是我个人比较看好的小程序应用方向。我认为,小程序正正应该是“用完即走”,过多的停留还是应该留给Native App来处理。毕竟,总不可能在微信里面在造一个小微信吧:-P?

      WechatApp Application
    • Wechat App和RN,我个人感觉还是蛮大区别的,RN更多的是应用在Hybrid App中,但Wechat App由于其不能在浏览器中打开,可能更多的还是会自成一派。

    • 最后我想东拼西凑的一段话来结束这篇文章,望博君一笑:

      不懂互联网的普通人往往过高的估算小程序的价值与意义,而懂互联网的程序员往往是低估了小程序的未来价值。在我看来,唯一不变的只有变化,何不拥抱这场变化?Just Kiss The Change!


  • Last Edited:2016.10.9
  • Author:@Seahub
  • Please contact me if you want to share this Article, 3Q~
五毛也是情, 一元也是爱