- 全局自定义弹框/提示框(Uniapp)
场景:任意页面都可以使用方法的形式唤起弹框/提示框 框架:uniapp+Vue3+vite 第一步:安装依赖 npm i @yck-web/vite-plugin-template-inset 该插件在转换的时候使用正则对页面进行自定义弹框的添加 第二步:修改配置vite.config.js, plugins中添加插件(位置需要放在uni()方法前面) import uni from "@dcloudio/vite-plugin-uni"; import vitePluginTemplateInset from "@yck-web/vite-plugin-template-inset"; plugins: [ vitePluginTemplateInset(["<DialogMessage ref='DialogMessage'></DialogMessage>"]), uni(), ], 第三步:编辑自定义组件 DialogMessage/index.vue <template name="dialogMessage"> <view class="mask" v-if="show"> <view class="content"> <view class="title">系统升级</view> <view class="hint">为了给您提供更好的体验<br />系统已升级<br />快去试试看吧!</view> <van-button class="jump-btn" @click="handleToMini" type="primary" size="large"> 去使用 </van-button> </view> </view> </template> <!-- 自定义全局弹框 --> <script setup lang="ts"> import { ref } from "vue"; let show = ref(false); const open = () => { show.value = true; }; const close = () => { show.value = false; }; const handleToMini = () => { uni.showToast({ icon: "success", title: "成功", duration: 3000, }); close(); }; //暴露open和close方法 defineExpose({ open, close, }); </script> <style lang="scss" scoped> .mask { position: fixed; left: 0; top: 0; right: 0; bottom: 0; height: 100vh; width: 100vw; display: flex; justify-content: center; align-items: center; background-color: rgba(0, 0, 0, 0.6); z-index: 99999; padding: 20rpx; } .content { width: 100%; background-color: #fff; display: flex; flex-direction: column; justify-content: center; align-items: center; border-radius: 32rpx; padding: 40rpx 20rpx; .title { font-size: 38rpx; margin-bottom: 20rpx; } .hint { font-size: 24rpx; margin-bottom: 16rp; text-align: center; } .jump-btn { width: 100%; background: $theme-color; border-radius: 48rpx; color: #ffffff; cursor: pointer; text-align: center; margin-top: 40rpx; } } </style> 第四步:main.js全局注入 import DialogMessage from "@/components/DialogMessage/index.vue"; app.component("DialogMessage", DialogMessage); 第五步:页面使用 <template> <view class="home-page"> <van-button class="jump-btn" @click="handleClick" type="primary" size="large"> 打开全局弹框 </van-button> </view> </template> <script lang="ts" setup> import { getCurrentInstance } from "vue"; const instance = getCurrentInstance() as any; const handleClick = () => { console.log("handleClick", instance?.ctx?.$refs); instance?.ctx?.$refs.DialogMessage.open(); }; </script> 效果如下: [图片]
2023-03-28 - 高适应性的自定义导航栏开发思路
[图片] 非自定义导航栏高度怎么计算? 自定义导航栏高度由谁决定? 小程序自定义导航栏开发注意点与参考文档 一、默认导航栏高度怎么计算?(非custom情况下获取) wx.getSystemInfo 和 wx.getSystemInfoSync 获取机器信息 screenHeight - windowHeight 计算标题栏高度 [代码]{[代码][代码] [代码][代码]'iPhone'[代码][代码]: 64,[代码][代码] [代码][代码]'iPhone X'[代码][代码]: 88,[代码][代码] [代码][代码]'android'[代码][代码]: 68[代码][代码] [代码][代码]}[代码]不完全统计(ip6 , ip5 , ip6p , ipx , 小米mix2 , 小米5等综合了开发工具提供的数据和真机数据)所得 二、自定义导航栏高度由谁决定?(自定义情况下,屏幕高度和窗口高度没有差别,所以要通过步骤1先获取数据,预定义到代码中) 开发时发现,自定义导航栏的实现需要 包含状态栏+胶囊 :没有自定义导航栏的时候页面是全屏幕滚动会出现在状态栏的下一层 根据上一标题中步骤1的函数,可以获得状态栏高度 statusBarHeight demo,点击打开小程序开发工具 三、小程序自定义导航栏开发注意点与参考文档 微信官方设计指导中关于胶囊按钮的描述 由此得知胶囊宽度87pt=116px,设置之后,的确能产生较好的兼容性效果 社区Q&A:自定义标题栏高度计算、在 navigationStyle: 'custom',苹果X和8兼容问题 注意某些方法、参数的兼容性,时刻关注官方更新信息 开一个项目采集设备的screenHeight,windowHeight,pixelRatio等信息到一个数据库中,或者微信可以提供这样一个数据库便于计算,亦或者微信优化自定义标题栏(譬如通知栏可以改变颜色但不要算在自定义范围内,给出胶囊宽高到通知栏距离到右侧屏幕边框距离等相关参数)
2018-07-31 - 【优化】利用函数防抖和函数节流提高小程序性能
大家好,上次给大家分享了swiper仿tab的小技巧: https://developers.weixin.qq.com/community/develop/article/doc/000040a5dc4518005d2842fdf51c13 [代码]今天给大家分享两个有用的函数,《函数防抖和函数节流》 函数防抖和函数节流是都优化高频率执行js代码的一种手段,因为是js实现的,所以在小程序里也是适用的。 [代码] 首先先来理解一下两者的概念和区别: [代码] 函数防抖(debounce)是指事件在一定时间内事件只执行一次,如果在这段时间又触发了事件,则重新开始计时,打个很简单的比喻,比如在打王者荣耀时,一定要连续干掉五个人才能触发hetai kill '五连绝世'效果,如果中途被打断就得重新开始连续干五个人了。 函数节流(throttle)是指限制某段时间内事件只能执行一次,比如说我要求自己一天只能打一局王者荣耀。 这里也有个可视化工具可以让大家看一下三者的区别,分别是正常情况下,用了函数防抖和函数节流的情况下:http://demo.nimius.net/debounce_throttle/ [代码] 适用场景 函数防抖 搜索框搜索联想。只需用户最后一次输入完,再发送请求 手机号、邮箱验证输入检测 窗口resize。只需窗口调整完成后,计算窗口大小。防止重复渲染 高频点击提交,表单重复提交 函数节流 滚动加载,加载更多或滚到底部监听 搜索联想功能 实现原理 [代码] 函数防抖 [代码] [代码]const _.debounce = (func, wait) => { let timer; return () => { clearTimeout(timer); timer = setTimeout(func, wait); }; }; [代码] [代码] 函数节流 [代码] [代码]const throttle = (func, wait) => { let last = 0; return () => { const current_time = +new Date(); if (current_time - last > wait) { func.apply(this, arguments); last = +new Date(); } }; }; [代码] [代码] 上面两个方法都是比较常见的,算是简化版的函数 [代码] lodash中的 Debounce 、Throttle [代码] lodash中已经帮我们封装好了这两个函数了,我们可以把它引入到小程序项目了,不用全部引入,只需要引入debounce.js和throttle.js就行了,链接:https://github.com/lodash/lodash 使用方法可以看这个代码片段,具体的用法可以看上面github的文档,有很详细的介绍:https://developers.weixin.qq.com/s/vjutZpmL7A51[代码]
2019-02-22 - 帮你查天气——基于百度地图天气API
先上截图: [图片] 小程序二维码: [图片] 一、申请百度地图的AK 在百度地图开放平台上注册账号并登录,然后在“控制台”中创建一个应用。 [图片] 选择“微信小程序”,并填入创建小程序时得到的APP ID。 [图片] 提交后就可以在前一个页面中看到新创建的应用的AK了。 二、下载SDK 在“开发文档”中点击“微信小程序JavaScript API” [图片] 在“相关下载”中点击“全部下载”。 [图片] 压缩包里主要包括两个文件夹:[代码]demo[代码]和[代码]src[代码],开发时主要用到[代码]src[代码]里的js文件:[代码]bmap-wx.js[代码](为讲解方便,本文不使用[代码].min[代码])。 三、配置服务器域名 登录微信小程序管理后台,进入开发——开发设置 [图片] 在服务器域名中,填入request合法域名:https://api.map.baidu.com [图片] PS:微信要求域名都为https,所以有些API为http的就不能用了。 四、写代码 打开微信开发者工具,并新建一个小程序项目,会自动生成一些文件(新建项目的方法、各文件的作用,网上有很多教程,不再赘述)。 1、打开[代码]index.js[代码]文件,添加对[代码]bmap-wx.js[代码]文件的引用: [代码]//index.js //获取应用实例 const app = getApp() //调用百度地图天气API的js文件 var bmap = require('../../utils/bmap-wx.js'); [代码] 2、在[代码]onLoad[代码]方法中,新建一个[代码]BMapWX[代码]对象,并填入AK: [代码]var BMap = new bmap.BMapWX({ ak: '你申请的百度地图AK' }); [代码] 3、在[代码]onLoad[代码]方法中,发起查询天气的请求: [代码]BMap.weather({ fail: fail, success: success }); [代码] 4、在[代码]onLoad[代码]方法中,定义查询成功和失败的方法: [代码]var fail = function(data) { console.log('查询失败') }; var success = function(data) { console.log('查询成功'); var currentWeather = data; this.setData({ currentWeather: currentWeather }); } [代码] 注意,[代码]setData[代码]中的[代码]currentWeather[代码]要与[代码]Page[代码]中的[代码]data[代码]部分对应: [代码]data: { currentWeather: '' }, [代码] 至此,就可以获得返回的天气数据了,剩下的工作就是解析返回的数据。 五、解析数据 在第三步中,查询成功获得的返回数据[代码]data[代码]包括了我们需要展示的信息,因此解析的工作也主要是针对[代码]data[代码]。 data主要包括两部分内容:currentWeather和originalData [图片] 1、解析data.currentWeather 结构如下: [图片] 解析方式如下: [代码]var currentWeather = data.currentWeather[0]; //currentWeather.currentCity:"济南市" //currentWeather.date:"周四 01月17日 (实时:3℃)" //currentWeather.pm25:"85" //currentWeather.temperature:"7 ~ -2℃" //currentWeather.weatherDesc:"晴" //currentWeather.wind:"南风微风" [代码] 注意,data.currentWeather是一个JSON数组,关键的数据都存在data.currentWeather[0]中 2、解析data.originalData 结构如下: [图片] data.originalData也是JSON格式,我们关心的数据存在data.originalData.results数组中,结构如下: [图片] 可以看出,data.originalData.results[0]数组中关键的部分也是两块:index数组和weather_data数组: [图片] data.originalData.results[0].index[0]是穿衣的相关信息 data.originalData.results[0].index[1]是洗车的相关信息 data.originalData.results[0].index[2]是感冒的相关信息 data.originalData.results[0].index[3]是运动的相关信息 data.originalData.results[0].index[4]是紫外线强度的相关信息 [图片] data.originalData.results[0].weather_data[0]是今天的天气情况 data.originalData.results[0].weather_data[1]是明天的天气情况 data.originalData.results[0].weather_data[2]是后天的天气情况 data.originalData.results[0].weather_data[3]是大后天的天气情况 至此,就完成了数据解析工作,通过setData可以将数据与index.wxml中的变量绑定。修改success如下: [代码]var success = function(data) { console.log('查询成功'); //实时天气 var currentWeather = data.currentWeather[0]; //感冒信息 var flu = data.originalData.results[0].index[2]; //未来三天的天气 var forecast = new Array(3); for (var i = 0; i < 3; i++) { forecast[i] = data.originalData.results[0].weather_data[i + 1]; } //配置数据 this.setData({ currentWeather: currentWeather, flu: flu, forecast: forecast }); } [代码] 在index.wxml文件中调用: [代码]<!--当前定位的城市--> <view class='cityName'>{{currentWeather.currentCity}}</view> <!--未来3天的天气情况,包括日期、天气描述、温度范围、风力--> <view class='forecast'> <view class='next-day' wx:key="{{index}}" wx:for="{{forecast}}"> <view class='detail date'>{{item.date}}</view> <view class='detail'>{{item.weather}}</view> <view class='detail'>{{item.temperature}}</view> <view class='detail'>{{item.wind}}</view> </view> </view> <!--感冒信息--> <view class='tips'> <view class='index'>感冒指数:{{flu.zs}}</view> <view class='description'>{{flu.des}}</view> </view> [代码] 六、bmap-wx.js简单介绍 打开bmap-wx.js文件,可以看到只有一个类BMapWX。该类包含了四个方法,而我们需要用到的是weather(param)方法: [代码]/** * 天气检索 * * @param {Object} param 检索配置 */ weather(param) { var that = this; param = param || {}; let weatherparam = { coord_type: param["coord_type"] || 'gcj02', output: param["output"] || 'json', ak: that.ak, sn: param["sn"] || '', timestamp: param["timestamp"] || '' }; let otherparam = { success: param["success"] || function () {}, fail: param["fail"] || function () {} }; let type = 'gcj02'; let locationsuccess = function (result) { weatherparam["location"] = result["longitude"] + ',' + result["latitude"]; wx.request({ url: 'https://api.map.baidu.com/telematics/v3/weather', data: weatherparam, header: {"content-type": "application/json"}, method: 'GET', success(data) { let res = data["data"]; if (res["error"] === 0 && res["status"] === 'success') { let weatherArr = res["results"]; // outputRes 包含两个对象, // originalData为百度接口返回的原始数据 // wxMarkerData为小程序规范的marker格式 let outputRes = {}; outputRes["originalData"] = res; outputRes["currentWeather"] = []; outputRes["currentWeather"][0] = { currentCity: weatherArr[0]["currentCity"], pm25: weatherArr[0]["pm25"], date: weatherArr[0]["weather_data"][0]["date"], temperature: weatherArr[0]["weather_data"][0]["temperature"], weatherDesc: weatherArr[0]["weather_data"][0]["weather"], wind: weatherArr[0]["weather_data"][0]["wind"] }; otherparam.success(outputRes); } else { otherparam.fail({ errMsg: res["message"], statusCode: res["status"] }); } }, fail(data) { otherparam.fail(data); } }); } let locationfail = function (result) { otherparam.fail(result); } let locationcomplete = function (result) { } if (!param["location"]) { that.getWXLocation(type, locationsuccess, locationfail, locationcomplete); } else { let longitude = param.location.split(',')[0]; let latitude = param.location.split(',')[1]; let errMsg = 'input location'; let res = { errMsg: errMsg, latitude: latitude, longitude: longitude }; locationsuccess(res); } } [代码] 可以看出,成功返回的数据为data,通过解析,封装成了我们在前面得到的data.currentWeather和data.originalData两个数组。 另外,程序中默认查询的城市是当前定位的城市,依据的参数是经纬度坐标。 [代码]weatherparam["location"] = result["longitude"] + ',' + result["latitude"]; [代码] 如果想查询其它城市,例如北京,可以修改为: [代码]weatherparam["location"] = param["北京"]; [代码] 其中param就是weather()函数的参数。
2019-02-22