微信小程序开发后整理

709 阅读5分钟

扫一扫

wx.scanCode

 wx.scanCode({
  success: (res) => {
    console.log(res);
  },
});

跳转外部页面

<web-view src="{{url}}" />

分享功能

点击分享,分享到微信好友

  1. 在 onLoad 函数内添加 wx.showShareMenu
 onLoad() {
    wx.showShareMenu({
      withShareTicket: true,
      menus: ["shareAppMessage", "shareTimeline"],
    });
  },

  1. 通过 button 发起请求;将使用到的图标和官方button重叠在一起就能达到点击分享的效果
<view class="btn-wrap">
    <image src="/static/community_share_white.png" class="icon" lazy-load />
    <button 
        class="btn-share"
        type="primary"
        data-name="pageShare"
        id="share"
        open-type="share"/>
</view>
.btn-wrap {
    position: relative;
}
.btn-share{
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    opacity: 0;
}

图片上传可一次选择多张

van-uploader 通过multiple设置多张选择,通过 afterPhotoReadhandleDeleteFiles 对图片进行删减,确定后再调用后端接口

<van-uploader
    file-list="{{ photoUrlList }}"
    bind:after-read="afterPhotoRead"
    deletable
    bind:delete="handleDeleteFiles"
    data-type="photo"
    multiple/>

<van-button
    round
    color="#5F56FF"
    block
    bindtap="toSubmit"
    >提交
</van-button>
Page({
    data: {
        photoUrlList: [],
        photoUrl: '', //图片URL拼接
    },
  
    //图片上传:将获取到的图片路径保存在 photoUrlList 中
    afterPhotoRead(event) {
        const { file } = event.detail;
        let list = this.data.photoUrlList;
        this.setData({
          photoUrlList: [...list, ...file],
        });
    },

    // 图片删除
    handleDeleteFiles(e) {
        const { index } = e.detail;
        const { type } = e.currentTarget.dataset;
        if (type === "photo") {
          const { photoUrlList } = this.data;  //复制一份进行操作
          photoUrlList.splice(index, 1);
          this.setData({
            photoUrlList,
          });
        } 
    },
  
    // 图片上传:调用后端接口,通过 Promise.all 确定所有图片成功提交到服务器,并获取服务器返回的线上图片地址
    beforeSubmit() {
        wx.showLoading({
          title: "上传中...",
          icon: "loading",
          mask: true,
        });

        const { photoUrlList } = this.data;
        return Promise.all([
          uploadMultipleFile(photoUrlList).then((res) => {
            this.setData({
              photoUrl: res.join(","),
            });
          }),
          //可以有多个存在
        ]);
    },

    // 提交操作:将图片服务器返回的图片路径上传到接口
    toSubmit(e) {
        this.beforeSubmit().then((res) => {
          wx.hideLoading();
          
          // 文件上传成功后调用
          const params = {xxxx: this.data.photoUrl}
          xxxxxAPI(params).then(data => {
                //....
          })
        });
    },
})

封装好后的图片上传方法

const BASE_URL = 'http://cdn.fuwuqi.com'
/**
 * 单张图片上传
 * @param {*文件路径} path
 * @returns
 */
const uploadFile = (path) => {
  return new Promise((resolve, reject) => {
    wx.uploadFile({
      url: BASE_URL + '/uploadFile',
      filePath: path,
      name: 'file',
      formData: { user: 'test' },
      success: (res) => {
        const { code, data } = JSON.parse(res.data);

        if (code === 200) {
          resolve(data);
        } else {
          wx.showToast({
            title: '系统错误,请联系管理员',
            icon: 'none',
          });
          reject(data);
        }
      },
      fail: (err) => {
        reject(err);
      },
      complete: (info) => {
      },
    });
  });
};

/**
 * 多张图片上传
 * @param {*文件数组} list
 * @returns
 */
const uploadMultipleFile = (list = []) => {
  return Promise.all(
    list.map(async (d) => {
      if (d.size && d.type) {
        let data = await uploadFile(d.url);
        return data.filePath;
      } else {
        return d.url;
      }
    })
  );
};

验证表单提交

const validRules = {
    name: {
        msg: "请填写商家名称",
    },
};

data: {
    name: ''
},

for (let item in validRules) {
  if (!this.data[item] || this.data[item].length === 0) {
    validRules[item].msg &&
      wx.showToast({
      title: validRules[item].msg,
      icon: "none",
    });
    return;
  }
}

下拉加载

scroll-view 搭配 ang-loading

