原生小程序开发之组件封装【玩转前端】

举报
叶一一 发表于 2023/02/14 20:15:14 2023/02/14
【摘要】 分享小程序开发中如何封装组件。

前言

前篇介绍了小程序开发的基础功能,第二篇分享小程序开发中如何封装组件。


小程序功能


日期选择器

picker组件可以实现日期选择器的功能,可以设置可选的日期范围,只要设置开始和结束两个时间点即可,注意,时间范围在真机模拟中才生效。官方文档

如下图为我在小程序中加入的日期选择器的交互界面,我设置的是往前可选到两年前,往后只能选到当前月。

image.jpeg

travelList.wxml

使用picker组件将事件点击区域包裹起来,这样点击就可以触发日期选择的弹窗,bindchange事件绑定的是进行日期选择之后的操作

<picker mode="date" fields="month" value="{{ date }}" start="{{ createStartTime }}" end="{{ createEndTime }}" bindchange="getDateTime">
    <view class="head">
      <view class="head-left">{{ searchTimeText }}</view>
      <view class="arrow-icon">
        <image src="../../images/icon/icon-arrow.png"></image>
      </view>
    </view>
  </picker>

travelList.js

searchTimeText:页面展示的日期变量;

createStartTime:日期选择器可选的最早日期,格式为yyyy-MM;

createEndTime:日期选择器可选的最晚日期,格式为yyyy-MM;

getDateTime: 日期选择器的确定操作的回调方法,返回值格式为yyyy-MM。


const date = new Date();
var year = date.getFullYear();
var month = date.getMonth();
var minValue = new Date().getTime() - 2 * 365 * 24 * 60 * 60 * 1000;
var maxValue = new Date().getTime();

Page({
  /**
   * 页面的初始数据
   */
  data: {
    searchTimeText: `${year}年${month + 1}月`, // 页面展示日期
    createStartTime: util.dateFormatter(minValue, 'yyyy-MM'), // 可选的最早日期
    createEndTime: util.dateFormatter(maxValue, 'yyyy-MM'), // 可选的最晚日期
  },
  // 选择日期
  getDateTime: function (e) {
    console.log('picker发送选择改变,携带值为', e.detail.value);
    let value = e.detail.value;
    let list = value.split('-');
    let syear = list[0];
    let smonth = list[1];
    // 重新请求列表数据并设置年份回显
    this.setData({
      searchTimeText: `${syear}年${smonth}月`,
    });
  },
});

modal弹窗

基础的modal弹窗

wx.showModal可以实现modal弹窗,直接在点击事件中调用即可。官方文档

可以自定义弹窗标题、弹窗内容、成功回调处理、失败回调处理等

比如在我的旅游小程序中,用户跳转自己的游记页面,我需要判断这个用户有没有写过游记,如果没有需要给出提示。

mine.html

<view class="mine-content-item" bindtap="gotoTravel">
    <view class="content-item-label">
      <text>我的游记</text>
      <text class="ml5">({{ travelList.length }}篇)</text>
    </view>
    <view class="arrow-icon">
      <image src="../../images/icon/icon-arrow.png"></image>
    </view>
  </view>

mine.js

当列表数据没有数据的时候给出提示。

// 跳转我的游记列表
gotoTravel() {
  if (this.data.travelList.length === 0) {
    wx.showModal({
      title: '温馨提示',
      content: '您暂时还没有发表游记,是否跳转热门游记?',
      success(res) {
        if (res.confirm) {
          wx.redirectTo({
            url: '../travelList/travelList?type=hot',
          });
        } else if (res.cancel) {
          console.log('用户点击取消');
        }
      },
    });
  } else {
    wx.redirectTo({
      url: '../travelList/travelList?type=self',
    });
  }
},


最终的弹窗提示如图:

image.jpeg


自定义modal弹窗

wx.showModal提供的能力中,展示内容是字符串类型,如果我们需要展示的内容比较复杂,那么wx.showModal就无法满足我们的需求了,这个时候需要自定义弹窗。

我仿照掘金的展示模块,给我的旅游小程序加了一个个人成就的栏位,功能是展示文章被赞和被阅读的数量,交互如下:

image.jpeg


image.jpeg


实现的方案就是在wxml中把弹窗的布局写出来,通过wx:if进行内容是否展示的控制。

mine.wxml

