2天入门小程序开发

前言

  当下的前端业态正在朝多端化发展,小程序和诸多跨平台的架构(ReactNative、Weex、Flutter)开发逐渐成为大公司的必备选项。作为前端从业者,除了传统的web开发工具集,我们也需要掌握一定的跨端开发能力,以适应技术潮流的发展。在此我将通过一个简单的例子,展示微信小程序的基本开发流程。

小程序开发概述

小程序优缺点

  作为一个有一定学习门槛的新平台,小程序必然要给我们带来一定的收益才能说服程序员们啃这块骨头。

  • 小程序首先是一个半原生的平台,能够通过微信app作为中间层,调用部分原生的接口,你能想像仅使用js来实现扫描二维码的功能吗?通过调用微信小程序封装好的api,开发者可以十分方便地使用一些常用功能,比如地图定位,搜索等等,还可以通过使用小程序内置的各种组件,直接让用户获取类似于原生的体验,同时也不用担心在android和ios系统下的兼容性问题。
  • 微信是当下中国最具国民性的应用。小程序作为微信的亲儿子,天然具有引流属性,与用户更近,你很难想象用户为了一些十分简单的需求而去专门下载一个app,而h5在使用智能手机原生特性上有先天不足,同样不适合微应用场景。小程序灵活轻便,即用即丢。小程序的功能通常能够满足绝大多数公司的需求,作为微信生态的重要组成部分,小程序自带用户验证,微信支付等重要入口,接入简单,极大降低了开发成本。

  所有的优缺点都是相对于特定的应用场景而言的。小程序有什么样的不足呢?

  • 与传统js开发不同,小程序使用双线程的架构,小程序的逻辑部分和渲染部分是分成两个线程的,二者之间的状态和UI同步具有一定的成本,在某些极端情况下存在性能瓶颈(比如超长列表的状态刷新),同时由于它的小,必然不可能实现十分复杂的功能,普通微信小程序的主包大小不能超过2M,哪怕采取分包策略,打包后的体积也是有上线的。
  • 由于背靠微信,就意味着必然受到微信官方平台的很多限制,在获取用户信息上被严格限制,很多好用的api只对微信自己或者部分大厂开放,普通开发者不能调用(个人注册的小程序甚至不能使用webView),开发的灵活性收到很大限制(既想享受原生的体验,又想避免跨平台的兼容问题,笔者推荐flutter,后续也会出相关的文,待更)。

  闲言少叙,我们接下来进入实战环节。

准备开发环境、了解项目结构

  首先下载微信小程序开发者套件,目前仅支持macOS和windows系统。下载完毕后进行安装,打开开发者工具,新建一个项目,此时要填写AppId,我们可以直接选择点击测试号,进入下一步,如果要开发自己的上线小程序,就需要在微信公共平台注册自己的小程序id,填写在AppId处:

新建项目后,会得到如下界面,这是一个小程序的默认项目,大家可以先体验下代码:
编辑器面板

  微信小程序的开发基于js(现也支持TypeScript),代码的组织方式十分类似Vue,开发流程类似标准的前端工作流,即js+html+css。不过在微信小程序里面,微信使用wxml文件替换html文件,wxss替换css文件,分别控制小程序的文档流和对应样式。我们首先来观察下项目的目录结构:
项目结构
  以app开头的文件是项目的入口文件,必须在项目的根目录下。app.js为项目的代码逻辑入口,app.json则放置项目的公共配置,这两个都是必须存在的文件,app.wxss控制项目的公共样式,是可选项。project.config.json是项目的配置文件,sitemap.json用来配置小程序及其页面是否能被微信索引。
  我们首先查看app.js文件:

//app.js
App({
  onLaunch (options) {
    // Do something initial when launch.
  },
  onShow (options) {
    // Do something when show.
  },
  onHide () {
    // Do something when hide.
  },
  onError (msg) {
    console.log(msg)
  },
  globalData: 'I am global data'
})

  小程序和Vue以及react等知名框架一样,也有自己的生命周期,在其中可以注册各种各样的的事件。App方法类似于c语言中的main函数,是整个程序的入口。