需要给scroll-view设置一个高度

<scroll-view class="scroll-height" scroll-y bindscrolltolower="handleToLower"> 

    <view
        class="store-item"
        wx:for="{{pageList}}"
        wx:key="*this"
     >
        <image src="{{item.avatarUrl}}" />
    </view>
  <ang-loading noData='{{ noData }}' noMore='{{ noMore }}' />
  
</scroll-view>
 // 下拉加载
handleToLower() {
  let { isLoading, page, noMore, noData } = this.data;
  if (isLoading || noMore || noData) return;
  this.setData({
    page: page + 1,
  });
  this.fetchList();
},

  // 获取数据
fetchList() {
  this.setData({
    isLoading: true,
  });
  const {
    page,
    limit,
    pageList,
  } = this.data;

  const params = {
    page,
    limit,
  };

  xxxAPI(params).then((data) => {
    if (data) {
      const { totalCount, list } = data;

      let currentList = page === 1 ? list : [...pageList, ...list];
      let noData = totalCount == 0;
      let noMore = currentList.length === totalCount;

      this.setData({
        pageList: currentList,
        isLoading: false,
        noMore,
        noData,
      });
    }
   });
  },

从底部弹起的询问窗口,显示操作菜单

wx.showActionSheet

wx.showActionSheet({
  itemList: ['删除'],
  success(res) {
    if (res.tapIndex === 0) {
     // 选择删除
    }
  },
  fail(res) {
    console.log(res.errMsg);
  },
});

是否开启定位

先通过 isLocation 方法判断当前用户的定位权限状态

  1. 从未申请定位权限,跳转询问 => askForLocation
  2. 已经授权定位权限,直接查询 => wxGetLocation
  3. 询问过,但拒绝了,跳转询问 => askForLocation
isLocation() {
  let _this = this;
  wx.getSetting({
    success(res) {
      // 如果从未申请定位权限,则申请定位权限
      if (res.authSetting['scope.userLocation'] == null) {
        wx.authorize({
          scope: 'scope.userLocation',
          success() {
            _this.askForLocation();
          },
          fail() {},
        });
      } else if (res.authSetting['scope.userLocation'] == true) {
        //如果已经有权限,就查询
        _this.wxGetLocation();
      } else {
        //询问过,但是拒绝了,需要再次询问,并引导到授权页面
        _this.askForLocation();
      }
    },
  });
},

 //弹窗询问是否开启定位,并引导到开启定位授权页面
 askForLocation() {
   let that = this;
   wx.showModal({
     title: '位置信息授权',
     content: '位置授权暂未开启',
     cancelText: '拒绝',
     confirmText: '开启授权',
     success: function (res) {
       if (res.confirm) {
         // 跳转授权页
         wx.openSetting({
           withSubscriptions: true,
           fail: function () {},
           success: function () {
             that.wxGetLocation();
           },
         });
       }
     },
    });
  },

 // 获取定位信息
 wxGetLocation() {
   const _this = this;
   wx.getLocation({
     type: 'wgs84',
     success: function (res) {
       //将位置信息存放到全局
       app.globalData.latitude = res.latitude;
       app.globalData.longitude = res.longitude;
       //将位置信息存放到本页面
       _this.setData({
         latitude: res.latitude,
         longitude: res.longitude,
       });
       _this.getList();
      },
    });
  },

微信支付

通过调用后端接口发起支付,接口返回参数 timeStamp、nonceStr、package、signType、paySign等参数,用于调用小程序提供的支付接口 wx.requestPayment ,具体传参如下

//下单支付
toPay(orderId) {
  API.PAY_ORDER({ orderId }).then((data) => {
    if (data) {
      let result = JSON.parse(data.result);
      if (result.timeStamp) {
        this.toWxPay(result);
      }
    }
  });
},

 // 微信支付
 toWxPay(d) {
    wx.requestPayment({
      timeStamp: d.timeStamp,
      nonceStr: d.nonceStr,
      package: d.package,
      signType: d.signType,
      paySign: d.paySign,
      success: function (res) {
        wx.showToast({
          title: "购买成功",
          icon: "none",
        });
        setTimeout(() => {
          GoPage("商家_我的");
        }, 2 * 1000);
      },
      fail: function (res) {},
      complete: function (res) {},
    });
  },

腾讯位置服务-地图打开后可通过本地app打开具体的路线

  1. wx.getLocation获取当前位置的经纬度,并将值存储到全局的 app.js
const app = getApp();

