微信小程序面试题
微信小程序页面的生命周期函数主要包括哪些?
onLoad: 页面加载时触发。一个页面只会调用一次,可以在onLoad的参数中获取打开当前页面路径中的参数。
onShow: 页面显示时触发调用。
onReady: 页面初次渲染完成时触发,一个页面只会调用一次。
onHide: 页面隐藏时触发,如navigateTo或底部tab切换到其他页面等。
onUnload: 页面卸载时触发。如redirectTo或navigateBack到其他页面时。
微信小程序有哪些导航API(怎么进行页面跳转的),它们各自的应用场景与差异区别是什么?
1. uni.navigateTo(OBJECT) :
uni.navigateTo({
url: "/pages/home/src/homeDetail/homeDetail?name=" + this.info.name + "&key=1"
})
保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack可以返回到原页面。
back(){
uni.navigateBack()
},
2. uni.redirectTo(OBJECT):
关闭当前页面,跳转到应用内的某个页面。
uni.redirectTo({
url: 'test?id=1'
});
3. uni.reLaunch(OBJECT)
关闭所有页面,打开到应用内的某个页面。
uni.reLaunch({
url: 'test?id=1'
});
4. uni.switchTab(OBJECT)
跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。
跳转到 tabBar 页面只能使用 switchTab 跳转
uni.switchTab({
url: '/pages/home/home'
});
5. uni.navigateBack(OBJECT)
关闭当前页面,返回上一页面或多级页面。
uni.navigateBack({
delta: 2
});
一键授权登录怎么做
button按钮中有属性@getphonenumber用来获取用户手机号回调,需要使用open-type=“getPhoneNumber” ,以及回调@getphonenumber=“getPhoneNumber”
JS中找到getphonenumber的回调,可以拿到code,
然后通过uni.login()方法获取临时登录用户凭证,通过临时用户凭证向后端获取token
最后拿着code和token去后端换取真正的手机号
小程序什么时候会主动销毁?
小程序在进入后台之后,客户端会帮我们在一定时间内维持我们的一个状态,超过五分钟后,会被微信主动销毁。
官方也没有明确说明 什么时候销毁, 在不同机型表现也不一样,
2019年开发时:时间官方文档没有说明,但是经过询问一般指5分钟内
2020年开发时:时间官方文档没有说明,实测安卓没有固定时间,内存足够情况下,有时候一天了还在,有时候几分钟就没了。
分包的操作以及如何来计划分包
分包主要包括:使用分包、独立分包、分包预下载
分包:主包添加跳转路径,分包放内容,在pages.json配置subpakeages声明项目分包结构。
微信小程序代码包总包大小为20M,单个主包/分包大小不能超过2M。
按照功能划分的打包原则:可以按照功能的划分,拆分成几个分包,当需要用到某个功能时,才加载这个功能对应的分包;公共逻辑、组件放在主包内。
总结:首先配置好打包路径,tabbar页面必须在主包内,各分包之间不能互相调用,能调用的都在主包内。
小程序中是否存在跨域的问题
小程序中不存在跨域的问题,微信小程序有自带的api接口,wx.request();因为微信小程序不是浏览器,没有同源策略的约束,但是需要在后台配置域名白名单。开发环境可以选择不校验域名;
设置白名单:
https://mp.weixin.qq.com/