接下来我们查看app.json文件:

{
  "pages": [
    "pages/index/index",
    "pages/logs/index"
  ],
  "window": {
    "navigationBarTitleText": "Demo"
  },
  "tabBar": {
    "list": [{
      "pagePath": "pages/index/index",
      "text": "首页"
    }, {
      "pagePath": "pages/logs/logs",
      "text": "日志"
    }]
  },
  "networkTimeout": {
    "request": 10000,
    "downloadFile": 10000
  },
  "debug": true,
  "navigateToMiniProgramAppIdList": [
    "wxe5f52902cf4de896"
  ]
}

pages标识项目的所有路由,我们可以轻易知道各个路由下的入口文件在哪里。其他的选项主要控制页面的样式,详见官方文档,配置小程序
  pages文件夹下存放的是小程序的路由。与app.json中pages属性相对应。接下来我们将进入一个具体的路由页分析文件结构,单个路由的文件夹下的文件同根目录下的文件作用类似,index.js控制主逻辑,里面包含该路由下会用到的公共数据和方法,index.json控制路由页的相关配置。index.wxml类似于html,里面有页面的相关内容,通过小程序自己的一套标签来绘制页面,index.wxss则对标css,里面主要负责样式控制。在任何一个平台或框架下,状态控制都是开发者最需要关注的问题之一,小程序的转态同步主要通过this.setData方法完成。具体的解析将在项目实战部分讲解。

项目实战

  我们将通过一个简单的例子来作为实战项目。小程序识别码放在文末。这个是笔者自己做的一个小程序demo, 主要功能是计算房屋贷款每月的还款额,可选择还款方式,设置年限、利率以及贷款总额。以下是主页面截图:
项目主页面
该项目只有一个路由页,放在pages/index目录下。首先我们点开index.wxml文件。

<!--index.wxml-->
<view class="container">
  <view class='main-container'>房贷计算器</view>
  <view>
    //  通过radio控制还款方式
    <radio-group data-type='loanIn' class="con-flex" bindchange="bindInput">
      <view class='hkFun'>还款方式</view>
      <label class="radio" wx:for="{{loanParten}}">
        <radio value="{{item.name}}" checked="{{item.checked}}"/>{{item.value}}
      </label>
    </radio-group>
  </view>
  //  通过input组件完成贷款金额等的输入和数据绑定
  <view class='con-flex input-padding'>
    <view>贷款金额</view>
    <view class='con-flex'>
      <input data-type='capital' type='digit' bindinput='bindInput' value='{{capital}}' 
       class='con-input' placeholder='请输入贷款金额'></input>
      <view>万</view>
    </view>
  </view>
  
  <view class='con-flex input-padding'>
    <view>贷款年限</view>
    <view class='con-flex'>
      <input data-type='year' type='digit' bindinput='bindInput' value='{{year}}' 
        class='con-input' placeholder='请输入贷款年限'></input>
      <view>年</view>
    </view>
  </view>

  <view class='con-flex input-intetrest'>
    <view>贷款年利率</view>
    <view class='con-flex'>
      <input data-type='interestRate' type='digit' bindinput='bindInput' value='{{interestRate}}' 
        class='con-input' placeholder='请输入贷款年利率'></input>
      <view>%</view>
    </view>
  </view>
  //  计算利息总额
  <view class='con-flex cum-height'>
    <button class='button' type="primary" size="mini" bindtap="primary"> 计算 </button>
    <view class='allInt'>总利息{{allInterest}}万</view>
  </view>
  //  绘制可滚动的表单,展示每月还款明细
  <view class='left-content'>
    <view class='scroll-title'>
      <view class='title-item title-qi'>期数</view>
      <view class='title-item title-int'>月供</view>
      <view class='title-item title-int'>月供本金</view>
      <view class='title-item title-int'>月供利息</view>
      <view class='title-item'>本金余额</view>
    </view>
    <scroll-view scroll-y class='scroll-content'>
      <view class='con-flex font-item' wx:for='{{detail}}'>
        <view class='item-moun'>{{index + 1}}</view>
        <view class='item-content'>{{item.allSpendMounth}}</view>
        <view class='item-content'>{{item.cap}}</view>
        <view class='item-content'>{{item.interest}}</view>
        <view class='item-content-last'>{{item.remainCap}}</view>
      </view>
    </scroll-view>
  </view>