wxGetLocation() {
    const _this = this;
    wx.getLocation({
      type: "wgs84",
      success: function (res) {
        app.globalData.latitude = res.latitude;
        app.globalData.longitude = res.longitude;
        _this.setData({
          latitude: res.latitude,
          longitude: res.longitude,
        });
        _this.getList();
      },
    });
    },
  1. 需要地图定位当前坐标,并能打开本地地图app
const QQMapWx = require("../../../utils/qqmap-wx-jssdk.min.js");
let qqmapsdk;

openAddress() {
  const { longitude, latitude, address } = this.data.info;
  const _this = this;

  // 使用 JavaScript SDK 获取目的地经纬度
  // 实例化API核心类
  qqmapsdk = new QQMapWX({
    key: TX_KEY, // 腾讯地图申请的key值
  });
  qqmapsdk.geocoder({
    address,
    success: function (res) {
      _this.setData({
        latitude,
        longitude,
      });
    },
  });
  
  // 使用微信内置地图查看位置
  wx.getLocation({
    type: "gcj02", //返回可以用于wx.openLocation的经纬度
    success: function (res) {
      wx.openLocation({
        latitude: Number(latitude),
        longitude: Number(longitude),
        scale: 28,
        name: address, //打开后显示的地址名称
      });
    },
  });
}

腾讯位置服务-位置选择

腾讯位置服务-小程序插件

  1. 按照上方链接注册KEY值;
  2. 拼接出需要套跳转的url :
//使用在腾讯位置服务申请的key
export const TX_KEY = 'PO4BZ-XTM6J-WKPFG-K6DD3-LTYBQ-HSFSB'; 
//调用插件的app的名称
export const TX_REFERER = 'fineFood-weChat'; 
// 非必传
const TX_CATEGORY = '美食'; 
// 非必传
const TX_LOCATION = JSON.stringify({
  latitude: 39.89631551,
  longitude: 116.323459711,
});

// 地图需要跳转的url
const TX_MAP_URL =
  "plugin://chooseLocation/index?key=" +
  TX_KEY +
  "&referer=" +
  TX_REFERER +
  "&location=" +
  TX_LOCATION +
  "&category=" +
  TX_CATEGORY;
  
// 跳转指定位置的地图
wx.navigateTo({
  url: TX_MAP_URL,
});
  1. 从地图插件返回后,在页面的onShow生命周期函数中能够调用插件接口,取得选点结果对象
  onShow() {
    const location = chooseLocation.getLocation(); 
    
    // 如果点击确认选点按钮,则返回选点结果对象,否则返回null
    if (location) {
      this.setData({
        address: location.address,
        longitude: location.longitude,
        latitude: location.latitude,
      });
    }
  },

vant 组件库引入

方法一

npm包构建,举例 vant 引入

  1. npm init 创建 package.json 文件夹
  2. npm i @vant/weapp -S --production 安装
  3. 微信开发者工具 > 工具 > 构建 npm,构建生成 miniprogram_npm 文件夹
  4. 详情 > 使用 npm 模块
  5. 在需要的页面(例如 index.json)引用组件,然后 index.wxml 页面使用组件
{
  "usingComponents": {
    "van-button": "/miniprogram_npm/@vant/weapp/button/index"
  }
}
<van-button type="primary">按钮</van-button>

方法二

可直接去vant github库,将组件库直接下载到本地,直接使用。

页面跳转

方法一:使用switchTab跳转tarbar内的页面:

wx.switchTab({
  url: '../job/job',
})

方法二:使用redirectTo,navigateTo的跳转不是tarBar内的页面:

//直接替代当前页面
wx.redirectTo({
  url: '../logs/logs',
})

//可返回
wx.navigateTo({
  url: '../logs/logs',
})

onShow 与 onLoad

onshow

  • 每次打开页面都会调用一次。(页面加载好之后 你切到其他页面 再回来 显示这个页面 之前加载过的话 onLoad就不跑了 这是 页面信息呈现在你面前的这个过程 会跑onShow )

onLoad

  • 打开小程序进入该页面时候 (此时点击tabbar中的每一项都会执行onload, 从点击过了的tab项再进入其它点击过的tab项,不会执行 onload)
  • 修改代码点击保存的时候会 onload
  • 页面跳转(带参数,因为页面只能通过onload(option)方法中options 获取参数)
  • wx.navigateTo和wx.redirectTo及中带有 query参数,注意wx.switchTab要跳转到的页面已经被打开过,不会触发onload