<view class="mine-content-item" bindtap="remarkShow">
    <view class="content-item-label">个人成就</view>
    <view class="arrow-icon">
      <image src="../../images/icon/icon-arrow.png"></image>
    </view>
</view>
  ...
  <!-- 个人成就-弹窗 -->
  <view wx:if="{{ achievementShowFlag }}" class="remark-view">
    <view class="remark-view-background">
      <view class="remark-view-top">个人成就</view>
      <view class="remark-view-middle">
        <view class="item">
          <view class="label">文章被点赞:</view>
          <view class="text">{{ achievement.praise }}</view>
        </view>
        <view class="item">
          <view class="label">文章被阅读:</view>
          <view class="text">{{ achievement.view }}</view>
        </view>
      </view>
      <view class="remark-view-bottom">
        <view class="remark-view-cancel" bindtap="remarkClose">关闭</view>
      </view>
    </view>
  </view>

mine.wxss

.remark-view {
  height: 100vh;
  width: 100%;
  background: rgba(0, 0, 0, 0.5);
  z-index: 999;
  position: fixed;
  top: 0;
}
.remark-view-background {
  background: white;
  height: 30%;
  margin: 60% 48rpx 0;
  border-radius: 8rpx;
}
.remark-view-top {
  padding: 20rpx 32rpx 0;
  font-size: 36rpx;
  color: #0b1d32;
  text-align: center;
  font-weight: bold;
}
.remark-view-middle {
  margin: 40rpx 32rpx 0;
  height: 50%;
  border-radius: 8px;
  font-size: 32rpx;
  font-weight: 200;
}
.remark-view-middle .item {
  margin-bottom: 10rpx;
  display: flex;
  justify-content: space-between;
  justify-items: center;
}
.remark-view-blank {
  height: 1rpx;
  margin-top: 65rpx;
  background: #dfe2e4;
}
.remark-view-bottom {
  height: 80rpx;
  border-radius: 8px;
  font-size: 18px;
  width: 100%;
  border-top: 2rpx solid #f4f4f4;
}
.remark-view-cancel {
  line-height: 80rpx;
  color: #0b1d32;
  font-weight: 200;
  font-size: 30rpx;
  text-align: center;
}
.remark-view-confim {
  width: 50%;
  line-height: 80rpx;
  color: #0a73f5;
  font-weight: 200;
  font-size: 30rpx;
}

mine.js

  • 设置两个参数分别是个人成就内容对象-achievement和人成就弹窗是否展示布尔值-achievementShowFlag;
  • 两个方法,打开弹窗方法:remarkShow和关闭弹窗方法:remarkClose
/**
   * 页面的初始数据
   */
  data: {
    achievement: {}, // 个人成就
    achievementShowFlag: false, // 个人成就弹窗是否展示 默认-false
  },
  
  // 个人成就弹窗-打开
  remarkShow() {
    this.setData({
        achievementShowFlag: true,
        achievement: {
            praise: 30,
              view: 1200,
          },
      });
  },
  // 个人成就弹窗-关闭
  remarkClose() {
    this.setData({
      achievementShowFlag: false,
    });
  },

2.2.7 拨打手机号

小程序拨打电话的API是wx.makePhoneCall,官方文档

值如果是固定的比如客服,可以定义全局的常量,方便统一维护,如果是需要从接口动态获取的,直接通过接口获取并赋值即可。

我再util文件下面新增了一个常量文件-constant.js,用于维护我的项目中的公共常量。

constant.js

定义全局的客服电话

/**
 * @description 公共常量
 */

/** @name 客服电话 */
export const servicePhone = '400-xxx-xxx';

mine.wxml

在需要拨打电话的页面,绑定唤起拨打电话功能的方法:phoneCall

<view class='mine-content-item' bindtap='phoneCall'>
  <text class='content-item-label'>联系客服(待开发)</text>
  <view class='arrow-icon'>
    <image src='../../images/icon/icon-arrow.png'></image>
  </view>
</view>

mine.js

const constant = require('../../utils/constant.js');

// 拨打客服电话
phoneCall() {
    const phoneNumber = constant.servicePhone;
    wx.makePhoneCall({
      phoneNumber: phoneNumber,
    });
},


多选组件

普通多选

官方提供了checkbox组件,支持单个多选框和多选组,官方文档

官方提供的示例基本把用法都列出来了

wxml文件