小程序中需要在管理平台设置对应可访问的授权地址,可以设置多个,最多20个域名设置。
只能支持https协议。
最大并发数为10个,socket的并发限制为5个
小程序如何进行本地存储?
小程序提供了读写本地数据缓存的接口,通过 wx.getStorage/wx.getStorageSync读取本地缓存,通过 wx.setStorage/wx.setStorageSync写数据到缓存,其中带Sync后缀的接口表示是同步接口
小程序宿主环境会管理不同小程序的数据缓存,不同小程序的本地缓存空间是分开的,每个小程序的缓存空间上限为10MB,如果当前缓存已经达到10MB,再通过wx.setStorage写入缓存会触发fail回调。
小程序的本地缓存不仅仅通过小程序这个维度来隔离空间,考虑到同一个设备可以登录不同微信用户,宿主环境还对不同用户的缓存进行了隔离,避免用户间的数据隐私泄露。
由于本地缓存是存放在当前设备,用户换设备之后无法从另一个设备读取到当前设备数据,因此用户的关键信息不建议只存在本地缓存,应该把数据放到服务器端进行持久化存储。
一个邮箱可以注册几个小程序?个人、个体工商户和企业分别可以注册几个小程序?
同一个邮箱只能申请注册1个小程序
个人和个体工商户可以注册5个小程序
企业资质可以注册50个小程序
原生的微信小程序文件类型
WXML (WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。内部主要是微信自己定义的一套组件。
WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式,
js 逻辑处理,网络请求
json 小程序设置,如页面注册,页面标题及tabBar
你熟悉哪些小程序的UI框架
uniapp对应的ui框架–>uview框架(暂时不支持vue3+vite):
https://v1.uviewui.com/
(其他的ui框架:
WeUI:WeUI 是微信官方出品的组件库,它沿用了微信的视觉设计与交互设计,提供了各类原生组件的基础样式,风格简约大方。选用这一套组件库,可以让你的小程序与微信本身保持一致的界面风格。
Vant-Weapp:适用于电商、餐饮、外卖平台、票务预订等购物类小程序
ColorUI:ColorUI 是由文晓港发布的高颜值组件库,侧重于视觉交互,适用于日记类、记账类、博客、Vlog 类小程序
iView-Weapp:了解vue技术,使用iview进行后台管理系统开发人员应该对iview的UI框不会陌生
TaroUI:TaroUI 是由京东·凹凸实验室发布的多端 UI 组件库。这套组件库,可以在 H5、微信小程序、支付宝小程序、百度小程序多端适配运行,适用小程序:工具、读书、资讯、教育、商务等,但Taro主要的技术体系是React技术方向
WuxUI:适用于开发工具类小程序,项目更新还是比较及时的)
如何实现下拉刷新与上拉加载
下拉刷新
首先需要思考的是操作的对象不同,有页面级的下拉刷新与上拉加载操作,也有scroll-view组件级的下拉刷新和上拉加载处理。
- 页面下拉刷新:
https://uniapp.dcloud.net.cn/api/ui/pulldown.html#onpulldownrefresh
在 pages.json文件中里,找到的当前页面的pages节点,并在style中开启 enablePullDownRefresh:
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app",
"enablePullDownRefresh": true
}
}
],
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#0faeff",
"backgroundColor": "#fbf9fe"
}
}
当处理完数据刷新后,uni.stopPullDownRefresh 可以停止当前页面的下拉刷新
index.vue页面中:
export default {
data() {
return {
text: 'uni-app'
}
},
onLoad: function (options) {
setTimeout(function () {
console.log('start pulldown');
}, 1000);
// 开始下拉刷新,调用后触发下拉刷新动画
uni.startPullDownRefresh();
},
onPullDownRefresh() {
console.log('refresh');
setTimeout(function () {
// 停止当前页面下拉刷新,实现回弹操作
uni.stopPullDownRefresh();
}, 1000);
}
}
- scroll-view下拉刷新:
要实现回弹得先声明一个trigger布尔数据值
然后再给scorll-view设置refresher-triggered的属性值为trigger数据值
在完成下拉刷新任务内容以后,对trigger布尔值设值为false实现下拉刷新的回弹
标签中:
<template>
<view>
<scroll-view style="height: 300px;" scroll-y="true" refresher-enabled="true" :refresher-triggered="triggered"
:refresher-threshold="100" refresher-background="lightgreen" @refresherpulling="onPulling"
@refresherrefresh="onRefresh" @refresherrestore="onRestore" @refresherabort="onAbort"></scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
triggered: false // 是否下拉状态,为false时下拉刷新回弹
}
},
onLoad() {
// 锁,规定时间内只执行一次
this._freshing = false;
setTimeout(() => {
this.triggered = true;
}, 1000)
},
methods: {
onPulling(e) {
console.log("onpulling", e);
},
onRefresh() {
if (this._freshing) return;
this._freshing = true;
setTimeout(() => {
this.triggered = false;
this._freshing = false;
}, 3000)
},
onRestore() {
this.triggered = 'restore'; // 需要重置
console.log("onRestore");
},
onAbort() {
console.log("onAbort");
}
}
}
</script>
上拉加载
在 pages.json文件中里,找到的当前页面的pages节点,并在style中,使用onReachBottomDistance设置页面上拉触底事件触发时距页面底部距离
pages.json:
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app",
"onReachBottomDistance": 50
}
}
],
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#0faeff",
"backgroundColor": "#fbf9fe"
}
}
页面下拉到底部加载更多数据,找到对应的上拉加载onReachBottom声明周期
https://uniapp.dcloud.net.cn/tutorial/page.html#lifecycle
在onReachBottom声明周期进行数据获取逻辑处理
onPageScroll : function(e) {
console.log("滚动距离为:" + e.scrollTop);
},
- 针对scroll-view组件级:
直接在使用scroll-view的组件标签中,加上属性upper-threshold,lower-threshold设置距离值,然后触发scrolltoupper事件,@scrolltoupper在对应的回调中加载数据即可
https://uniapp.dcloud.net.cn/component/scroll-view.html

