1.小程序中如何进行接口请求?会不会跨域,为什么
微信小程序有自带的api接口,wx.request();
不会跨域,因为微信小程序不是浏览器,没有同源策略的约束;
wx.request({ url: 'https://xxxxxxx.com/api', method: "POST", data: { pageNum: 1, pageSize: 10 }, header: { "content-type": "application/x-www-form-urlencoded" }, success: res => { console.log(res) }})
2.小程序的常用命令有哪些
引用数据 {{}}
逻辑渲染 wx:if wx:elif wx:else hidden
列表渲染 wx:for wx:for-item wx:for-index wx:key,使用 wx:for-item 指定数组当前元素的变量名,使用 wx:for-index 指定数组当前下标的变量名。
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName"></view>
驱动视图 this.setData({})
事件绑定 bind
3.你认为微信小程序的优点是什么,缺点是什么
优点:①容易推广。在微信中,小程序拥有众多入口,且微信用户基数大,这些都有助于推广小程序;②使用便捷。微信下拉即可打开小程序列表,点击即可使用小程序,不需要额外的安装操作等;③体验良好。小程序不会像H5页面一样经常出现卡顿、延时、加载慢、权限不足等问题;④成本更低,从开发成本到运营推广成本,小程序的花费仅为APP的十分之一。
缺点:①单个包大小限制为2M,这导致无法开发大型的应用,采用分包最大是20M;②需要像app一样审核上架,这点相对于H5的发布要麻烦一些;③处处受微信限制。例如不能直接分享到朋友圈,涉及到积分,或者虚拟交易的时候,小程序也是不允许的。
4.微信小程序中的js和浏览器中的js以及node中的js的区别
👉这篇文章有更详细的解释
浏览器中的JS:ES,DOM,BOM
ES: ECMAScript、 DOM : 文档对象模型、 BOM : 浏览器对象模型;
Node 中的JS:ES,NPM,Native
Native就是原生的模块,通过这个模块来使用JavaScript语言本身不具有的一些能力(来自百度:native方法简单的讲,即Java调用非Java代码的接口)。
NPM是包管理系统、NPM是目前最大的开原库生态系统,通过各种NPM扩展包快速的实践一些功能。
小程序中的JS:ES、小程序框架,小程序API
直观的说小程序中没有DOM和BOM对象,也无法对npm包进行管理
5.微信小程序中的数据渲染与浏览器中有什么不同
浏览器中渲染是单线程的;
而在小程序中的运行环境分成渲染层和逻辑层, WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。
6.简述一下微信小程序中通讯模型
小程序的渲染层和逻辑层分别由2个线程管理:
渲染层的界面使用了WebView 进行渲染;
逻辑层采用JsCore线程运行JS脚本。
一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端(Native)做中转。
逻辑层发送网络请求也经由Native转发。
7.谈谈你对微信小程序中生命周期函数的理解
小程序中的生命周期函数,分为 应用生命周期函数 和 页面生命周期函数 ;
应用生命周期函数有:
onLaunch 函数的参数也可以使用 wx.getLaunchOptionsSync
获取;
onShow 也可以使用 wx.onAppShow
绑定监听;
onHide 也可以使用 wx.onAppHide
绑定监听;
App.js是小程序入口文件,所以在App.js中调用应用生命周期函数:
App({ // 小程序初始化完成时,执行此函数,可以做一些初始化的工作 onLaunch: function( options ){} // 小程序显示到屏幕上的时候,执行此函数 onShow: function( options ){} // 小程序被最小化的时候,执行此函数 onHide: function(){}})
还有一个不太常用,但还是挺有作用的应用生命周期函数:onError(String error)
,在小程序发生脚本错误或 API 调用报错时触发。也可以使用 wx.onError
绑定监听。
还有其他不常用的应用生命周期函数,可以参考:官方文档
页面生命周期函数有:
onLoad函数有一个参数:onLoad(Object query)
还有其他比较常用的,如下图红框内容:
8.微信小程序中如何进行事件的定义,传参
小程序中使用bind关键字绑定事件,但小程序中不能在绑定事件的同时为事件处理函数传递参数,可以为组件提供 data-* 自定义属性传参,其中 * 代表的是参数的名字。
<button bindtap="tapTap" data-param="{{"事件传参"}}">事件传参button>
接收传递到的参数:
tapTap(e){ console.log(e.currentTarget.dataset.param) // 打印结果为:事件传参}
9.wxss和css有什么区别
WXSS和CSS类似,不过在CSS的基础上做了一些补充和修改。
- wxss尺寸单位rpx的引入,来提升不同屏幕的适配体验,750rpx = 375px;
- 提供了全局的样式和局部样式
项目根目录中的 app.wxss 会作用于所有小程序页面
局部页面的 .wxss 样式仅对当前页面生效 - wxss仅支持部分css选择器
.class和#id
element
并集选择器 后代选择器
::after ::before等伪类选择器 - 外联样式导入不同,wxss 使用
@import
标识符来导入外联样式。
10.小程序如何进行页面的跳转传参以及接收数据
最常用的两个页面的跳转和传参方式:①wx.navigateTo ②navigator标签
wx.navigateTo({ url: `/pages/details?id=${xxx}`});
<navigator url="/page/navigate/navigate?title=navigate" hover-class="navigator-hover">跳转到新页面navigator>
跳转页接收参数:
onLoad (options) { console.log(options) this.setData({ goodsId:options.id, goodsName:options.name })}
其他方式:
-
wx.switchTab()
用来 跳转至tabBar页面,并关闭其他所有非 tabBar 页面 -
wx.redirectTo()
和wx.navigateTo()
一样,都 跳转至非tabBar页面,但会关闭当前页面 -
wx.reLaunch()
也是 跳转至非tabBar页面,并且会关闭其他所有页面 -
wx.navigateBack()
用来返回上一页面或多级页面,并关闭当前页面。wx.navigateBack({ delta: 2 //返回的页面数,1为返回上一页,如果delta大于现有页面数,则返回到首页。})
11.小程序如何进行本地存储?
小程序提供了读写本地数据缓存的接口,通过 wx.getStorage/wx.getStorageSync
读取本地缓存,通过 wx.setStorage/wx.setStorageSync
写数据到缓存,其中带Sync后缀的接口表示是同步接口
// 同步存储wx.setStorageSync('key', 'value')// 异步存储,并且开启加密存储wx.setStorage({ key: "key", data: "value", encrypt: true, // 若开启加密存储,setStorage 和 getStorage 需要同时声明 encrypt 的值为 true success() { wx.getStorage({ key: "key", encrypt: true, // 若开启加密存储,setStorage 和 getStorage 需要同时声明 encrypt 的值为 true success(res) { console.log(res.data) } }) }})// 同步读取缓存var value = wx.getStorageSync('key')// 异步读取缓存wx.getStorage({ key: 'key', success (res) { console.log(res.data) }})
-
小程序宿主环境会管理不同小程序的数据缓存,不同小程序的本地缓存空间是分开的,每个小程序的缓存空间上限为10MB,如果当前缓存已经达到10MB,再通过wx.setStorage写入缓存会触发fail回调。
-
小程序的本地缓存不仅仅通过小程序这个维度来隔离空间,考虑到同一个设备可以登录不同微信用户,宿主环境还对不同用户的缓存进行了隔离,避免用户间的数据隐私泄露。
-
由于本地缓存是存放在当前设备,用户换设备之后无法从另一个设备读取到当前设备数据,因此用户的关键信息不建议只存在本地缓存,应该把数据放到服务器端进行持久化存储。
12.谈谈你对微信小程序请求封装的理解
在小程序开发过程中,我们可能会进行许多的网络请求,如果每次请求都去写一遍 request 代码:
wx.request({ url: 'xxx', data: { a: '', b: '' }, header: { 'content-type': 'application/json' // 默认值 }, success(res) { console.log(res.data) }, fail(err){ console.log(err) }})
效率低下且不便于维护,所以封装一下 wx.request
接口还是有必要的。
通常以返回 promise 对象的形式进行请求的封装:
const baseUrl = "123456.com"function request(method, url, dataObj) { return new Promise(function(resolve, reject) { let header = { 'content-type': 'application/json', }; wx.request({ url: baseURL + url, method: method, data: dataObj.data, header: dataObj.header||header, success(res) { //请求成功 if (res.code == 0) { resolve(res); } else { //其他异常 reject('运行时错误,请稍后再试'); } }, fail(err) { //请求失败 reject(err) } }) })}
封装之后代码统一管理,方便维护,节省时间,提高了工作效率!
13.小程序如何实现数据驱动视图
微信小程序中使用 setData
函数把变量渲染到视图层
注意:
- 直接修改this.data,而不调用this.setData(),是无法改变当前页面的状态的,会导致数据不一致
- 仅支持可以JSON化的数据
- 单次设置的数据不能超过1024KB,尽量避免一次设置过多的数据
- 不要把data中的任何一项的value设为undefined,否则这一项将不能被设置,可能会有潜在的问题
示例:
Page({ data: { testOne: 1, testTwo: 2 }, onLoad: function() {}, onShow () { this.setData({ test02:8 }) console.log(this.data.testTwo) } },})
14.对小程序中常见的开放能力API有什么了解
-
获取网络状态(2G/3G/4G/5G/WIFI…)
Page({ // 点击“预览文档”的按钮,触发tap回调 tap: function() { wx.getNetworkType({ success: function(res) { // networkType字段的有效值: // wifi/2g/3g/4g/5g/unknown(Android下不常见的网络类型)/none(无网络) if (res.networkType == 'wifi') { // 从网络上下载文档 wx.downloadFile({ url:' https://lark-temp.oss-cn-hangzhou.aliyuncs.com/__temp/464110/docx/bb5d8e7d-97bc-406b-be94-ca2b4724c0e6.docx?OSSAccessKeyId=LTAI4GKnqTWmz2X8mzA1Sjbv&Expires=1644944885&Signature=qUYOtNWZOaopjkEFbcKpvgmn%2B1U%3D', success: function (res) { // 下载成功之后进行预览文档 wx.openDocument({ filePath: res.tempFilePath }) } }) } else { wx.showToast({ title: '当前为非Wifi环境' }) } } }) }})
-
扫码能力
Page({ // 点击“扫码订餐”的按钮,触发tapScan回调 tapScan: function() { // 调用wx.login获取微信登录凭证 wx.scanCode({ success: function(res) { var num = res.result // 获取到的num就是餐桌的编号 } }) }})
-
分享能力(分享到朋友圈或个人聊天等)
Page({ onShareAppMessage(){ // 我们要记录转发的记录 return { // 分享的 title:'网友热议', // 分享的封面, 默认为当前页面的截图 imageUrl:"/assets/icon/index.png", // 点击分享跳转的路径,默认是当前路径,也可以自定义配置,添加额外的跳转参数 path:"/pages/index/index?userId=10&entry=share" }}, // 省略了别的属性 ...})
-
wx.canIUse(string schema)
判断小程序的API、回调、参数、组件等是否在当前版本可用 -
wx.getSystemInfoSync() | wx.getSystemInfo()
获取系统信息 -
wx.getUserProfile(Object object)
获取用户信息。页面产生点击事件(例如 button 上 bindtap 的回调中)后才可调用,每次请求都会弹出授权窗口,用户同意后返回 userInfo。该接口用于替换 wx.getUserInfo
示例代码截取自此篇文章
15.小程序的父子传参和vue中的有什么区别
父传子的不同点是:微信小程序在子组件中接受父组件传 用 propertites 进行接收,而不是 props
properties: { msg:{ // type 要接收的数据的类型 type:String, // value 默认值 value:"" }, },
子传父的不同点是:微信小程序在子组件中使用 triggerEvent
抛出自定义事件名,而不是 this.$emit()
methods: { sendData() { console.log(this.data.msg) this.triggerEvent('eventName', '要传递的参数') } }
16.谈谈你对behavior的理解
behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的 mixins
或 traits
。
每个 behavior 可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。 每个组件可以引用多个 behavior ,behavior 也可以引用其它 behavior 。
组件引用时,在 behaviors 定义段中将它们逐个列出即可。
代码示例:
// my-component.jsvar myBehavior = require('my-behavior')Component({ behaviors: [myBehavior], properties: { myProperty: { type: String } }, data: { myData: 'my-component-data' }, created: function () { console.log('[my-component] created') }, attached: function () { console.log('[my-component] attached') }, ready: function () { console.log('[my-component] ready') }, methods: { myMethod: function () { console.log('[my-component] log by myMethod') }, }})
17.如何优化首次加载小程序的速度
截取自简书原文,学到了
-
包体积优化
-
分包加载(优先采用,大幅降低主包体积)。
-
图片优化(1.使用tinypng压缩图片素材; 2.服务器端支持,可采用webp格式)。
-
组件化开发(易维护)。
-
减少文件个数及冗余数据。
-
-
请求优化
- 关键数据尽早请求(onLoad()阶段请求,次要数据可以通过事件触发再请求);整合请求数据,降低请求次数。
- 采用cdn缓存静态的接口数据(如判断用户登录状态,未登录则请求缓存接口数据),cdn稳定且就近访问速度快(针对加载总时长波动大)。
- 缓存请求的接口数据。
-
首次渲染优化
- 图片懒加载(节省带宽)。
- setData优化(不要一次性设置过多的数据等)。
- DOM渲染优化(减少DOM节点)
18.微信小程序如何实现瀑布流效果?
思路:把屏幕分为左右两个容器,根据容器的高度决定下一个元素应该放在哪个容器内(高度相对较低的容器)。
代码如下:
// 处理数据 initList(list) { this.data.finish = false // 临界值 if (list.length == 0) { this.data.finish = true return } let item = list.shift() wx.getImageInfo({ src: item.coverImgUrl, success: (res) => { if (this.data.leftHeight <= this.data.rightHeight) { // 默认从左往右渲 this.data.leftList.push(item) this.data.leftHeight += res.height / res.width } else { this.data.rightList.push(item) this.data.rightHeight += res.height / res.width } this.setData({ leftList: this.data.leftList, rightList: this.data.rightList, }) }, complete: () => { this.initList(list) } })
来源地址:https://blog.csdn.net/m0_53130738/article/details/128036171