- 如何自己制作小程序?
现在小程序非常流行,很多人都想制作一个自己的小程序来卖货。以前制作小程序通常需要请小程序开发公司,而且需要每年给多少钱(通常几百到几千)。但随着微信越来越完善,现在无需找小程序服务商搭建,无需懂代码、源码、编程,即可一键生成属于自己的小程序。 那就是微信官方免费提供的小程序:微信小商店,任何人(个人/个体户/公司/组织)都可以免费申请。下面为大家具体介绍自助开通小程序的步骤: 1. 手机微信搜索:小商店助手。进入小程序后,点击免费开店。 [图片] 2. 选择小商店类型。如果没有营业执照,可以选择个人。这证明个人可以开通小程序卖货,现在确实是一个人人卖货的时代。 [图片] 3.开店成功。至此小程序已经一键生成了,接下来完善一下开店信息。 [图片] 4.完善经营者信息。需要上传经营者身份信息,然后提交审核。 [图片] 5. 微信审核通过后,点击签约开张。注意:虽然免费开通了小程序,但是微信还是会收取交易手续费。目前费率是千分之六,也就是一千元交易额微信会收取六元钱手续费。 [图片] 6.上传商品。进入小商店首页,点击去发布商品。 [图片] [图片] 7. 添加更多功能。可以电脑登录小商店服务市场,选择对应的服务来给小程序设置装修、会员、订单打印发货等功能。如小程序对接小票、标签、发货单、电子面单打印机,小程序对接快递物流或者同城配送等第三方外卖平台,可以选择订单管家_订单自动打印发货服务。 [图片] 好了,以上就是介绍,希望可以帮助到您。人人卖货时代,祝福大家都能够卖出好业绩!
2021-05-24 - input键盘弹出时,滚动页面,输入框内容错位问题
在ios9.+的版本上,遇到了一个问题。在键盘弹出的时候,快速滚动页面,输入的内容或input提示语会错位。且有时无法恢复到原有位置。当然,前提是你这个页面是超过一屏需要滚动的时候 [图片] 解决办法: always-embed=true [图片]
2022-04-18 - 教你怎么监听小程序的返回键
更新:2020年7月28日08:51:11 基础库2.12.0起,可以调用wx.enableAlertBeforeUnload监听原生右上角返回、物理返回以及wx.navigateBack时弹框提示 AIP详情请看: https://developers.weixin.qq.com/miniprogram/dev/api/ui/interaction/wx.enableAlertBeforeUnload.html //======================================== 怎么监听小程序的返回键? 应该有很多人想要监听用户的这个动作吧,但是很遗憾,小程序不会给你这个API的,那是不是就没辙了? 幸好我们还可以自定义导航栏,这样一来我们就可以监听用户的这一动作了。 什么?这你已经知道啦? 那好咱们就不说自定义导航栏的返回监听了,说一下物理返回和左滑?右滑?(不管了,反正是滑)返回上一页怎么监听。 监听物理返回 首先说一下这个监听方法的缺点,虽说是监听,但是还是无法真正意义上的监听并拦截来阻止页面跳转,页面还是会返回上一页,而后重新载入刚刚的页面,如果这不是你想要的,那可以不用往下看了 其次说一下用到什么东西: wx.onAppRoute、wx.showModal 最后是一些主要代码: 重写wx.showModal,主要是加个confirmStay参数和使wx.showModal Promise化 [代码]const { showModal } = wx; Object.defineProperty(wx, 'showModal', { configurable: false, // 是否可以配置 enumerable: false, // 是否可迭代 writable: false, // 是否可重写 value(...param) { return new Promise(function (rs, rj) { let { success, fail, complete, confirmStay } = param[0] param[0].success = (res) => { res.navBack = (res.confirm && !confirmStay) || (res.cancel && confirmStay) wx.setStorageSync('showBackModal', !res.navBack) success && success(res) rs(res) } param[0].fail = (res) => { fail && fail(res) rj(res) } param[0].complete = (res) => { complete && complete(res) (res.confirm || res.cancel) ? rs(res) : rj(res) } return showModal.apply(this, param); // 原样移交函数参数和this }.bind(this)) } }); [代码] 使用wx.onAppRoute实现返回原来的页面 [代码]wx.onAppRoute(function (res) { var a = getApp(), ps = getCurrentPages(), t = ps[ps.length - 1], b = a && a.globalData && a.globalData.pageBeforeBacks || {}, c = a && a.globalData && a.globalData.lastPage || {} if (res.openType == 'navigateBack') { var showBackModal = wx.getStorageSync('showBackModal') if (c.route && showBackModal && typeof b[c.route] == 'function') { wx.navigateTo({ url: '/' + c.route + '?useCache=1', }) b[c.route]().then(res => { if (res.navBack){ a.globalData.pageBeforeBacks = {} wx.navigateBack({ delta: 1 }) } }) } } else if (res.openType == 'navigateTo' || res.openType == 'redirectTo') { if (!a.hasOwnProperty('globalData')) a.globalData = {} if (!a.globalData.hasOwnProperty('lastPage')) a.globalData.lastPage = {} if (!a.globalData.hasOwnProperty('pageBeforeBacks')) a.globalData.pageBeforeBacks = {} if (ps.length >= 2 && t.onBeforeBack && typeof t.onBeforeBack == 'function') { let { onUnload } = t wx.setStorageSync('showBackModal', !0) t.onUnload = function () { a.globalData.lastPage = { route: t.route, data: t.data } onUnload() } } t.onBeforeBack && typeof t.onBeforeBack == 'function' && (a.globalData.pageBeforeBacks[t.route] = t.onBeforeBack) } }) [代码] 改造Page [代码]const myPage = Page Page = function(e){ let { onLoad, onShow, onUnload } = e e.onLoad = (() => { return function (res) { this.app = getApp() this.app.globalData = this.app.globalData || {} let reinit = () => { if (this.app.globalData.lastPage && this.app.globalData.lastPage.route == this.route) { this.app.globalData.lastPage.data && this.setData(this.app.globalData.lastPage.data) Object.assign(this, this.app.globalData.lastPage.syncProps || {}) } } this.useCache = res.useCache res.useCache ? reinit() : (onLoad && onLoad.call(this, res)) } })() e.onShow = (() => { return function (res) { !this.useCache && onShow && onShow.call(this, res) } })() e.onUnload = (() => { return function (res) { this.app.globalData = Object.assign(this.app.globalData || {}, { lastPage: this }) onUnload && onUnload.call(this, res) } })() return myPage.call(this, e) } [代码] 在需要监听的页面加个onBeforeBack方法,方法返回Promise化的wx.showModal [代码]onBeforeBack: function () { return wx.showModal({ title: '提示', content: '信息尚未保存,确定要返回吗?', confirmStay: !1 //结合content意思,点击确定按钮,是否留在原来页面,confirmStay默认false }) } [代码] 运行测试,Oj8K 是不是很简单,马上去试试水吧,效果图就不放了,静态图也看不出效果,动态图懒得弄,想看效果的自己运行代码片段吧 代码片段 https://developers.weixin.qq.com/s/hc2tyrmw79hg
2020-07-28 - 基础库切换到2.0.4以上版本,WAService.js就找不到
[图片] [图片] 我选择2.1.1的基础库,报错说是WAService.js找不到,显示网络连接错误 但我切换到2.0.4就可以 [图片]
2018-06-26 - 最近开发小程序,开发版/体验版/线上版会混淆是什么问题?
最近开发小程序,开发版/体验版/线上版会混淆是什么问题? 开发版设置的页面,接口域名会与线上的冲突,开发版的请求域名,接口会直接被替换成线上的,要讲正式版的小程序删掉,并在开发版打开调试模式,才正常,以前都没这问题,现在是开发/体验/正式共用一个存储空间吗?
2019-11-27 - 用__wxConfig.envVersion区分小程序体验版,开发板,正式版
在开发过程中,通常测试版和正式版的api的根路径不同,需要在发布时手动去更改路径,这就显得很繁琐,然后官方也没有给出相应的判断环境的api,其实小程序是预设了这个api的,只是不知道为什么没有公布出来,这个api就是 __wxConfig 关键点 — __wxConfig 在控制台中打印__wxConfig可以得到一下数据 [图片] 其中的envVersion为运行环境,有以下几个值 envVersion: ‘develop’, //开发版 envVersion: ‘trial’, //体验版 envVersion: ‘release’, //正式版 其中的platform为运行的平台 有Android ios devtools 等 之前一直不知道微信小程序可以用__wxConfig.envVersion区分小程序体验版,开发板,正式版 目前在官方文档没有查到相关资料,但是亲测可用 [代码] envVersion 类型为字符串 envVersion: 'develop', //开发版 envVersion: 'trial', //体验版 envVersion: 'release', //正式版 [代码] 具体代码可参考如下截图 [图片] 20191120 其实在我们的开发过程中是不需要这个变量的,因为我们开发版、体验版、和生产版是三个不同的小程序,所以不需要根据环境变量来区分 20191121摘自社区帖子 [代码]const env = typeof __wxConfig !== "undefined" ? __wxConfig.envVersion || "release" : "release"; const isProd = env === "release"; const protocol = isProd ? "https://" : "http://"; const baseApi = { develop: "testapi.com", trial: 'readyapi.com', release: "api.com" }; export const api = protocol + baseApi[env]; [代码]
2019-11-20 - 你不知道的小程序系列之生命周期执行顺序
再次开始之前先问几个问题: 你是否知道[代码]Page[代码]生命周期 与 [代码]pagelifetimes[代码] 生命周期执行顺序? 你是否知道[代码]behaviors[代码]中的生命周期与组件生命周期执行顺序? 你是否知道[代码]Page[代码]生命周期 与 组件[代码]pagelifetimes[代码]生命周期执行顺序? 要回答上面的问题,首先我们看看小程序生命周期有哪些: App onLaunch onShow onHide Page onLoad onShow onReady onHide onUnload Component created attached ready moved detached 想一下加载一个页面(包含组件)的加载顺序,按照直觉小程序加载顺序应该是这样的加载顺序(以下列子中[代码]Component[代码]都是同步组件): App(onLaunch) -> Page(onLoad) -> Component(created) 但其实并不然,小程序的加载顺序是这样的: 首先执行 [代码]App.onLaunch[代码] -> [代码]App.onShow[代码] 其次执行 [代码]Component.created[代码] -> [代码]Component.attached[代码] 再执行 [代码]Page.onLoad[代码] -> [代码]Page.onShow[代码] 最后 执行 [代码]Component.ready[代码] -> [代码]Page.onReady[代码] 其实也不难理解微信这么设计背后的逻辑,我们先看下官方的的生命周期: [图片] 可以看到,在页面[代码]onLoad[代码]之前会有页面[代码]create[代码]阶段,这其中就包含了组件的初始化,等组件初始化完成之后,才会执行页面的[代码]onLoad[代码], 之后页面[代码]ready[代码]事件也是在组件[代码]ready[代码]之后才触发的。 下面我们来看看 [代码]Behavior[代码], [代码]Behavior[代码] 与 [代码]Vue[代码]中的 [代码]mixin[代码] 类似,猜想下其中的执行顺序: Behavior.created => Component.created 测试下来和预期相符,其实在[代码]Vue[代码]的文档中有一段这样的描述: 另外,混入对象的钩子将在组件自身钩子之前调用。 这样的设计和主流设计保持一致。接下来我们看看 [代码]pageLifetimes[代码],有[代码]show[代码]和[代码]hide[代码]生命周期对应页面的展示与隐藏,预期的执行顺序: pageLifetime.show => Page.onShow 测试下来也和预期相符,那么我们可以推断出如下的结论: 当页面中包含组件时,组件的生命周期(包括pageLifetimes)总是优先于页面,[代码]Behaviors[代码]生命周期优先于组件的生命周期。但其实有个例外:页面退出堆栈,当页面[代码]unload[代码]时会执行如下顺序: Page.onUnload => Component.detached 看了以上的分析你应该知道了答案,最后做个总结(demo): [图片] 最后的最后布置个作业 异步组件(异步渲染的组件,通常是通过if条件判断是否渲染)的生命周期执行顺序是怎样的,pagelifetimes会不会执行?
2020-01-10 - cover-view,fixed时定位异常
- 问题描述 因需求需要 需要在tabbar页面外其他页面也支持tabbar 故引用了 自定义tabbar组件 然后发现在其他引入tabbar的页面 多次请求数据后,底部的tabbar会浮动上去,看了下tabbar的实现,因层级问题,tabbar使用了cover-view。定位是position:fixed; bottom:0; 如无意外是固定底部的。在社区搜索了一下,发现其他老哥在使用cover-view 在定位为fixed时也出现类似情况。 数据动态请求的,故好像放源码并没有大效用。目前测试只在苹果系统复现该问题。 好像这个bug到现在已经好久了,望回复,谢谢了! - bug复现机型: 苹果6s 系统 ios10 微信版本7.0.0 苹果7splus 系统 ios11 微信版本7.0.3 - 当前 Bug 的表现: [图片] - 预期表现 [图片]
2019-03-18 - 小程序使用async/await 来处理异步
小程序使用async/await 来处理异步 regeneratorRuntime https://github.com/facebook/regenerator/blob/master/packages/regenerator-runtime/runtime.js 详细看代码片段 https://developers.weixin.qq.com/s/FlIPCOmw7P3c //引入编译模块 const regeneratorRuntime =require("../libs/regeneratorRuntime.js") const promisify = require('../libs/promisify.js'); //微信 API,转成返回 Promise 的接口 云开发API的有Promise 风格 不需要再转了 const getUserInfo= promisify(wx.getUserInfo); const login = promisify(wx.login); wx.cloud.init(); Page({ data: { }, onLoad: async function () { console.log(this) const user = await getUserInfo(); console.log("onLoad user",user) const code = await login(); console.log("onLoad code",code); const res = await wx.cloud.database().collection('todos').where({ _openid: 'xxx' }).get(); console.log("onLoad res", res) }, onShow: async function(){ const user = await getUserInfo(); console.log("onshow", user) } })
2018-11-10