学习微信小程序开发的总结

291 阅读8分钟

上周学习了微信小程序的开发,这里总结一下微信小程序和原生web开发的不同,和一些微信小程序的基本开发。

1.文件后缀的不同

  1. html文件的后缀改为.wxml
  2. css文件的后缀改为.wxss

2.html结构的不同

  1. 把html,header和body标签删掉,默认外面包上page标签
  2. 微信小程序不识别原生大多数的标签
  3. 大部分块级标签(例:div,p,ul,li,)需要改为 <view></view>
  4. 大部分行内标签(例:span,i)需要改为<text></text>
  5. img标签需要改为image,且需要通过mode属性来更改图片展示的模式
  6. <a href="xxxx"></a> => <navigator url="xxxx"> </navigator>
  7. 小程序中的标签像一个组件,加上属性就可以添加对应的功能
  8. 小程序中还有很多组件标签,例:swiper(轮播图)scroll-view(可滚动视图区域)等等

3.创建页面的不同

微信小程序创建页面需要在app.js文件的pages下添加路径到数组中。还有添加底部tab栏,不同于原生web,微信小程序只需要在app.js文件tabBar下配置,可以设置其页面路径,标题,未选择和选中后的颜色和图标

4.小程序使用vant-ui

在小程序中使用vant-ui需要一些配置

  1. 初始化项目 npm init -y

  2. 安装ui库 npm i @vant/weapp -S --production

  3. 构建npm

    开发工具 => 工具 => 构建 npm

  4. 修改 app.json

    "style": "v2" 去除

  5. 导入组件

    // 修改app.json,添加以下代码 
    "usingComponents": {
        "van-button": "@vant/weapp/button/index",
         ... // 添加其它组件
    }
    

5.小程序弹窗api

小程序还提供了一些弹窗提示用户的api,在加载数据中和加载完毕后可以给用户一些弹窗信息,增强交互性

  1. showToast
    wx.showToast({
      title: '成功',
      icon: 'success',
      duration: 2000
    })
    
  2. showModal
    wx.showModal({
      title: '提示',
      content: '这是一个模态弹窗',
      success (res) {
        if (res.confirm) {
          console.log('用户点击确定')
        } else if (res.cancel) {
          console.log('用户点击取消')
        }
      }
    })
    
  3. showLoading
    wx.showLoading({
      title: '加载中',
    })
    
    setTimeout(function () {
      wx.hideLoading() //隐藏加载
    }, 2000)
    

6.生命周期

