各位小伙伴们,好久不见,突然想起来微信小程序没有给大家整一份面经,废话不多说,开干!
1.wxml和html有什么区别
①使用标签不同。
②wxml提供了和vue.js中模版语法类似的模版语法,而html没有。
③html在浏览器浏览,而wxml在微信或开发工具中。
④wxml标签必须有结束符</>
2.wxss和css有什么区别
①单位不同:css:px,wxss:rpx。
②wxss不能使用本地图片,需要使用 @import 引入 外联样式文件,地址为相对路径。
③WXSS 和 CSS 的语法在大多数情况下是相似的,但 WXSS 有一些特定的扩展和限制。例如,WXSS 支持一些特定的选择器,如 .class、#id、element、element,element、:pseudo-class、::pseudo-element 等,但它不支持 CSS 的某些高级选择器,如属性选择器 [attribute]
3.小程序的双向绑定和Vue哪里不一样
小程序 直接使用this.data.key = value 是 不能更新到视图当中的。
必须使用 this.setData({ key : value }) 来更新值。
举个栗子:
首先利用bindinput来触发改变input输入框中的值
2,使用data-name来获取改变的数据的内容
3, bindinput触发后在方法中通过e.currentTarget.dataset.name来获取改变后的内容‘
4, 通过this.setData()来改变data-name绑定的参数
4.小程序生命周期有哪些
问到这在头脑里你需要想到有这么三种,这样才是面试官想要得到的答案
①应用的生命周期
②页面的生命周期
③组件的生命周期
应用生命周期
小程序的生命周期函数是在app.js里面调用的,通过App(Object)函数用来注册一个小程序,指定其小程序的生命周期回调
生命周期 | 说明 |
---|---|
onLaunch | 小程序初始化完成时触发,全局只触发一次 |
onShow | 小程序启动,或从后台进入前台显示时触发 |
onHide | 小程序从前台进入后台时触发 |
onError | 小程序发生脚本错误或 API 调用报错时触发 |
onPageNotFound | 小程序要打开的页面不存在时触发 |
onUnhandledRejection() | 小程序有未处理的 Promise 拒绝时触发 |
onThemeChange | 系统切换主题时触发 |
页面生命周期
页面生命周期函数就是当你每进入/切换到一个新的页面的时候,就会调用的生命周期函数,同样通过App(Object)函数用来注册一个页面
生命周期 | 说明 | 作用 |
---|---|---|
onLoad | 生命周期回调—监听页面加载 | 发送请求获取数据 |
onShow | 生命周期回调—监听页面显示 | 请求数据 |
onReady | 生命周期回调—监听页面初次渲染完成 | 获取页面元素(少用) |
onHide | 生命周期回调—监听页面隐藏 | 终止任务,如定时器或者播放音乐 |
onUnload | 生命周期回调—监听页面卸载 | 终止任务 |
组件的生命周期
组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发,通过Component(Object)进行注册组件
生命周期 | 说明 |
---|---|
created | 生命周期回调—监听页面加载 |
attached | 生命周期回调—监听页面显示 |
ready | 生命周期回调—监听页面初次渲染完成 |
moved | 生命周期回调—监听页面隐藏 |
detached | 生命周期回调—监听页面卸载 |
error | 每当组件方法抛出错误时执行 |
组件实例刚刚被创建好时, created 生命周期被触发,此时,组件数据 this.data 就是在 Component 构造器中定义的数据 data , 此时不能调用 setData
在组件完全初始化完毕、进入页面节点树后, attached 生命周期被触发。此时, this.data 已被初始化为组件的当前值。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行
在组件离开页面节点树后, detached 生命周期被触发。退出一个页面时,如果组件还在页面节点树中,则 detached 会被触发
特殊的生命周期
它们并非与组件有很强的关联,但有时组件需要获知,以便组件内部处理,这样的生命周期称为“组件所在页面的生命周期”,在 pageLifetimes 定义段中定义
生命周期 | 说明 |
---|---|
show | 组件所在的页面被展示时执行 |
hide | 组件所在的页面被隐藏时执行 |
Component({ pageLifetimes: { show: function() { // 页面被展示 }, hide: function() { // 页面被隐藏 }, }})
5.说说微信小程序中路由跳转的方式有哪些?区别?
wx.navigateTo(Object)
用于保留当前页面、跳转到应用内的某个页面,使用 wx.navigateBack可以返回到原页面
对于页面不是特别多的小程序,通常推荐使用 wx.navigateTo进行跳转, 以便返回原页面,以提高加载速度。当页面特别多时,则不推荐使用
wx.redirectTo(Object)
重定向,当页面过多时,被保留页面会挤占微信分配给小程序的内存,或是达到微信所限制的 10 层页面栈的情况下,我们应该考虑选择 wx.redirectTo
wx.redirectTo()用于关闭当前页面,跳转到应用内的某个页面
这样的跳转,可以避免跳转前页面占据运行内存,但返回时页面需要重新加载,增加了返回页面的显示时间
wx.switchTab(Object)
跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
wx.navigateBack(Object)
用于关闭当前页面,并返回上一页面或多级页面,开发者可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层则设置对象的delta属性即可
wx.reLaunch(Object)
关闭所有页面,打开到应用内的某个页面,返回的时候跳到首页
总结
- navigateTo 保留当前页面,跳转到应用内的某个页面,使用 wx.navigateBack 可以返回到原页
- redirectTo 关闭当前页面,跳转到应用内的某个页面
- switchTab 跳转到 tabBar 页面,同时关闭其他非tabBar 页面
- navigateBack 返回上一页面
- reLanch 关闭所有页面,打开到应用内的某个页面
关于页面的堆和栈
- avigateTo 新页面入栈
- redirectTo 当前页面出栈,新页面入栈
- navigateBack 页面不断出栈,直到目标返回页,新页面入栈
- switchTab 页面全部出栈,只留下新的 Tab 页面
- reLanch 页面全部出栈,只留下新的页面
6.小程序怎么实现下拉刷新
方案 一 :
通过在 app.json 中, 将 “enablePullDownRefresh”: true, 开启全局下拉刷新。
或者通过在 组件 .json , 将 “enablePullDownRefresh”: true, 单组件下拉刷新。
方案二:
scroll-view : 使用该滚动组件 自定义刷新,通过 bindscrolltoupper 属性, 当滚动到顶部/左边,会触发 scrolltoupper事件,所以我们可以利用这个属性,来实现下拉刷新功能。
7.bindtap 和 catchtap 区别
相同点: 都是点击事件
不同点: bindtap 不会阻止冒泡, catchtap 可以阻止冒泡。
8.小程序有哪些传递数据的方法
- 使用全局变量
在 app.js 中的 this.globalData = { } 中放入要存储的数据。
在 组件.js 中, 头部 引入 const app = getApp(); 获取到全局变量
直接使用 app.globalData.key 来进行赋值和获取值。- 使用 路由
wx.navigateTo 和 wx.redirectTo 时,可以通过在 url 后 拼接 + 变量, 然后在 目标页面 通过在 onLoad 周期中,通过参数来获取传递过来的值。- 使用本地缓存
9.小程序 wx:if 和 hidden 的区别
wx:if : 有更高的切换消耗。
hidden : 有更高的初始渲染消耗。
使用场景:
频繁切换使用 hidden, 运行时条件变化使用 wx: if
10.如何封装小程序请求
封装 wx.request 请求传递需要的参数( url , data , method , success 成功回调 , fail 失败回调 ) , 封装常用方法 POST , GET , DELETE , PUT … 最后导出这些方法
然后新建一个 api.js 文件,导入封装好的方法,然后调取相应的方法,传递数据。
封装wx.request
var app = getApp(); //获取小程序全局唯一app实例var host = '******************'; //接口地址 //POST请求function post(url, data, success,fail) { request(url, postData, "POST", doSuccess, doFail);} //GET请求function get(url, data, success, fail) { request(url, postData, "GET", doSuccess, doFail);} function request(url, data, method, success, fail) { wx.showLoading({ title: "正在加载中...", }) wx.request({ url: host + url, //请求地址 method: method, //请求方法 header: { //请求头 "Content-Type": "application/json;charset=UTF-8" }, data: data, //请求参数 dataType: 'json', //返回数据格式 responseType: 'text', //响应的数据类型 success: function(res) { wx.hideLoading(); //成功执行方法,参数值为res.data,直接将返回的数据传入 success(res.data); }, fail: function() { //失败执行方法 fail(); }, })}module.exports = { postRequest: post, getRequest: get,}
使用封装的wx.request发送请求
var http = require('../../utils/request.js'); //相对路径var params = {//请求参数 id:this.data.userId}http.postRequest("user/delUser", params, function(res) { console.log("修改成功!"); }, function(res) { console.log("修改失败!!!")})
11.小程序运行机制
热启动:假如用户已经打开了某个小程序,在一定时间内再次打开小程序的话,这个时候我们就不再需要重新启动了,这需要把我们的后台打开的小程序切换到前台来使用。
冷启动:用户首次打开小程序或被微信主动销毁再次打开的情况,此时小程序需要重新加载启动
。
12.小程序什么时候会主动销毁?
小程序在进入后台之后,客户端会帮我们在一定时间内维持我们的一个状态,超过五分钟后,会被微信主动销毁.
官方也没有明确说明 什么时候销毁, 在不同机型表现也不一样,
2019年开发时:时间官方文档没有说明,但是经过询问一般指5分钟内
2020年开发时:时间官方文档没有说明,实测安卓没有固定时间,内存足够情况下,有时候一天了还在,有时候几分钟就没了
13.如何提高微信小程序的应用速度的手段有哪些?
- 下载小程序代码包
- 加载小程序代码包
- 初始化小程序首页
优化加载常用手段:
- 代码包的体积压缩可以通过勾选开发者工具中“上传代码时,压缩代码”选项
- 及时清理无用的代码和资源文件
- 减少资源包中的图片等资源的数量和大小(理论上除了小icon,其他图片资源从网络下载),图片资源压缩率有限
- 可以采取分包加载的操作,将用户访问率高的页面放在主包里,将访问率低的页面放入子包里,按需加载
- 当用户点击到子包的目录时,还是有一个代码包下载的过程,这会感觉到明显的卡顿,所以子包也不建议拆的太大,当然我们可以采用子包预加载技术,并不需要等到用户点击到子包页面后在下载子包
优化渲染的常用手段
- 请求可以在页面onLoad就加载,不需要等页面ready后在异步请求数据
- 尽量减少不必要的https请求,可使用getStorageSync() 及 setStorageSync() 方法将数据存储在本地
- 可以在前置页面将一些有用的字段带到当前页,进行首次渲染(列表页的某些数据–> 详情页),没有数据的模块可以进行骨架屏的占位
- 不要过于频繁调用setData,应考虑将多次setData合并成一次setData调用
- 数据通信的性能与数据量正相关,因而如果有一些数据字段不在界面中展示且数据结构比较复杂或包含长字符串,则不应使用setData来设置这些数据
- 与界面渲染无关的数据最好不要设置在data中,可以考虑设置在page对象的其他字段下
- 对于一些独立的模块我们尽可能抽离出来,这是因为自定义组件的更新并不会影响页面上其他元素的更新
登录流程
- 通过 wx.login() 获取到用户的code判断用户是否授权读取用户信息,调用wx.getUserInfo 读取用户数据
- 由于小程序后台授权域名无法授权微信的域名,所以需要自身后端调用微信服务器获取用户信息
- 通过 wx.request() 方法请求业务方服务器,后端把 appid , appsecret 和 code 一起发送到微信服务器。 appid 和 appsecret 都是微信提供的,可以在管理员后台找到
- 微信服务器返回了 openid 及本次登录的会话密钥 session_key
- 后端从数据库中查找 openid ,如果没有查到记录,说明该用户没有注册,如果有记录,则继续往下走
- session_key 是对用户数据进行加密签名的密钥。为了自身应用安全,session_key 不应该在网络上传输
- 然后生成 session并返回给小程序
- 小程序把 session 存到 storage 里面
- 下次请求时,先从 storage 里面读取,然后带给服务端
- 服务端对比 session 对应的记录,然后校验有效期
根据 3rd_session在 session存储中查找合法的 session_key和 openid
14.普通页面与自定义组件的区别
①组件的初始函数是Component()函数,而普通页面是Page()。
②组件中的data放私有变量,properties存放共有变量。
③组件的方法放在methods里面。
④组件的json中的“component":true,表示这是一个组件。
15.微信小程序父子组件之间的通信
1.父组件传给子组件
父组件 这是通过viewText="{{viewText}}"传向子组件:
<MyToast viewText="{{viewText}}" bind:myEvent="OnViewText"></MyToast>
子组件是通过properties来获取:
properties:{ viewText:{ //属性名 type:Number, //类型,必填项 目前接受的类型有:String,Number,Boolean,Object,Arrray,null(表示任意类型) value:'' //属性初始值(可选)如果未制定,会根据类型选择一个。 }}methods:{ //这里是随便一个方法名字 getnumber:function(){ console.log(this.data.viewText); //这样就可以取道父组件传过来的值了 }}
2.子组件传给父组件
子组件的写法
//这里的input是子组件中的某个输入框<input type="number" bindinput="getInputnumber" value="{{codes}}"></input>methods:{ //这里是bindinput的方法名 getInputnumber:function(e){ this.triggerEvent('myEvent',e.detail.value) //这里的myEvent是自己自定义的事件名字,需要父组件中通过他来接受, }}
父组件写法,这里我还引用上边父组件的名字,也就是说子组件在触发这个方法后需要在父组件中手动获取就好了
<MyToast viewText="{{viewText}}" bind:myEvent="OnViewText"></MyToast>//这里的myEvent是子组件传递过来的自定义事件名称,OnViewText这个是父组件中自定义的事件名称methods:{ OnViewText:function(e){ //这立的这个e就是子组件传过来的值 this.setData({ code:e })}}
结束语:
到此就结束了,希望面试有个好结果,大家共同进步,如有错误,请斧正!!