yanyue404 / blog

Just blog and not just blog.
https://yanyue404.github.io/blog/
Other
88 stars 13 forks source link

原生微信小程序开发简明教程 #178

Open yanyue404 opened 4 years ago

yanyue404 commented 4 years ago

目录

生命周期

App

// app.js
App({
  onLaunch(options) {
    // 小程序初始化启动时先做一些事情,如:扩展 wx 对象
  },
  onShow(options) {
    // 小程序启动,或从后台进入前台显示时触发
  },
  onHide() {
    // 小程序从前台进入后台时触发
  },
  onError(msg) {
    // 小程序发生脚本错误或 API 调用报错时触发
  },
  globalData: 'I am global data',
});

Page

Page({
  data: {
    text: 'This is page data.',
  },
  onLoad: function (options) {
    // 页面创建时执行,一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数
  },
  onShow: function () {
    // 页面显示/切入前台时触发
  },
  onReady: function () {
    // 页面首次渲染完毕时执行,一个页面只会调用一次,代表页面已经准备妥当(可以操作 Dom)
   // ! 如果需要获取 ajax 动态渲染的 dom 元素,可以在获取数据后设置 setData 时的回调中获取
  },
  onHide: function () {
    // 页面从前台变为后台时执行
  },
  onUnload: function () {
    // 页面销毁时执行
  },
  onPullDownRefresh: function () {
    // 触发下拉刷新时执行
  },
  onReachBottom: function () {
    // 页面触底时执行
  },
  onShareAppMessage: function () {
    // 页面被用户分享时执行
  },
  onPageScroll: function () {
    // 页面滚动时执行
  },
});

Component

Component({
  // 在组件中是否使用全局 css 样式
  options: {
    addGlobalClass: true,
  },
  // 组件的属性列表(从父接收)
  properties: {
    paramA: Number,
    paramB: String,
  },
  data: {
    text: 'This is page data.',
  },
  created() {
    // 在组件实例刚刚被创建时执行,注意此时不能调用 setData
  },
  attached() {
    //  在组件实例进入页面节点树时执行
  },
  ready() {
    // 在组件布局完成后执行
  },
  detached() {
    // 在组件实例被从页面节点树移除时执行
  },
  methods: {
    // 事件响应函数
    viewTap: function () {
      // ...
    },
  },
});

路由

跳转到其他页面

// 跳转至非 tabbar 页面( 保留当前页面,可以返回到本页面)
wx.navigateTo({
  url: '../articleDetail/articleDetail?id=7',
});

// 关闭当前的页面再跳转,不可返回
wx.navigateTo({
  url: `../mediaCoverage_detail/mediaCoverage_detail?id=${data.id}`,
});

// 关闭所有页面,打开到应用内的某个页面(支持所有页面)
wx.reLaunch({
  url: '../sort/sort',
});

//跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
wx.switchTab({
  url: '../whereCanSearch/whereCanSearch',
});

返回页面

// 返回上一页
wx.navigateBack({ delta: 1 });

页面栈

getCurrentPages();
Page({
  click_address() {
    let pages = getCurrentPages(); // 获取页面栈
    let current = pages[pages.length - 1]; // 当前页面
    let url = current.route; //当前页面url
    let options = current.options; //如果要获取url中所带的参数可以查看options
    let prevpage = pages[pages.length - 2]; // 上一个页面
    let data = prevpage.data; // 获取上一页data里的数据
    if (prevPage) {
      //存在上一页
      prevPage.changeDataPageA('load'); // 调用上一页的函数
      prevPage.setData({ address_id: id }); // 修改上一页的数据
      wx.navigateBack(); // 返回上一页
    }
  },
});

重要组件

布局元素

开放能力

web-view

承载网页的容器。会自动铺满整个小程序页面。

配置:src 属性 为webview 指向网页的链接。可打开关联的公众号的文章,其它网页需登录小程序管理后台配置业务域名。 调试:微信开发者工具最新版本, 在web-view页面点击鼠标右键可出现调试按钮。 其他接口:

数据交互

模板

(1)动态 class

<view
  wx:for="{{mediaData}}"
  class="coverageBox {{(index < mediaData.length -1) ? 'border_bottom':'' }}"
  data-index="{{index}}"
></view>

(2)列表渲染

