一、小程序的优势和劣势有哪些?
优势:
入口众多。在微信中,小程序拥有众多入口,例如附近的小程序、小程序码、分享、发现-小程序等五十多个的入口。这些入口有助于企业更好的获取流量,从而进行转化、变现。
使用便捷。用户在使用小程序时,只需要轻轻点一下就可以使用,更加符合用户对使用方便、快捷的需求,所以小程序的用户数量不断增加。
体验良好,有接近原生app的体验。在微信生态里,小程序在功能和体验上是可以秒杀掉 H5 页面的,H5 页面经常出现卡顿、延时、加载慢、权限不足等原因,而这些问题在小程序里都不会出现。
微信助力,容易推广。
成本更低,从开发成本到运营推广成本,小程序的花费仅为APP的十分之一,无论是对创业者还是传统商家来说都是一大优势。
劣势:
大小限制为2M,这导致无法开发大型的应用。
不能直接分享到朋友圈。
需要像app一样审核上架,这点相对于H5的发布要麻烦一些
微信对小程序的开发也有限制
二、 小程序中的生命周期函数有哪些?(需要把app,page和component三个构造器的声明周期函数写出来
App中的:
onLaunch 小程序初始化完成时触发,全局只触发一次
onShow 小程序启动,或从后台进入前台显示时触发
onHide 小程序从前台进入后台时触发
onError 小程序发生脚本错误或 API 调用报错时触发
onPageNotFound 小程序要打开的页面不存在时触发
onUnhandledRejection 小程序有未处理的 Promise 拒绝时触发
onThemeChange 系统切换主题时触发
页面中的:
onLoad 监听页面加载 发送请求获取数据
onShow 监听页面显示 请求数据
onReady 监听页面初次渲染完成 获取页面元素
onHide 监听页面隐藏 终止任务
onUnload 监听页面卸载 终止任务
组件中的:
created 监听页面加载
attached 监听页面显示
ready 监听页面初次渲染完成
moved 监听页面隐藏
detached 监听页面卸载
error 每当组件方法抛出错误时执行
三、小程序中如何修改data上的数据?
通过this.setData()
四、提高微信小程序速度的方法
用户行为预测
组件化方案
精简代码,降低WXML结构和JS代码的复杂性;
合理使用setData调用,减少setData次数和数据量
必要时使用分包优化
五、 简述一下小程序中常见的界面跳转的方式,以及区别?
wx.navigateTo
wx.navigateTo({
url: 'test?id=1',
})
保留当前页面,只能打开非 tabBar 页面。
wx.redirectTo
wx.redirectTo({
url: 'test?id=1'
})
关闭卸载当前页面,只能打开非 tabBar 页面。
wx.switchTab
wx.switchTab({
url: '/index'
})
关闭所有非tabbar页面, 只能打开 tabBar 页面。
wx.reLaunch
wx.reLaunch({
url: 'test?id=1'
})
关闭卸载所有页面,可以打开任意页面。
wx.navigateBack
wx.navigateBack({
delta: 2 //返回的页面数,如果 delta 大于现有页面数,则返回到首页。
})
返回前面的页面,可以指定返回多少页,如果用过redirectTo,那么被关闭的页面将返回不去
六、小程序中如何进行本地存储?
存储数据
wx.setStorage : 异步
wx.setStorageSync : 同步
获取数据
wx.getStorage: 异步
wx.getStorageSycn: 同步
七、 小程序中如何进行组件间传参?
父传子
父组件在引用子组件的时候通过设置属性的方式给子组件传值
//在父页面中:
<son msg='hello'></son>
<son></son>
//子组件:
//子组件接收:
properties:{
msg:{
type:[String,Number],
value:’hello world’,
}
}
//vue中子组件用props接收传递的数据
<view>{{msg}}</view>
子传父
//父组件:在组件中绑定一个自定义事件
<son bind:fromson='fromson'></son>
//父组件接收子组件参数:
fromson(res){
console.log(res.detail)
this.setData({
'fromson':res.detail
})
}
//子组件:
<button bindtap='tofather'>子传父</button>
//子组件中触发:子组件中通过triggerEvent触发事件
methods:{
tofather(){
this.triggerEvent(‘fromson’,’111’)
}
}
//vue中子组件通过$emit触发事件
八、 小程序中如何进行接口请求?会不会跨域,为什么?
wx.request
不会跨域
因为不是浏览器,没有同源策略
九、 怎么封装小程序的数据请求?
目的
为了给所有的接口请求添加统一的配置,避免每次请求的时候指定配置
可以添加统一的请求拦截器和响应拦截器,在调用接口的时候做一些通用的处理
如何封装
创建一个request的JS模块
在这个模块里封装wx.request请求,通过Promise解决异步问题
在发送请求之前可以添加统一的请求头
在响应数据之前可以进行统一的逻辑处理
function request(options) {
// 请求拦截器
// ...
// 加一些统一的参数,或者配置
if (!options.url.startsWith("https://") &&!options.url.startsWith("http://")) {
options.url = "https://showme2.myhope365.com" + options.url
}
// 默认的请求头
let header = {
"cookie": wx.getStorageSync("cookie") || "",
"content-type": "application/x-www-form-urlencoded",
};
if (options.header) {
header = {
...header,
...options.header
}
}
return new Promise((reslove, reject) => {
// 调用接口
wx.request({
// 默认的配置
// 加载传入的配置
...options,
header,
success(res) {
// 响应拦截器,所有接口获取数据之前,都会先执行这里
// 1. 统一的错误处理
if (res.statusCode != 200) {
wx.showToast({
title: '服务器异常,请联系管理员',
})
}
reslove(res)
},
fail(err) {
reject(err)
}
})
})
}
//封装get请求
export function get(url, options = {}) {
return request({
url,
...options
})
}
//封装post请求
export function post(url, data, options = {}) {
return request({
url,
data,
method: "POST",
...options
})
}
十、 怎么解决微信小程序的异步请求问题?
使用promise封装异步请求,统一化管理
直接在异步请求的回调函数中调用执行函数
多个异步请求可以使用$nextTick()来判断是否执行完毕
十一、 微信小程序常见的开放能力API有哪些
wx.request http请求
wx.getNetworkType 获取网络状态
wx.downloadFile 从网络上下载pdf文档
wx.openDocument 下载成功之后进行预览文档
wx.scanCode 扫码能力
wx.getUserInfo 用户头像,昵称
十二、谈谈对Behaviors的了解
behaviors 是小程序中,用于实现组件间代码共享的特性,类似于 Vue.js 中的 “mixins”。
每个 behavior 可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中。每个组件可以引用多个 behavior,behavior 也可以引用其它 behavior。
调用 Behavior(Object object) 方法即可创建一个共享的 behavior 实例对象,供所有的组件使用:
//调用Behavior()方法,创建实例
// 并使用exports导出
module.exports = Behavior({
// 属性节点
properties:{},
// 私有数据节点
data:{ usename:'zs'},
// 事件处理函数和自定义方法
methods:{},
// 其他节点
})
在组件中,使用 require() 方法导入需要的 behavior,挂载后即可访问 behavior 中的数据或方法,示例代码如下:
// 引入Behavior实例对象
const myBhavior = require("../../behaviors/behavior")
Component({
// 将导入的myBhavior挂载到behaviors节点上
behaviors:[myBhavior],
})
十二、小程序中界面跳转如何传递参数?如何获取这些参数
路由跳转传参可以通过?的方式拼接参数。跳转到指定界面之后,可以在该页面的onLoad方法中的options参数(本身是个对象)拿到路由跳转的参数。
十三、瀑布流的实现
将数组拆分成左右两个数组
记录左右数组的高度,遍历总数组,将新的元素放在高度比较小的数组里
//wxml文件
<template name="postList">
<view class="box" bindtap="toChat" data-postid="{{item.postsId}}">
<view class="title">
{{item.title}}
</view>
<view class="imgBox">
<image src="{{item.coverImgUrl}}" mode="widthFix"></image>
</view>
</view>
</template>
<view class="bigBox">
<view class="leftBox">
<template is="postList" data="{{item}}" wx:for="{{leftList}}" wx:key="postsId"> </template>
</view>
<view class="leftBox">
<template is="postList" data="{{item}}" wx:for="{{rightList}}" wx:key="postsId"></template>
</view>
</view>
<view class="load">
<van-loading type="spinner" wx:if="{{isLoading}}" />
</view>
<view wx:if="{{isEnd}}" class="tip">没有更多了...</view>
<view class="back" hidden="{{backShow}}" bindtap="backTap" >
<van-icon name="back-top" />
</view>
//js文件
import { getlist } from "../../api/chat"
// pages/chat/chat.js
Page({
/**
* 页面的初始数据
*/
data: {
list:[],
leftList:[],
rightList:[],
leftHeight:0,
rightHeight:0,
// 整个数据处理完成
finish:false,
pageNum:1,
pageSize:10,
total:0,
isEnd:false,
isLoading:true,
// 返回顶部
backShow:true,
},
// 请求的函数封装
getPost(){
getlist(this.data.pageNum,this.data.pageSize).then(res=>{
if(res.data.code == 0){
wx.stopPullDownRefresh();
this.initList(res.data.rows);
this.data.total = res.data.total;
}
})
},
// 处理数据的封装
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,
isLoading:false
})
},
complete:()=>{
this.initList(list);
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.setData({
isLoading:true
})
// 处理数据
this.getPost();
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
this.setData({
isEnd:false
})
// 下拉刷新
if(this.data.finish){
this.data.pageNum = 1
this.setData({
leftList:[],
rightList:[],
leftHeight:0,
rightHeight:0
})
this.getPost();
}else{
return
}
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
this.setData({
isLoading:true,
})
// 触底了
if(this.data.finish){
if(this.data.pageNum * this.data.pageSize >= this.data.total){
this.setData({
isEnd:true,
isLoading:false,
})
}else{
this.data.pageNum ++;
this.getPost()
}
}
},
})
十四、对WebSocket的理解
由于http只能是单向发起的,只能由客户端主动发起,服务端被动响应。服务端无法主动向客户端发送消息,如果想实现类似于聊天室这种即时通讯的功能,就需要使用消息轮询。轮询的效率低,比较消耗资源。
WebSocket最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
而WebSocket协议具有以下特点:(可以更好的实现即时通讯)
1、 webSocket是一种在单个TCP连接上进行全双工通信的协议
2、websocket建立连接时,数据是通过http传输的,建立连接后就不需要http协议了。
3、websocket建立连接后就是全双工模式,也是基于tcp协议。
4、建立连接之后,不必在客户端发送request之后服务器才能返回信息到浏览器,这时候服务器有主动权,允许可以随时发消息给客户端
5、发送的信息中不必带有head部分信息了,相对于http来说,降低了服务器的压力,极大的减少了不必要的网络流量与延迟。
6、没有同源限制,客户端可以与任意服务器通信
7、协议标识符是ws(如果加密,则为wss),服务器网址就是 URL