记录使用微信小程序的开发过程当中遇到的各类难点及教程(不定时更新)

本文为整理记录本人使用微信小程序开发产品的过程当中,针对项目中业务需求所遇到的各类难点、API问题、BUG、及教程整理😁

一、wxml页面的 Mustache 语法(双大括号)数据绑定是不能使用全局js方法的,例如utils.js里面定义的时间日期格式化,价钱格式化等等公共函数方法。
只能用.wxs文件,这是文档:https://developers.weixin.qq....,而且.wxs文件只能使用es4语法,不支持es6语法,以及一些符号,好比我在vue项目里经常使用的这个邮箱正则
const emailReg = /[\w!#$%&'*+/=?^_{|}~-]+(?:.[w!#$%&'*+/=?^_{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/; ,就会报错。
因此想要在.wxml页面使用全局方法的话,就先定义好.wxs文件的全局方法,而后以下引入就可使用util.wxs里面的全局方法了,
<wxs src="../../utils/util.wxs" module="util" />
可是用.wxs来作全局方法的话有局限性,例如moment.js和accounting.js,这种使用率比较大的第三方插件,.wxs文件是不能引用js文件的,只能引用.wxs文件。html

因此这点很操蛋,只能继续使用 utils.js 在里面定义好全局方法,而后在app.js入口引入,vue

/**
 * 全局公共方法
 * @type {function}
 */
const utils = require('./utils/utils.js');

App({
    // 全局公共方法
    utils: utils,
})

接着,假如在test页面里,须要使用全局方法来处理数据的美圆、RMB价钱以及平方英尺、平方米换算。使用方法很简单:在test.js里,在data里声明好变量,而后就能够在下面使用全局方法来处理数据了。
例子:git

/* test.js */

// 获取全局应用程序实例对象
const app = getApp();

Page({
    /**
     * 页面的初始数据
     */
    data: {
        price: null,
    },
    
    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function (options) {
        //js里只能这样使用util全局方法,结合data声明的变量处理数据
        
        //此处是判断服务器接口返回的数据字段是否为null,如res.data.price = 123
        this.setData({ price: app.utils.isNull0(res.data.price) });
    },
})

/* test.wxml */

<view>{{ price }}</view>
//最终页面呈现为<view>123</view>,若是服务端接口返回的price字段是null的话,那么通过全局方法判断后,页面这里应该显示-

以上这些就是小程序page子路由页面如何使用utils全局方法的所有内容了,这一点算是我入手小程序这几天以来遇到的比较恶心🤢的了,相比用vue开发webapp项目,小程序这一点真的是反人类,很不方便😱。es6

二、UI库的使用,我用了有赞的vant-weapp和iView-weapp。
使用方法:
vant-weapp:https://github.com/youzan/van...
iView-weapp:https://github.com/TalkingDat...
把代码包下载到本地后,把里面的dist目录放到小程序的components目录下,最终结构为
图片描述github

而后在app.json里面定义好usingComponents字段,用到哪一个组件,按照其官方文档的使用指南,把组件引入到usingComponents里面就好了,注意相对路径要设置好,否则会报错。
例如我目前开发的小程序项目暂时用到了这几个组件,以后开发完之后,dist目录里没有用到的组件能够删掉。web

"usingComponents": {
    "van-row": "../components/vant-weapp/dist/row/index",
    "van-col": "../components/vant-weapp/dist/col/index",
    "van-toast": "../components/vant-weapp/dist/toast/index",
    "van-notify": "../components/vant-weapp/dist/notify/index",
    "van-tab": "../components/vant-weapp/dist/tab/index",
    "van-tabs": "../components/vant-weapp/dist/tabs/index",
    "van-search": "../components/vant-weapp/dist/search/index",

    "i-spin": "../components/iView-weapp/dist/spin/index",
    "i-button": "../components/iView-weapp/dist/button/index",
    "i-drawer": "../components/iView-weapp/dist/drawer/index"
}

三、小程序的页面间跳转有些规则的,vue开发wabapp项目,跳转路由通常使用编程式导航的话是这样的:vue-cli

this.$router.push({path: "/houseDetails", query: {id: id}});
//传参在query里定义。

而小程序的跳转有4种:
(1)、wx.navigateTo(Object object);//保留当前页面,跳转到应用内的某个页面。可是不能跳到 tabbar 页面。使用 wx.navigateBack 能够返回到原页面。
(2)、wx.redirectTo(Object object);//关闭当前页面,跳转到应用内的某个页面。可是不容许跳转到 tabbar 页面。
(3)、wx.reLaunch(Object object);//关闭全部页面,打开到应用内的某个页面
(4)、wx.switchTab(Object object);//跳转到 tabBar 页面,并关闭其余全部非 tabBar 页面npm

刚开始开发首页的时候,用bindtap点击事件绑定一个方法,在里面用 navigateTo 怎么点都不跳转,没反应,次日仔细看文档才发现,要跳转的页面是 tabBar 页面,因此向 tabBar 页面跳转的时候,不能使用navigateTo,要用 switchTab 方法来跳转😳。编程

四、安装npm第三方插件,参考此文档,https://developers.weixin.qq....
具体步骤:
(1)、先在本项目里打开命令行,而后npm install --production
(2)、跑完之后,好比要安装moment.js 则 npm install moment --save
(3)、安装完后 去微信开发者工具里找到菜单栏 -> 工具 -> 构建npm 点击执行,等待完成。
(4)、构建完后,项目根目录里会多出一个miniprogram_npm目录,里面就是安装好的moment.js插件。
而后在utils.js引用:json

// moment时间格式化
import moment from 'moment';
// moment.locale('zh-cn');//加载中文包

而后就能够在下面的全局方法 momentFormat(函数名本身取的) 里利用moment.js的 API 正常处理数据了。

五、js里的方法不能用es6的箭头函数,只能用function(),不然会报错this指向,查看报错信息里,this是undefined,暂不知是什么缘由。
例如:

keywordChange: app.utils.debounce((e) => {
    this.setData({ searchKeyword: e.detail });//此时的this是undefined  因此这行会报错
    if (app.utils.getByteLen(e.detail) > 3) {
        this.setData({ searchLoaderShow: true });
    }
}, 500)

keywordChange: app.utils.debounce(function(e) {
    this.setData({ searchKeyword: e.detail });//不用es6的箭头函数就没问题
    if (app.utils.getByteLen(e.detail) > 3) {
        this.setData({ searchLoaderShow: true });
    }
}, 500)

六、bindtap点击事件的方法传参要这么写才行:

<view bindtap="gotoDetails" data-searchType="{{ item.id }}"></view>

//方法里这样获取点击事件要用的key-value
gotoDetails(e){
    let url = '/pages/details/details?id='+ e.currentTarget.dataset.searchtype;
    //这里有个坑,绑定事件的设置参数,若是参数名有大写字母的话,下面获取的时候要用小写的,否则会报错undefined。例如:data-searchType -> e.currentTarget.dataset.searchtype
    wx.navigateTo({
        url: url
    })
}

//不能像vue项目那样,直接在括号里跟参数,会报错,哎,小程序有些地方真的反人类😝
<view bindtap="gotoDetails(id)"></view>

七、报错:wx.switchTab: url 不支持 queryString
意思是tabBar页面不支持url传参,只能利用app.js定义好globalData里的query参数,在要跳转的页面里赋值,就能够了。

八、吐槽下微信开发者工具的版本管理,真TMD难用,还不如直接用命令行操做git来的方便,跟intellij IDEA 内置的Git管理工具差远了。
附个微信开发者工具的版本管理的设置教程:https://static.oschina.net/ne...

九、微信小程序设为体验版后,不能加载数据,进去首页后会弹个Toast 轻提示 报错:Object Object
通过百度搜索,多是这些缘由:域名已经备案、https已经配置、ssl证书在1.2以上版本、小程序后台已经配置服务器域名

十、小程序遍历对象要用wx:for-index属性

<view wx:for="{{ obj }}" wx:for-item="item"  wx:for-index="key">
    <view class='aside'>{{ key }}</view>
</view>

十一、小程序的自定义组件有些像vue的组件化,好比详情页类型的内容结构复杂的页面或者是有2处及以上有复用需求的,能够用自定义组件来实现,具体教程可参考:
https://developers.weixin.qq....
https://blog.csdn.net/qq_4181...
注意:自定义组件不能用wxs。

十二、若是小程序页面要作echarts图表可视化功能,可是echarts图表有不少,须要进行封装,这种状况最好仍是采用小程序的webview API来实现,
具体教程可参考:
https://developers.weixin.qq....
https://www.jianshu.com/p/292...

已经有作好的webAPP项目,可是要同步开发小程序,详情页有不少echarts图表,这种状况就很适合用webview,我刚开始的时候不知道webview,在研究自定义组件,在构思怎么封装全局可以使用的line、bar、pie、面积图这四种公共组件,当时没想好怎么作,很麻烦。后来CTO告诉我用webview来实现。

好比已经作好了一个vue框架的webapp项目,而后只须要vue-cli再起一个vue项目,而后把之前作好的详情页图表相关的代码结构照搬过来就好了,无非就是改一点儿东西。

好比个人web端项目的详情页加起来有9个模块,近百个echarts图表,若是用户初次进入页面就加载所有的接口,那么浏览器内存会很高,用户会卡死几秒的时间,体验不好,因此用户初次进入页面是默认不加载图表相关接口的。我采用了每一个模块作成折叠面板的方案,点击展开时展现该模块下的全部图表,收起时销毁图表实例释放内存,而且只在第一次展开时加载接口,后面收起再展开时就不须要重复请求接口了。

而小程序webview所需的vue项目,好比详情页9个模块,能够在小程序里定义为9个page页面,而后点击每一个模块时跳转到这个模块对应的page页面,而且把这个模块下全部图表所需的参数(好比商品id),经过url传过去。而后这个page的wxml里放webview组件,动态设置src。js里获取从详情页点击模块跳转过来时所携带的query参数,拼接好之后,setData设置webviewURL。大概是这样:

<!--商品详情页——图表模块标题-->
点击图表模块时跳转到这个模块对应的page页面,而且携程必备query参数过去,好比我是这样写的:

<van-cell-group>
    <van-cell icon="location-o" title="查看图表详情" url="/pages/Details_RegionSituation/Details_RegionSituation?id={{id}}&zip={{zip}}" is-link />
</van-cell-group>

图片描述

而后这个图表模块的page页面获取上面穿过来的query参数,并进行拼接处理,处理好后setData设置webview的src,我是这样写的:

<!--图表模块的采用webview组件的page页面——wxml-->
<view class="page-body">
    <view class="page-section page-section-gap">
        <web-view src="{{ webviewURL }}"></web-view>
    </view>
</view>

<!--图表模块的采用webview组件的page页面——js-->
data: {
    id: null, //商品id
    zip: null,
},
onLoad: function (options) {
        // console.log(options)
        //获取url参数
        this.setData({
            id: options.id || null,
            zip: options.zip || null
        });

        let url = `https://-----此处为你配置的业务域名-------/situation?id=${this.data.id}&zip=${this.data.zip}`;
        
        // situation为模块页面名称,随便你怎么定义。后面就是query参数

        this.setData({
            webviewURL: url
        });
},

【之因此项目详情页里有9个图表模块,小程序就要新建9个page页面,是由于一个page页面只能放一个webview组件,而且会覆盖掉其余组件。】

而后在vue项目里获取到小程序webview src跳转的时候携带的query参数,而后进行接口请求数据,配置图表,就完事儿了。
记得退出页面时也要销毁图表实例,vue项目的生命周期是这样的:

beforeDestroy () {
    if(this.myEcharts){
        this.myEcharts.dispose();
    }
},

具体流程就是以上这些了,并不复杂。

这样下来节省了大量的工做,详情页9个图表模块,加起来近百个echarts图表,用webview从无到有只用了三四天时间,我就不用头疼麻烦的用小程序的自定义组建来实现需求了。

1三、image组件默认图片的宽度300px、高度225px,有点二恶心,要实现实现宽度100%,高度自适应效果,要使用mode="widthFix"参数,参考API文档:https://developers.weixin.qq....

1四、实现 Anchor 锚点定位,相似楼层导航的功能,主要使用scroll-view组件的scroll-into-view属性,参考教程:https://developers.weixin.qq....
https://blog.csdn.net/weixin_...

1五、使用txv-video标签,实现腾讯视频播放功能。

【txv-video标签的方案】
1️⃣:登陆上微信公众平台,而后第三方设置里,添加腾讯视频插件。
图片描述

2️⃣:在app.json里添加以下代码

"plugins": {
    "tencentVideo": {
        "version": "1.3.0",
        "provider": "wxa75efa648b60994b"
    }
}

//version是腾讯视频插件的版本号,我今天安装完,查看最新更新的版本是1.3.0。
//provider是小程序的AppID,填对应本身开发的小程序AppID便可

3️⃣:在要用txv-video标签的页面的json文件里添加以下代码

"usingComponents": {
    "txv-video": "plugin://tencentVideo/video"
}

4️⃣:取出接口返回的src中的vid,(我使用的是web端的接口,video字段返回的是embed标签,v-html直接渲染出来,然鹅,小程序不能用rich-text渲染embed标签。。而后取出vid的逻辑看本身怎么实现吧,个人代码放上来仅供参考,可能有点儿傻😝)

//取出video中src
let videoSrc;
if (res.data.video.includes("src=")) {
    videoSrc = res.data.video.split('src=')[1].split('allowFullScreen')[0]; 
}
console.log(videoSrc)
//取出videoSrc中vid的值
let vid;
if (videoSrc.includes("vid=")) {
    vid = videoSrc.split('vid=')[1].split('&auto')[0];
}
this.setData({
    vid: vid
});
console.log(vid)
console.log(this.data.vid)

5️⃣:而后在wxml里使用txv-video标签,就完事儿了,蛋疼的是有广告😒

//playerid名字随便取,相似于id,是惟一的
<txv-video vid="{{ vid }}" playerid="txvVideo1"></txv-video>

到此就算完事儿了,播放腾讯视频的功能已经完成,至于产品需求有多个视频/有视频列表,要作动态切换的话,就本身慢慢摸索吧,应该没什么难度。小程序目前看来最方便的就是用txv-video标签,而后传过去vid值,就能够实现播放腾讯视频的功能了,比下面的video组件的方案好,video组件的方案太麻烦,并且已通过去很长时间了,属于取巧的一种方法吧。

【video组件实现播放腾讯视频的方案】
具体流程参考这篇教程:https://blog.csdn.net/qq_4162...,前面取vid值的逻辑是同样的,只不事后面要发接口vv.video.qq.com,再根据返回的字段,切割拼接出完整的video url,就是这么个逻辑。

注:我没顺利完成,由于卡在了配置服务器域名这一步,https://tcb-api.tencentclouda...、https://vv.video.qq.com这两个域名我都添加配置好了,可是请求接口时会报错:https://vv.video.qq.com 不在如下 request 合法域名列表中,请参考文档:https://developers.weixin.qq....
刚开始我觉得是配置服务器域名,小程序有缓存,要等10分钟,后来仍是不行,果断放弃该方案了。

1六、点击图片预览大图,通常详情页的轮播图使用。
参考文档:https://developers.weixin.qq....

//wxml
<swiper indicator-dots  circular indicator-active-color="#fff" current wx-if="{{ !housePhotoNoDataShow }}">
    <block wx:for="{{ housePhotoItem }}" wx:for-item="item" wx:key="index">
        <swiper-item>
            <image src='{{ item }}' lazy-load mode="aspectFill" data-index='{{index}}' bindtap='previewImg'></image>
        </swiper-item>
    </block>
</swiper>

//js
previewImg(e) {
    var currentImgIndex = e.currentTarget.dataset.index;
    var imgArr = this.data.housePhotoItem;
    // console.log(currentImgIndex, imgArr);
    wx.previewImage({
        current: imgArr[currentImgIndex],     //当前图片地址
        urls: imgArr,               //全部要预览的图片的地址集合-数组形式
        success: function (res) {
            console.log(res)
        },
        fail: function (res) {
            console.log(res)
        },
        complete: function (res) {
            console.log(res)
        },
    })
},

1七、app.js新增更新线上版本的用户友好提示(用于热启动时及时提示用户有新版本更新,冷启动时会自动下载更新),参考官方文档:https://developers.weixin.qq....

App({
    onLaunch: function (options) {
        // 获取小程序更新机制兼容
        if (wx.canIUse('getUpdateManager')) {
            const updateManager = wx.getUpdateManager();

            //监听向微信后台请求检查更新结果事件。微信在小程序冷启动时自动检查更新,不需由开发者主动触发。
            updateManager.onCheckForUpdate(function (res) {
                // 请求完新版本信息的回调
                console.log(res.hasUpdate)
            });

            //监听小程序有版本更新事件。客户端主动触发下载(无需开发者触发),下载成功后回调
            updateManager.onUpdateReady(function () {
                wx.showModal({
                    title: '新版本更新提示~',
                    content: '本小程序新版本已经准备好,是否重启应用?',
                    success: function (res) {
                        if (res.confirm) {
                            // 新版本已经下载好,调用 applyUpdate 应用新版本并重启
                            updateManager.applyUpdate()
                        }
                    }
                });
            });

            //监听小程序更新失败事件。小程序有新版本,客户端主动触发下载(无需开发者触发),下载失败(多是网络缘由等)后回调
            updateManager.onUpdateFailed(function () {
                // 新版本下载失败
                wx.showModal({
                    title: '已经有新版本了哟~',
                    content: '本小程序最新版本已经上线啦~,请您在小程序列表删除当前小程序,从新搜索关键词打开本小程序便可体验最新版本哟~',
                })
            });
        } else {
            // 提示用户在最新版本的客户端上体验您的小程序
            wx.showModal({
                title: '华美优胜提示您:',
                content: '当前微信版本太低,没法正常使用小程序,请升级到最新微信版本后重试。'
            })
        }
    },
})
相关文章
相关标签/搜索