<view class="container">
  <view class="page-body">
    <view class="page-section page-section-gap">
      <view class="page-section-title">默认样式</view>
      <label class="checkbox">
        <checkbox value="cb" checked="true"/>选中
      </label>
      <label class="checkbox">
        <checkbox value="cb" />未选中
      </label>
    </view>
  
    <view class="page-section">
      <view class="page-section-title">推荐展示样式</view>
      <view class="weui-cells weui-cells_after-title">
        <checkbox-group bindchange="checkboxChange">
          <label class="weui-cell weui-check__label" wx:for="{{items}}" wx:key="{{item.value}}">
            <view class="weui-cell__hd">
              <checkbox value="{{item.value}}" checked="{{item.checked}}"/>
            </view>
            <view class="weui-cell__bd">{{item.name}}</view>
          </label>
        </checkbox-group>
      </view>
    </view>
  </view>  
</view>

js文件

Page({
  onShareAppMessage() {
    return {
      title: 'checkbox',
      path: 'page/component/pages/checkbox/checkbox'
    }
  },

  data: {
    items: [
      {value: 'USA', name: '美国'},
      {value: 'CHN', name: '中国', checked: 'true'},
      {value: 'BRA', name: '巴西'},
      {value: 'JPN', name: '日本'},
      {value: 'ENG', name: '英国'},
      {value: 'FRA', name: '法国'}
    ]
  },

  checkboxChange(e) {
    console.log('checkbox发生change事件,携带value值为:', e.detail.value)

    const items = this.data.items
    const values = e.detail.value
    for (let i = 0, lenI = items.length; i < lenI; ++i) {
      items[i].checked = false

      for (let j = 0, lenJ = values.length; j < lenJ; ++j) {
        if (items[i].value === values[j]) {
          items[i].checked = true
          break
        }
      }
    }

    this.setData({
      items
    })
  }
})


展示效果

image.jpeg

二维数组的多选

我的小程序里面用到多选的数据是一个二维数组,选择城市的页面,城市数据含城市首字母大写,我尝试之后发现checkbox组件对二维数组也是支持的

cityList.wxml

checkbox-group需要把整个数组包起来,才能正常获取选中项,我刚开始只把最里面的循环包起来了,发现拿到的选中项的数据不对。

<checkbox-group bindchange="checkboxChange" class="checkbox-box">
  <view class="weui-cells weui-cells_after-title" wx:for="{{ list }}" wx:key="index" wx:for-item="item" wx:if="{{ list.length > 0 }}">
    <text class="scroll-letter">{{ item.firstLetter }}</text>
      <label class="weui-cell weui-check__label scroll-item checkbox-item" wx:for="{{item.list}}" wx:key="cityIndex" wx:for-item="city">
        <view class="weui-cell__hd">
          <checkbox value="{{city.cityId}}" checked="{{city.checked}}"/>
        </view>
        <view class="weui-cell__bd">{{ city.cityName }}</view>
      </label>
  </view>
</checkbox-group>

cityList.js

list:城市列表二维数组,包含城市首字母大写

// pages/cityList/cityList.js
Page({
  /**
   * 页面的初始数据
   */
  data: {
    list: [
          {
            firstLetter: 'A',
            list: [
              {
                cityId: 3,
                cityName: '毕节市',
                provinceId: 3,
                provinceName: '贵州省',
              },
            ],
          },
          {
            firstLetter: 'B',
            list: [
              {
                cityId: 4,
                cityName: '安顺市',
                provinceId: 3,
                provinceName: '贵州省',
              },
            ],
          },
          {
            firstLetter: 'G',
            list: [
              {
                cityId: 5,
                cityName: '贵阳市',
                provinceId: 3,
                provinceName: '贵州省',
              },
            ],
          },
          {
            firstLetter: 'L',
            list: [
              {
                cityId: 6,
                cityName: '六盘水市',
                provinceId: 3,
                provinceName: '贵州省',
              },
            ],
          },
          {
            firstLetter: 'T',
            list: [
              {
                cityId: 7,
                cityName: '铜仁市',
                provinceId: 3,
                provinceName: '贵州省',
              },
            ],
          },
          {
            firstLetter: 'Z',
            list: [
              {
                cityId: 8,
                cityName: '遵义市',
                provinceId: 3,
                provinceName: '贵州省',
              },
            ],
          },
        ], // 城市列表
  },
});

UI展示