</view>

  这里代码的组织形式同Vue非常类似,我们来分析如下的代码段:

    <radio-group data-type='loanIn' class="con-flex" bindchange="bindInput">
      <view class='hkFun'>还款方式</view>
      <label class="radio" wx:for="{{loanParten}}">
        <radio value="{{item.name}}" checked="{{item.checked}}"/>{{item.value}}
      </label>
    </radio-group>

  radio-group这里表示一个标签类型,微信会渲染出一个基于平台的radio组件,为了统一不同机型和系统的组件UI,小程序对于很多的原生组件都进行了封装,以此来保证用户体验统一,但这也导致了开发者对组件进行二次开发相对比较困难。radio-group标签内有多个属性,data-type指明了组件的初始值,bindchange指明了组件发生改变后的回调。这些方法的实现和初始值的定义都在同一目录下的index.js文件中。label标签中使用wx:for来渲染一个数组内容,需要读取变量的内容使用两个大括号进行包裹。这里通过radio组件来控制计算器的还款方式。view即视口组件,类似于div。该文件绘制了房贷计算器会用到的所有输入控制器,同时下半部分通过一个scroll-view展示了具体某个月份的还款数据。关于更多原生组件的信息,请查阅官方文档:小程序组件,wxml文件的组织方式同vue非常接近,使用过vue框架的开发者可以快速上手。

  接下来我们移步index.js文件:

//index.js
//获取应用实例
const app = getApp()