小程序如何实现分享功能
在页面中如果不设置 onShareAppMessage 分享的事件回调函数,那么小程序右上角三个点的操作中不包含分享功能。
https://uniapp.dcloud.net.cn/tutorial/page.html#lifecycle
onShareAppMessage()声明周期写入页面即可:
onShareAppMessage(res) {
console.log(res);
let shareObj = {
title: '我的商城页面' || '',
path: '',
imageUrl: '',
success: function (res) {
console.log("转发成功!");
console.log(res);
}
}
console.log(shareObj);
return shareObj;
},
还可以通过页面中的某个按钮分析当前页面。button按钮的open-type属性设置为share则将调用页面中的 onShareAppMessage 事件,可以通过事件的 res中的 from 内容来判断是按钮button的分享处理还是右上角三个点menu的页面分享操作
性能
分析下微信小程序的优势与不足?
优势:
无需下载,通过搜索和扫一扫就可以打开。
良好的用户体验:打开速度快。
开发成本要比App要低。
安卓上可以添加到桌面,与原生App差不多。
为用户提供良好的安全保障。小程序的发布,微信拥有一套严格的审查流程, 不能通过审查的小程序是无法发布到线上的。
不足:
限制较多。页面大小不能超过2M,不能打开超过5个层级的页面。
样式单一,小程序的部分组件已经是成型的了,样式可改进的内容比较少,例如:幻灯片、导航。
推广面窄,不能分享朋友圈,只能通过分享给朋友,附近小程序推广,其中附近小程序也受到微信的限制。
依托于微信,无法开发后台管理功能。
微信小程序与H5的区别?
运行环境的不同:传统的HTML5的运行环境是浏览器,包括webview。微信小程序的运行环境并非完整的浏览器,是微信开发团队基于浏览器内核完全重构的一个内置解析器,针对小程序专门做了优化,配合自己定义的开发语言标准,提升了小程序的性能。
开发成本的不同:只在微信中运行,所以不用再去顾虑浏览器兼容性,不用担心生产环境中出现不可预料的奇妙BUG
获取系统级权限的不同:系统级权限都可以和微信小程序无缝衔接
应用在生产环境的运行流畅度:长久以来,当HTML5应用面对复杂的业务逻辑或者丰富的页面交互时,它的体验总是不尽人意,需要不断的对项目优化来提升用户体验,但是由于微信小程序运行环境独立。
一般在哪个生命周期钩子函数中进行数据请求,onLoad,onShow中进行数据请求的差异
一般情况在onLoad中进行数据请求,onLoad钩子函数在生命周期过程中最先触发,但在视图层也可以查看到渲染的数据,所以建议在onLoad中进行请求
onLoad钩子函数只触发一次,如果想要多次触发并且进行对应的数据请求,则需要在onShow钩子函数中进行处理,比如通过navigateTo进行路由跳转以后,再返回页面,那么onLoad中的数据请求操作将不会触发,只能在onShow中进行请求
onShow在每次页面打开以后都会触发,如果在该钩子函数中进行数据请求操作,一定需要注意条件判断的处理,以便实现最少请求次数进行性能优化
浏览器的本地存储与小程序的本地存储有哪些差异与区别
浏览器端的本地存储有哪些方式,主要包括:
localStorage 持久化存储,一般大小是5M
sessionStorage会话级存储,一般大小是5M
Cookie存储,一般大小是4K,可能会被用户禁用
小程序的存储方式只有storage,需要注意的事项:
将数据存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容。除非用户主动删除或因存储空间原因被系统清理,否则数据都一直可用。
单个 key 允许存储的最大数据长度为 1MB,所有数据存储上限为 10MB。
性能优化提高
你使用过哪些方法,来提高微信小程序的应用速度?
提高页面加载速度
用户行为预测
减少默认data的大小
组件化方案
控制包的大小
压缩代码,清理无用代码
采用分包策略
启用本地缓存
参考地址:https://blog.csdn.net/wu_xianqiang/article/details/108037685
小程序控制包的大小有哪些方式
压缩代码,清理无用的代码
图片放在cdn
利用iconfont进行图标应用,并且图标操作只留css样式文件,其它文件则删除不使用
如果使用echart图表,可以下载echart源码,利用配置操作发布指定功能的自定义的echart图表文件
采用分包策略
分包预加载
独立分包(版本要求有点高)
小程序对异步请求的优化有哪些方式
onLoad 阶段就可以发起请求,不用等ready
如果业务要求在ready中进行数据请求,需要利用条件判断减少请求次数
请求结果放在缓存中, 下次接着用
请求中可以先展示骨架图
先反馈,再请求。比如说,点赞的按钮,可以先改变按钮的样式,再发起异步请求。
如何利用createIntersectionObserver实现图片懒加载(图片一次性加载数量过大,使用图片懒加载)
原理:
媒体资源懒加载,用view占位,滚动到可视区域内的时候把view替换成媒体组件
https://uniapp.dcloud.net.cn/api/ui/intersection-observer.html#createintersectionobserver
<template>
<view class="container">
<text>{{appear ? '小球出现' : '小球消失'}}</text>
<view class="page-section">
<scroll-view class="scroll-view" scroll-y>
<view class="scroll-area">
<text class="notice">向下滚动让小球出现</text>
<view class="ball"></view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
let observer = null;
export default {
data() {
return {
appear: false
}
},
onReady() {
observer = uni.createIntersectionObserver(this);
// 先用.ball空的盒子进行占位
observer.relativeTo('.scroll-view').observe('.ball', (res) => {
// 当加载到这个.ball盒子的时候,把空盒子替换为图片
if (res.intersectionRatio > 0 && !this.appear) {
this.appear = true;
} else if (!res.intersectionRatio > 0 && this.appear) {
// 没有加载到的时候不显示,使用空盒子占位
this.appear = false;
}
})
},
onUnload() {
if (observer) {
observer.disconnect()
}
}
}
</script>
图片加载慢
可能是因为网速慢,图片是流式加载的,图片会有一点一点加载完成的现象。服务端的网速慢,占用服务器带宽,服务器端可以将动态api服务器与静态资源服务器分开。
还可能是用户与服务器站点距离远,也会导致加载速度慢。可以使用cdn服务器,腾讯云或者阿里云分布式服务器,它会根据用户的距离就近找最近的服务器节点,同时还能够优化网络,与加速器策略一样。
利用防抖与节流进行性能优化
在屏幕滚动与拖拽的时候,经常会用到一些持续触发的事件,而这类事件不可控触发频率非常高,大大影响了性能,而我们想要让其变得可控,就可以用到节流和防抖两种方案。
防抖:指的是事件在高频触发状态时,只收集事件最后一次执行的结果。例如滚动时候产生的scrollTop,只收集停止滚动时候的scrollTop,实现原理是每次滚动触发时,都清除定时器队列,只执行最后一个定义的定时器。
一定时间内方法只执行最后一次。
// 由于作用域的原因,声明定时器let timer必须放在页面构造器Page外边,否则无法清除定时器队列,导致重复触发!
let timer;
Page({
debounce(e){
// 清除之前的定时器
clearTimeout(timer);
// 只有一个定时器,把事件放到定时器中,每次都执行最后一次的事件,其他事件会被清空
timer = setTimeout(() => {
console.log(e.detail.scrollTop)
}, 500);
}
})
节流:指的是降低事件的触发频率,周期性获取事件的执行结果,例如滚动1像素便会触发的滚动事件,我们可以让它周期性每隔一段时间执行一次。实现原理是下一个定时器任务必须等待当前定时器任务执行完才执行。
一定时间内多次执行,只执行第一次。
Page({
data: {
// 定义一个事件锁
lock: true
},
throttling(e){
let timer
// 只有当锁为true的时候才会执行里面的代码,把事件放到里面
if(this.data.lock){
// 每次都先把锁变为false
this.lock = false;
setTimeout(()=>{
// 在定时器内把锁变为true,然后执行事件,这个事件在定时器执行时间内不会被触发
this.lock = true;
console.log(e.detail.scrollTop)
},500)
}
}
})