image.jpeg

全选、部分选中、删除已选项

在多选的基础上做全选、部分选中的功能是可行的,处理会复杂一些,由于文章篇幅的问题,我就不具体列出来了,文章底部我放置了我的小程序git地址,大家可以拉代码看,交互效果如下

部分选中

image.jpeg

全选

image.jpeg


自定义组件

组件化编程,重复功能组件化,复杂功能组件化拆分,都有利于代码的维护和提升开发效率,微信也提供了自定义组件的功能。官方文档


创建自定义组件

  • 打开微信开发者工具,我把我的自定义组件都放到了component目录下,在该目录下右键点击,选新建Component,然后命名组件,命名成功之后就会生成组件文件结构,如下图,我命名的组件是stars;
  • 类似于页面,一个自定义组件由 jsonwxml、wxssjs 4个文件组成。

image.jpeg

  • 要编写一个自定义组件,首先需要在 json 文件中进行自定义组件声明(将 component 字段设为 true 可将这一组文件设为自定义组件):
{
  "component": true
}


开发自定义组件

Component 构造器可用于定义组件,调用 Component 构造器时可以指定组件的属性、数据、方法等。详细的参数含义和使用请参考 Component 参考文档

以我小程序中的评价功能为例。评价功能设计的交互为点了星星,界面展示如下,选择了三个城市,点亮了两个城市的评价最后一个没有点亮:

image.jpeg

stars.wxml

星星使用的是图片,点亮和不点亮是两张不同的图片

<view class="stars-view">
  <view class="flex" wx:for="{{ imgs }}" wx:key="id" wx:for-item="item" bindtap="_changeColor" data-index="{{ item.id }}">
    <image class="canSelect ? big-star : litter-star" src="{{ item.id > starCount ? starNoSelect : starSelect }}"></image>
  </view>
</view>

stars.wxss

/* component/stars/stars.wxss */
.stars-view {
  display: flex;
  align-items: center;
}
.flex {
  display: flex;
  align-items: center;
}
.big-star {
  width: 44rpx;
  height: 44rpx;
  margin: 0px 8rpx;
  vertical-align: middle;
}

.litter-star {
  width: 36rpx;
  height: 36rpx;
  margin: 0px 4rpx;
  vertical-align: middle;
}

stars.js

  • properties组件的对外属性,是属性名到属性设置的映射表
  • methods组件的方法,包括事件响应函数和任意的自定义方法,关于事件响应函数的使用,参见 组件间通信与事件。其中微信的建议是内部方法建议以下划线开头。
// component/stars/starts.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    //是否可以点击
    canSelect: {
      type: Boolean,
      value: true,
    },
    //星星个数
    starCount: {
      type: Number,
      value: 5,
    },
    // 当前引用组件的子项的索引 当父组件是数组时有效
    index: {
      type: Number,
      value: 0,
    },
  },

  /**
   * 组件的初始数据
   */
  data: {
    imgs: [
      {
        id: 1,
      },
      {
        id: 2,
      },
      {
        id: 3,
      },
      {
        id: 4,
      },
      {
        id: 5,
      },
    ],
    starNoSelect: '/images/icon/star-noSelect.png',
    starSelect: '/images/icon/star-select.png',
  },

  /**
   * 组件的方法列表
   */
  methods: {
    // 更新星星颜色 内部方法建议以下划线开头
    _changeColor: function (e) {
      let starCount = e.currentTarget.dataset.index;
      this.setData({
        starCount: starCount,
      });
      let myEventDetail = {
        starCount: starCount,
        index: this.data.index,
      };
      this.triggerEvent('myevent', myEventDetail);
    },
  },
});

使用自定义组件

使用已注册的自定义组件前,首先要在页面的 json 文件中进行引用声明。此时需要提供每个自定义组件的标签名和对应的自定义组件文件路径:

activityFavorite.json

{
  "usingComponents": {
    "stars": "../../component/stars/stars"
  },
  "navigationBarTitleText": "评选喜爱城市"
}

在页面的 wxml 中就可以像使用基础组件一样使用自定义组件。节点名即自定义组件的标签名,节点属性即传递给组件的属性值。

activityFavorite.wxml

<view wx:for="{{ cityList }}" wx:key="index" wx:for-item="item" class="item">
  <view class="item-left">{{ item.cityName }}</view>
  <stars canSelect="{{ item.stars == 0 }}" starCount="{{ item.stars }}" bind:myevent="setStartCount" index="{{ index }}"></stars>