Page({
  //  给路由下的数据
  data: {
    userInfo: {},
    hasUserInfo: false,
    //canIUse: wx.canIUse('button.open-type.getUserInfo'),
    // 还款方式数组,供radio-group渲染使用
    loanParten: [
      { name: 'capital', value: '等额本金' }, 
      { name: 'interest', value: '等额本息', checked: true }
    ],
    //  每个月的还款细节,使用数组来保存
    detail: [],
    //  还款方式
    loanIn: 'interest',
    //  贷款本金
    capital: 300,
    //  贷款年限
    year: 30,
    //  总利息
    allInterest: 0,
    //  利率
    interestRate: 4.9,
    getnum: () => 3,
  },
  //  计算明细
  primary:function() {
    let obj = '';
    if (this.data.loanIn === 'interest') {
      obj = this.fillInterest();  
    } else {
      obj = this.fillCapital();
    }
    this.setData(obj);
  },
  //  输入回调
  bindInput: function(e) {
    let target = {};
    let value = e.detail.value;
    let key = e.currentTarget.dataset.type;
    if (key === 'loanIn' && value !== this.data.loanIn) {
      target = Object.assign(target, value === 'interest' ? this.fillInterest() : this.fillCapital());
    }
    target[key] = value;
    this.setData(target);
  },
  //  换算输入参数
  getProps: function() {
    return {
      mounth: this.data.year * 12,
      mounthRate: this.data.interestRate / 1200,
      capital: this.data.capital * 10000
    }
  },
  //  计算一个月的还款
  computeOneMounth: function() {
    let { mounth, mounthRate, capital } = this.getProps();
    return (capital * mounthRate) * Math.pow((1 + mounthRate), mounth) / (Math.pow((1 + mounthRate), mounth) - 1);
  },
  //  数据规整
  treatNum: function(num) {
    return parseFloat(num).toFixed(2)
  },
  //  等额本息计算
  fillInterest: function() {
    let { mounth, mounthRate, capital } = this.getProps();
    let yuan = this.computeOneMounth();
    let allInterest = 0;
    let ans = new Array(mounth).fill('').map((item, index) => {
      let int = capital * mounthRate;
      capital = capital - yuan + int;
      allInterest += int;
      return {
        allSpendMounth: this.treatNum(yuan),
        interest: this.treatNum(int),
        cap: this.treatNum(yuan - int),
        remainCap: this.treatNum(capital)
      }
    })
    return {
      detail: ans,
      allInterest: (allInterest / 10000).toFixed(2)
    }
  },
  //  等额本金计算
  fillCapital: function() {
    let { mounth, mounthRate, capital } = this.getProps();
    let allInterest = 0;
    let singleCap = capital / mounth;
    let allCap = 0;
    let ans = new Array(mounth).fill('').map((item, index) => {
      let interest = (capital - allCap) * mounthRate;
      let allSpend = singleCap + interest;
      allCap += singleCap;
      allInterest += interest;
      return {
        allSpendMounth: this.treatNum(allSpend),
        interest: this.treatNum(interest),
        cap: this.treatNum(singleCap),
        remainCap: this.treatNum(capital - allCap)
      }
    })
    return {
      detail: ans,
      allInterest: parseFloat(allInterest / 10000).toFixed(2)
    }
  },
  //  生命周期函数
  onLoad: function() {
    this.setData(this.fillInterest());
  }
})

  如果需要使用根目录下app.js入口文件中的全局变量或方法,这里可以使用getApp方法获取实例。Page方法接受一个对象作为参数,该对象中定义了该路由下会使用到的数据(状态)和方法。data属性记录下路由的所有状态,其余的自定义属性都是在index.wxml中会调用的方法。可在index.wxml中一一查看对比在这里还可以定义该路由页的生命周期函数,比如onLoad等。至此我们的房贷计算器小程序大致完成。接下来需要做的就是上传我们的代码,然后发布。微信官方针对小程序的分发和更新有自己的一套策略,普通开发者不用在意具体细节。由于省略了发版,运维,服务器部署等等环节,小程序对于个人开发者部署自己的小应用十分的友好。

后记

  获取AppId,小程序的发布,后台数据的查看以及部分物料(小程序码等)的下载,都需要登录微信公众号平台。微信公众号平台,如果没有账号的话,按照微信平台的要求申请一个。
微信公众号平台

如有任何疑问,欢迎留言交流~
————————————————————————————————————
文中小程序例子:
小程序识别码
项目代码: 项目地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
课程介绍 本套课程从技术理念到项目实践,教大家系统掌握ARKit技术开发,随心打造iOS端AR增强现实应用。由一开始的开发环境搭建,到Unity ARKit Plugin、ARFoundation ARKit等不同时期技术的讲解。从平面模型放置、识别图片、手势交互、3D物体识别、面部AR贴纸、光照估计、环境探针、多人AR技术,甚至包含ARKit3.0的动作捕捉技术等。除了以上课程内容,更加入了随着技术更新与时俱进更新的ARKit连载技术教学内容。课程收益 轻松理解ARKit的技术原理,从零到一创建自己的第一个AR项目。学习UnityARKit Plugin经典技术,了解ARKit中的常见概念和原理。学会在 ARFoundation 中使用ARKit,进行企业级AR项目开发。学会如何在AR项目里播放模型动画,通过触屏手势交互实现模型的旋转和缩放。 了解ARKit的图片识别,掌握AR卡片、AR书籍的实现方法。 学会使用面部增强技术,实现热门短视频应用的AR贴纸效果,实现面部表情追踪。学会使用ARKit物体检测技术,实现3D物体识别,可以广泛应用于工业、建筑、古董、玩具手办、艺展览等不同场景。学习ARKit中的经典交互案例,优化AR项目的用户体验。熟练使用环境纹理、光照估计技术,让AR内容随当前现实场景自动变化调节,看起来更加真实。基于WorldMap、CollaborativeSession AR技术,实现AR场景的持久化及多人AR体验效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值