小程序有以下生命周期

  1. onLoad 生命周期函数--监听页面加载`
  2. onReady 生命周期函数--监听页面初次渲染完成
  3. onShow 生命周期函数--监听页面显示
  4. onHide 生命周期函数--监听页面隐藏
  5. onUnload 生命周期函数--监听页面卸载
  6. onPullDownRefresh 页面相关事件处理函数--监听用户下拉动作
  7. onReachBottom 页面上拉触底事件的处理函数
  8. onShareAppMessage 用户点击右上角分享

注意:

  1. onLoad 只会在小程序中执行一次,比如当前页面是 a 页面,我们在 onLoad 发送请求去获取数据,然后我们切到 b 页面,再切回 a 页面的时候,onLoad 不会再触发,也就是不会再重新发请求获取数据
  2. onShow 跟 onLoad 不同,每次切回 a 页面的时候都会触发这个生命周期函数
  3. 所以到底是在 onLoad 发请求还是在 onShow 发请求,要根据实际的业务去做

7.实战开发-发请求

在项目中我们一般在app.js中使用 promise 封装请求,在app.js下的属性和方法,其他页面都可以通过getApp()得到一个对象,这个对象里包含了app.js下的属性和方法

8.渲染页面

小程序, vue, react框架都是数据驱动视图的框架, 两层含义

  • 不需要操作dom节点
  • 如果要展示不同的内容, 只需要修改数据即可

1. data 和 setData

  • data 定义数据

  • setData 修改数据

  • 查看数据: 打开控制台 => 调试器 => appData

    // demo.js
    Page({
       // 定义数据
       data: {
         msg: 'hello小程序',
         count: 100
       },
    });
    
    // demo.wxml
    <view>{{msg}}</view>
    <view>{{count}}</view>
    

2. 条件渲染 wx:if

{{}} --- 这里面可以写data里面的数据,也可以写一下简单js表达式

<!-- demo.wxml -->
//if else 必须一起用
<view wx:if="{{show}}">
一些内容........
</view>
<view wx:else>
另一些内容......
</view>


<view wx:if="{{num === 10}}">
222222222222
</view>

// demo.js
Page({
  data: { 
    show: true,
    num: 10
  }, 
}); 

3. 列表渲染 wx:for

  • 列表渲染用 wx:for=

  • item 列表的成员

  • index 成员的下标

  • wx:key 需要一个唯一的值

    • 基本数据类型 wx:key="*this"
    • 引用数据类型 wx:key="id"

9.绑定事件

(1) 绑定事件

// demo.wxml 文件

<button type="primary" bindtap="clickFn"> Click me! </button>
Page({
  clickFn: function(event) { 
     // alert('哈哈哈'); // 没有alert方法 
     console.log(event); 
  },
});

(2) 事件传参

// demo.wxml 文件

<button type="primary" bindtap="clickFn" data-name="张三">张三</button>
<button type="primary" bindtap="clickFn" data-name="李四">李四</button>
<button type="primary" bindtap="clickFn" data-name="王五">王五</button>

// demo.js文件

Page({ 
  data: {}, 
  clickFn(ev) {
    // ev.target 被点击的元素 dataset 存放在元素的数据
    console.log(ev.target.dataset.name);
  }
})

注意: wxml和html一样, 不区分大小写, 页面上的大写, 最后变成了小写

(3)常见事件类型 | 类型 | 触发条件 | 最低版本

touchstart | 手指触摸动作开始 | | | touchmove | 手指触摸后移动 | | | touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 | | | touchend | 手指触摸动作结束 | | | tap | 手指触摸后马上离开 | | | longpress | 手指触摸后,超过 350ms 再离开,如果指定了事件回调函数并触发了这个事件,tap 事件将不被触发 | 1.5.0 | | longtap | 手指触摸后,超过 350ms 再离开(推荐使用 longpress 事件代替) | | | transitionend | 会在 WXSS transition 或 wx.createAnimation 动画结束后触发 | | | animationstart | 会在一个 WXSS animation 动画开始时触发 | | | animationiteration | 会在一个 WXSS animation 一次迭代结束时触发 | | | animationend | 会在一个 WXSS animation 动画完成时触发 | | | touchforcechange | 在支持 3D Touch 的 iPhone 设备,重按时会触发

10.页面跳转

小程序常用两种方式,普通页面跳转和 tab 栏切换(跳转)

注意: 路径前面加 '/' (/ 表示根路径)

// demo.wxml

<!-- 跳转到普通页面 -->
<navigator open-type="navigate" url="/pages/film/detail">电影详情</navigator> 
<button size="mini" bindtap="toDetail">电影详情</button>


<!-- 跳转到tab栏页面 -->
<navigator open-type="switchTab" url="/pages/cinema/cinema">影院列表</navigator>
<button size="mini" bindtap="toCinema">影院列表</button>

// demo.js

Page({
  data: {
    
  }, 
    
  // 普通页面跳转
  toDetail() {
    wx.navigateTo({
      url: '/pages/film/detail',
    })
  }, 
  
  // js跳转到tab栏页面
  toCinema() {
    wx.switchTab({
      url: '/pages/cinema/cinema',
    })
  }
});

11.路由传参

(1) 页面传参: 参数是基本数据类型

// 列表页面

<navigator url="/pages/film/detail?id={{item.id}}">详情</navigator>

// 详情页面

onLoad: function (options) {
    // 获取列表页面传过来的id
    console.log(options.id);
},

注意: wx.swichTab跳转url后不能带参数

(2) 页面传参: 参数是对象(引用数据类型)

  1. 小程序路由传参只能传字符串, 不能传对象
  2. 如果想要传对象, 需要先将对象转成字符串
  3. 在接收的页面, 再将字符串转成对象

详细代码

// 列表页面

// 列表的wxml文件 index是数组成员的下标
<view bindtap="toDetail" data-index="{{index}}" class="play-but abs"></view>
// 列表的js文件
toDetail(event) { 
    // 获取点击元素的下标
    let index = event.target.dataset.index;
    // 根据下标获取数组对应的成员
    let obj = this.data.videoList[index];
    // 将obj对象转为json字符串
    let objStr = JSON.stringify(obj);
    wx.navigateTo({
      url: '/pages/video/detail?objStr='+objStr,
    }) 
  },

// 详情页面

Page({ 
  data: {
    detail: {}
  }, 
  onLoad: function (options) {
    // 将字符串转成对象
    let obj = JSON.parse(options.objStr);
    this.setData({
      detail: obj
    })
  }, 
})

12.数据缓存

  1. 异步方法
//储存数据
wx.setStorage({
  key: "key",
  data: "value",
});
//取数据
wx.getStorage({
  key: "key",
  success(res) {
    console.log(res.data);
  },
});
  1. 同步方法
wx.setStorageSync("key", "value");

// 例子
let token = 'asdfasdfasjdflasdjf;asdf;asdfjsak;ldf';
wx.setStorageSync('token',token);
let token = wx.getStorageSync('token');

13.小程序获取位置

(1) 获取位置信息

  1. 文档资料

    • 小程序文档->api->位置
    • [腾讯地图API](平时的开发也可以使用百度地图,高度地图):
  2. 添加密钥

    使用位置服务需要先添加密钥,添加到app.json中

"permission": {
    "scope.userLocation": {
      "desc": "你的位置信息将用于小程序位置接口的效果展示" 
    }
  }
  1. 获取经纬度
wx.getLocation({
  type: 'wgs84',
  success: (res) => {
    const latitude = res.latitude;
    const longitude = res.longitude;
  },
  fail: (err) => {
    this.setData({
      city: '定位失败,请手动选择'
    })
  }
})

(2) 实际应用:

  1. 获取城市名称(需要上一点提供的经纬度)

     wx.request({
       url: `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=XBZBZ-OBG63-LOD3N-3QR5Q-X6Z2Q-BFBIR`,
       success: (res) => {
         let cityName = res.data.result.address_component.city;
         console.log(cityName)
       }
     })
    
  2. 计算两个坐标之间的距离

    //通过经纬度计算两个地方的距离
    // 第一个参数是城市的,第二个参数是影院的,返回的距离单位是KM
    function getDistance({lat1, lng1},{ lat2, lng2}) {
        var radLat1 = lat1 * Math.PI / 180.0;
        var radLat2 = lat2 * Math.PI / 180.0;
        var a = radLat1 - radLat2;
        var b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
        var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
            Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * 6378.137; // EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s;
    },

注: 上面计算的函数是网上copy来的仅供记录笔记学习

14.小程序登录

  1. 前端首先调用 wx.login 获取 code,
  2. 紧接着需要调用 wx.getUserInfo 来获得用户信息 (需要用户授权) ,获得 iv 和 encryptedData
  3. 调用后台登录接口,比如 /user/login,把以上三个参数
  4. openId: 小程序用户在小程序中的唯一编号
{
  code, iv,userInfo, encryptedData;
}
  1. 传给后台, 后台调用微信平台的相关接口, 对encryptedData进行解密, 得到用户的详细信息, 然后返回给前端

代码开发步骤:

  1. 绑定登录事件, 获取用户授权, 拿到用户相关信息
  2. 调用wx.login获取code
  3. 发送登录请求, 传入用户相关信息和code
  4. 登录成功, 修改文案
  5. 登录成功时, 把用户昵称存入缓存
  6. 在onload里获取缓存的昵称, 若有, 就修改文案
  7. 点击登录按钮先判断是否已登录