</view>


自定义组件见通信

组件间的基本通信方式有以下几种。

  • WXML 数据绑定:用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容数据(自基础库版本 2.0.9 开始,还可以在数据中包含函数)。具体在 组件模板和样式 章节中介绍。
  • 事件:用于子组件向父组件传递数据,可以传递任意数据。
  • 如果以上两种方式不足以满足需要,父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法。

上面的评价组件中,

1.子组件向父组件通信中,使用 triggerEvent 方法进行事件触发,每次操作评价点亮时,都会触发通信。

// 更新星星颜色 内部方法建议以下划线开头
_changeColor: function (e) {
  let starCount = e.currentTarget.dataset.index;
  this.setData({
    starCount: starCount,
  });
  let myEventDetail = {
    starCount: starCount,
    index: this.data.index,
  };
  this.triggerEvent('myevent', myEventDetail);
},

2.父组件通过监听拿到子组件传过来的值

// 事件监听
  setStartCount: function (e) {
    let detail = e.detail; // 子组件通信传的值
    let cityList = [].concat(this.data.cityList);
    cityList[detail.index].stars = detail.starCount;
    this.setData({
      cityList: cityList,
    });
  },


wxs

WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。我开始理解的它有点像filter过滤器,但是后面做了一些尝试,发现它的功能挺强大的。官方文档

类似filter过滤器用法

比如我想做一个颜色过滤器,某些特定文字展示蓝色,其余展示灰色,于是我在comm.wxs文件中写了一个方法

comm.wxs

/**
 * 设置详情页顶部右侧文案颜色
 * @param {string} text 右侧文字内容
 * @return {string} color 文字颜色
 */
function setRightTextColor(text) {
  var color = '#999';
  if (text && text.indexOf('发布') !== -1) {
    color = '#0a73f5';
  }
  return color;
}
module.exports = {
  setRightTextColor: setRightTextColor,
};

cityDetail.wxml

wxml文件中使用,需要先引入,我习惯外部文件放到底部,其实官方放到了顶部。这样一来detail.source的值中有发布二字的会展示蓝色

<wxs src="../../wxs/comm.wxs" module="comm" />
<view class="head">
    <view class="head-left">{{ detail.describe }}</view>
    <view class="head-right" style="color:{{comm.setRightTextColor(detail.source)}}">{{ script.getShowText(detail.source) }}</view>
  </view>

页面展示

蓝色

image.jpeg

灰色

image.jpeg


其他用法

wxs也可以直接在wxml文件里写功能,比如我想加一个默认文案展示的处理,当接口返回的数据中某个变量的值为空时,展示默认文案,可以直接wxml里面写一个方法,然后进行调用

cityDetail.wxml

<!-- wxs显示默认文案 -->
<wxs module="script">
  var getShowText = function(text, defaultText='内容摘自百度百科') {
    var showText = showText ? showText : defaultText;
    return showText;
  }
  module.exports.getShowText = getShowText;
</wxs>

<view class="container">
  <view class="banner">
    <view class="banner-box">
      <view class="head">
        <view class="head-left">{{ detail.describe }}</view>
        <view class="head-right" style="color:{{comm.setRightTextColor(detail.source)}}">{{ script.getShowText(detail.source) }}</view>
      </view>
    </view>
  </view>
</view>


开放能力

小程序开发需要对官方提供的开放能力做一定调研,比如某些功能只有非个人开发者才能使用,如:获取手机号;比如某些功能是特定基础库之后才有的,如小程序加密网络通道功能是从基础库 2.17.3 开始支持的;某些功能需要在小程序管理后台申请,比如分享数据到微信运动,需要到小程序管理后台,「开发」-「接口设置」中自助开通该组件权限。 只针对「体育-在线健身」类目的小程序开放。

所以要关注小程序开放能力以及某些功能的调整。官方文档


如何解决小程序开发遇到的问题

导航条不展示

我在app.josn里加上导航条之后,如下为导航条代码

"tabBar": {
    "selectedColor": "#007AF5",
    "list": [
      {
        "pagePath": "pages/home/home",
        "text": "首页",
        "iconPath": "/image/icon/home-unselected.png",
        "selectedIconPath": "/image/icon/home-selected.png"
      },
      {
        "pagePath": "pages/mine/mine",
        "text": "我的",
        "iconPath": "/image/icon/mine-unselected.png",
        "selectedIconPath": "/image/icon/mine-selected.png"
      }
    ]
  },