wx:for 控制属性绑定一个数组,默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item。使用 wx:for-item 可以指定数组当前元素的变量名,使用 wx:for-index 可以指定数组当前下标的变量名:

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName" wx:key="id">
  {{idx}}: {{itemName.message}}
</view>

(3)条件渲染

wx:if,来判断是否需要渲染该代码块:

<view wx:if="{{condition}}">True</view>

也可以用 wx:elifwx:else 来添加一个 else 块:

<view wx:if="{{length > 5}}">1</view>
<view wx:elif="{{length > 2}}">2</view>
<view wx:else>3</view>

block wx:if

是一个包装元素,并不会展示。如果要一次性判断多个组件标签,可以使用 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。

<block wx:if="{{true}}">
  <view>view1</view>
  <view>view2</view>
</block>

wx:if vs hidden

频繁切换:用 hidden,逻辑切换:用 wx:if,类似于 v-if 与 v-show。

<view hidden="{{true}}">show</view>

setData

setData 函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)。

this.setData(
  {
    text: 'changed data',
  },
  function () {
    // setData引起的界面更新渲染完毕后的回调函数
  },
);
 changeItemInArray() {
    // 对于对象或数组字段,可以直接修改一个其下的子字段,这样做通常比修改整个对象或数组更好
    this.setData({
      'array[0].text': 'changed data'
    })
  },
  changeItemInObject() {
    this.setData({
      'object.text': 'changed data'
    })
  },

跨页面传值

授权登录与用户信息

获取用户信息(昵称、头像等)

获取用户信息有两种方式。一种是通过 wx.getUserInfo() ,静默获取用户信息,但是需要用户之前授过权,否则拿不到信息。另一种方式是通过微信开放能力,通过 <button class="agree-btn" open-type="getUserInfo" bindgetuserinfo="onGotUserInfo">微信授权登录</button> 的方式由用户主动触发,一定能拿到用户信息(昵称、头像、性别、地区..)。

![]()

登录凭证

前端开发者调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。开发者服务器接收到 code,结合 appid、appsecret,通过后台服务调用 auth.code2Session 接口,换取 用户唯一标识 OpenID 和 会话密钥 session_key,如果用户已满足 UnionID 下发条件的情况下会返回开放平台唯一标识 unionId。(UnionID 机制说明

之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。

注意:

获取手机号

通过微信开放能力 <button class="agree-btn" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">授权绑定手机号</button> 获取到加密数据 encryptedData 和初始向量 iv,后端结合 session_key 可 解密出手机号。

注意:

在回调中调用 wx.login 登录,可能会刷新登录态。此时服务器使用 code 换取的 sessionKey 不是加密时使用的 sessionKey,导致解密失败。建议开发者提前进行 login;或者在回调中先使用 checkSession 进行登录态检查,避免 login 刷新登录态。

调试

开发者工具

(1)断点调试

打开调试器工具,按下快捷键 contrl+p,输入搜索的文件名,例如:home.js,而后打断点进行调试。

(2)真机调试

(3)自定义编译

scene 扫码的参数可以使用 escape 加密, unescape 解析。

{
  "file": "project.config.json",
  "miniprogram": {
    "current": -1,
    "list": [
      {
        "id": -1,
        "name": "首页分享给代理人 yanyue404",
        "pathName": "pages/auth_login/auth_login",
        "query": "homePage=true&accountId=172",
        "scene": null
      },
      {
        "id": -1,
        "name": "点亮星星扫码进入代理人",
        "pathName": "pages/auth_login/auth_login",
        "query": "scene=a%3D172%26t%3Dhome_foreign",
        "scene": ""
      }
    ]
  }
}
query 解密 (escape) query 加密(unescape)
"query": "scene=a=172&t=personalCard" "query": "scene=a%3D172%26t%3DpersonalCard"

(4)弱网调试

借助调试器 Network 选项,可选择Fast 3G网络进行调试。

真机

以下的方法都借助 vConsole:

(1)体验版调试

点击右上角...图标,开启调试模式,查看 vConsole 输出面板。

建议将所有的请求都进行打印:

// 成功日志输出
console.log('Request Successful', {
  url,
  params,
  result,
});

// 失败日志输出
console.log('Request Error', {
  url,
  params,
  result,
});

(2)线上版本调试

先在体验版或开发版打开调试,再切到正式版就能看到 vConsole

周边

参考资料