发现导航条无法正常展示页面路径也空了,还报了一个错误,如下截图

image.jpeg


image.jpeg

我尝试把导航条内容删除,页面就正常了,于是我推测是iconpath的问题,果然我的文件夹名字是images但是这里我写成了image,改完重新编译,页面就能正常显示了

image.jpeg

因为导航条这里的代码并不是很多,遇到问题可以首先考虑iconPath的路径是否正确。


解决webview导致的不支持打开非业务域名的问题

1.问题如图:

image.jpeg

2.问题原因

小程序后台没有设置业务域名,小程序中使用了webview功能,需要配置业务域名,如果没有配置那么在操作小程序的时候会出现上图的提示。其他webview功能可以看官方文档

3.怎么看自己有没有配业务域名

两种方法

1)直接到小程序后台查看

开发管理->开发设置->业务域名模块,是否已配置了自己需要跳转的域名。注:只有企业认证的小程序采用业务域名模块,个人小程序没有。

2)开发者工具

在项目配置中有一项叫做web-view(业务域名)如果设置了会展示已经设置的域名,如果没设置会展示未设置

image.jpeg

4.如何设置业务域名

小程序后台,开发管理->开发设置->业务域名模块

1)点击开始配置按钮

image.jpeg


2)下载校验文件


请下载校验文件,并将文件放置在域名根目录下,例如wx.qq.com,并确保可以访问该文件。如配置中遇到问题,请查看具体指引。

image.jpeg


如何配置用户隐私保护指引设置中的使用用户信息类型

1.用户信息类型有哪些

小程序发版前需要确认用户隐私保护指引设置已完成,且其中的使用用户信息类需要选全,如果不全可能会导致小程序审核失败,用户信息类型如下截图:

image.jpeg

2.如何知道自己都需要选择哪些用户信息类型

微信提供了API对应用户信息类型的详细文档,文档官方地址

具体内容如下,如果小程序中使用了某个接口,用户隐私保护指引设置的时候就需要勾选对应的用户信息类型了:

处理的信息

接口或组件

收集你的微信昵称、头像

wx.getUserInfo、wx.getUserProfile、<button open-type="userInfo">

收集你的位置信息

wx.authorize({scope:'scope.userLocation'})、wx.authorize({scope: 'scope.userLocationBackground'})、wx.getLocation、wx.startLocationUpdate、wx.startLocationUpdateBackground、wx.choosePoi、wx.chooseLocation

收集你的地址

wx.chooseAddress

收集你的发票信息

wx.chooseInvoiceTitle、wx.chooseInvoice

收集你的微信运动步数

wx.authorize({scope: 'scope.werun'})、wx.getWeRunData

收集你的手机号

<button open-type="getPhoneNumber">

收集你的车牌号

wx.chooseLicensePlate

收集你选中的照片或视频信息

wx.chooseImage、wx.chooseMedia、wx.chooseVideo

收集你选中的文件

wx.chooseMessageFile

访问你的麦克风

wx.authorize({scope: 'scope.record'})、wx.startRecord、RecorderManager.start、<live-pusher>、wx.joinVoIPChat

访问你的摄像头

wx.authorize({scope: 'scope.camera'})、wx.createVKSession、<camera>、<live-pusher>、<voip-room>

访问你的蓝牙

wx.openBluetoothAdapter、wx.createBLEPeripheralServer

使用你的相册(仅写入)权限

wx.authorize({scope: 'scope.writePhotosAlbum'})、wx.saveImageToPhotosAlbum、wx.saveVideoToPhotosAlbum

使用你的通讯录(仅写入)权限

wx.addPhoneContact

使用你的日历(仅写入)权限

wx.addPhoneRepeatCalendar、wx.addPhoneCalendar


解决微信小程序真机 showToast 不显示

原文地址:https://www.jianshu.com/p/ab511b0edaf9

作者:chenxuxu

链接:https://www.jianshu.com/p/ab511b0edaf9

来源:简书

简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

真机上测试发现调用 showToast 不显示,或者闪一下就没了。经过查找,发现是与 wx.showLoading 冲突了,两者调用的是同个框。

先放上我的错误代码:

// 请求事件
  requestEvent: function() {

    wx.showLoading({
      title: '正在加载中',
    })
    wx.request({
      url: '',
      success: function(res) {
        wx.showToast({
          title: '成功',
          duration: 2000
        })
      },
      fail: function() {
        wx.showToast({
          title: '失败',
          duration: 2000
        })
      },
      complete: function() {
        wx.hideLoading()
      }
    })
  }


我是想请求接口后,将加载框隐藏掉,再显示 toast 提示。但是真机上发现 showToast 不显示。正如上面所说,两者调用的是同个框。现在,我们分析整个流程:

  • 首先显示 loading 框;
  • 然后调用 success / fail,弹框的内容由 loading 变成了 toast;
  • 最后调用 onComplete 时,hideLoading 将弹框隐藏掉了.

很明显,我们最终把 toast 框隐藏掉了。知道原因后,改起来就容易了。先调用 wx.hideLoading(),再调用 wx.showToast() 即可


建议

1)若是在网络请求前需要调用 wx.showLoading,建议在该 success 和 fail 回调函数内第一行就调用 wx.hideLoading。即使暂时不需要 showToast 操作。因为以后需要在回调函数内添加 toast 时, 就不用再管什么顺序问题了;

2)当 toast 和 loading 同时使用,多注意两者的调用顺序;

如下是正确代码:

// 请求事件
  requestEvent: function() {

    wx.showLoading({
      title: '正在加载中',
    })
    wx.request({
      url: '',
      success: function(res) {
        // 放到最上面
        wx.hideLoading();
        wx.showToast({
          title: '成功',
          duration: 2000
        })
      },
      fail: function() {
        wx.hideLoading()
        wx.showToast({
          title: '失败',
          duration: 2000
        })
      }
    })
  }


小程序过审注意事项

1.提交审核信息(非常重要)

  • 修改内容LOG一定要清晰完整
  • 有账户体系的小程序,必须支持微信登录,同时需要提供测试账号(微信审核人员不会主动注册账号进行审核的)
  • 版本号严谨,避免混乱

image.jpeg

2.代码质量

  • 减少代码内部必要的bug,比如那些devTool调试工具就可见的红字报错

如下截图为页面有bug时,审核未通过的原因

image.jpeg

  • APP.JSON中的pages页面一定要保证都能打开,如果没有内容需要展示无内容提醒,比如列表为空时,可以提示暂无数据,不可以展示空白页面;

如下截图为页面无法加载或者空白时,审核未通过的原因

image.jpeg

  • 避免小程序页面UI不规范,保证主流机型屏幕尺寸下,页面UI可以正常显示;

如下截图为页面UI显示不规范时,审核未通过的原因

image.jpeg



3.关注微信官方公告和政策

比如小程序的使用规范:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/channels-live.html#%E4%BD%BF%E7%94%A8%E8%A7%84%E8%8C%83

里面明确了

平台将坚决打击诱导跳转视频号直播、诱导预约视频号直播等行为,使用此功能时请严格遵守《微信小程序平台运营规范》


如下截图为小程序存在不符合规范的情况下,审核未通过的原因:

image.jpeg


4.开放的类目

  • 开发前,请先参考已经开放的类目,没有开放的类目审核会不通过
  • 部分类目需要资质,没有资质无法通过.

5.禁止测试性质的内容出现,禁止非正式的服务出现在小程序中

如下截图为小程序有测试性质内容下,审核未通过的原因:

image.jpeg

6.用户需要发表内容的小程序,需要设定关键词过滤,屏蔽掉政策不允许的内容

如下截图为小程序用户发布内容未进行关键词过滤,审核未通过的原因:

image.jpeg

7.视频,音乐等内容,不能设置为自动播放;

8.提供资讯的小程序,不能含有任何时政类的新闻

如下截图为小程序时包含政类的新闻,审核未通过的原因:

image.jpeg

9.假如审核通过,请立刻在后台发布;请勿在未发布审核通过的小程序时,就提交新版本审核,会导致无法发布。


总结


个人小程序git地址:https://github.com/wxmp-project/wxmp-travel

目前功能开发的还比较简单,后续会持续更新,文章也会持续更新,因为还有些功能由于还在摸索着,所以暂时没加。

作者:非职业「传道授业解惑」的开发者叶一一
简介:「趣学前端」、「CSS畅想」系列作者,华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。