前端学习之路


  • 首页

  • 归档

  • 分类

  • 标签

  • 搜索
close
小朱

小朱

前端学习之路

168 日志
37 分类
37 标签
RSS
GitHub
友情链接
  • 极客学院
  • caniuse
  • codepen
  • JS Bin
  • Babel在线编译
  • Iconfinder图标
  • 在线JSON格式化
  • 智能图像压缩

项目开发流程

发表于 2019-10-29   |   分类于 Project Base

工作流程

如图所示,项目的运行一共涉及6个环节。PM 在与业务方进行需求确认后产出文档,评审通过后通过 Confluence 交付;UX 根据需求文档进行交互涉及,产出交互稿,评审通过后通过 Abstract 交付,查看文件时使用 Sketch 查看;后面 BE 和 UI 并行工作,BE 根据 UX 交互稿开发接口,没有评审,通过 Docker 镜像的形式交付,或者线上的开发环境,或者 FE 自己拉取项目启动,查看 graphql 文档;UI 根据交互稿设计页面,评审通过后通过蓝湖交付,同时也会上传文件到 Abstract;BE 和 UI 都交付后,FE 进行开发,完成开发后部署到测试环境;最后由 QA 进行功能测试,使用 fir.im 发布移动端安装包,使用 Jira 进行 bug 管理 。

BE 和 FE 都使用 VSCode 进行开发,项目托管在 GitHub,使用 GitHub Desktop 维护代码,具体的开发流程参考使用 git 开发流程。

tip:最好从 PM 环节开始,功能模块的名称及对应的英文就已确定,后面的环节都使用统一的名称。最好所有人都参与评审,在每个环节评审前都给参与评审的人留出一些时间,提前仔细看一遍评审的内容,尽量在评审时发现并提出问题。

评审注意点

PM —> UX

  • 成本:人力、时间、紧急程度
  • 项目复杂度
  • 能不能基于现有程序解决
  • 可行的解决方案(从工程师角度出发)
  • 和现有的业务是什么关系
  • 对公司意味着什么

UX —> UI、BE

  • 功能和跳转逻辑
  • 后端数据关联、数据结构、穷尽所有的状态和类型
  • 状态的更新
  • 各个环节提示、报错信息、placeholder
  • 与以后的后台是否有冲突、更改、新增

BE -> FE

  • 接口齐全
  • 参数、返回有清晰描述
  • 接口可使用
  • 有测试数据

UI —> FE

  • 文案 、素材、图片格式是否齐全
  • 是否遵守规范
  • 是否极端情况考虑(字最多/少)
  • 适配
  • 动画的开发成本
  • 是否与 UX 保持一致

开发 —> QA

  • 准备好基础数据,如果需要准备 mock 数据
  • 完成冒烟测试
  • 之前测试的bug和功能是否覆盖

Node-基础

发表于 2019-10-25   |   分类于 Node

__dirname 指向被执行 js 文件的绝对路径
./ 指向执行 node 命令的路径,一个特殊情况是在 require() 中使用 ./ 时,这时的路径就会是含有 require() 的脚本文件的相对路径
path.join 使用特定的分隔符将路径片段连接起来生成规范路径
path.resolve 把一个路径解析为绝对路径,相当于执行 cd,/ 被解析为根目录

  • Loopback — 企业级别的 node 框架

NPM-发布包

发表于 2019-10-16   |   分类于 NPM

准备

注册 npm 账号

发布

npm adduser 如果报了 401 Unauthorized 错误,查看是否设置过镜像,删除 .npmrc 中的 registry 行即可

npm publish .

更新

修改 package.json 中的 version

npm publish .

删除

npm unpublish [name] --force 只有发布72小时之内的包可以删除

使用命令

安装包后如果想要在终端中使用命令,package.json 中需要添加 bin 字段定义命令及对应的执行文件,且该文件的第一行添加 #!/usr/bin/env node。

#! 指明这个脚本文件的解释程序,/usr/bin/env 就是告诉系统可以在 PATH 目录中查找,node 指明用 node 执行脚本文件,所以配置 #!/usr/bin/env node,就是解决了不同的用户 node 路径不同的问题,可以让系统动态的去查找 node 来执行你的脚本文件。

搭建私有仓库

npm install –global verdaccio 全局安装 verdaccio
verdaccio 启动 verdaccio
npm adduser --registry http://localhost:4873 登录用户
npm set ca null 如果不使用 https,设置为 null 即可
npm publish --registry http://localhost:4873 发布包,不能与线上包同名
npm unpublish --registry http://localhost:4873 --force 删除包

不同类型的图片

发表于 2019-09-30   |   分类于 CSS

GIF

GIF(图形交换格式)1987:是位图的一种,但与JPEG或PNG不同,GIF文件最多使用来自256种颜色的色板中的颜色,虽然256种可能听起来像很多蜡笔,但复杂的照片通常有数千种色调。此颜色范围在GIF转换过程中丢失,而这也是彩色照片不使用GIF格式的关键原因。但是256色的限制可以帮助保持较小的文件大小,这对于即使是最慢的互联网速度也是理想的。无损,提供了网络透明度选项,适用于简单的动画、小图标、低像素间变化的图形(即大量的平面颜色,如标志和旗帜)。

  • 优点:动态图,可透明,体积小,可用于后台统计日志统计前端性能
  • 缺点:处理256中颜色,不能半透,处理锯齿效果不好

JPEG

JPEG(联合图像专家组)1992:可以将此格式称为“JPEG”或“JPG”,是一种16位格式,可以通过混合红色、蓝色和绿色光来显示数百万的颜色。这使得JPG非常“相片友好”。这就是为什么当涉及到市场上大多数的数码相机时,它会是一个标准格式的部分原因。JPEG格式还允许您灵活选择压缩图像的程度——从0%(重压缩)到100%(无压缩)。60%-75%的压缩程度会大幅缩减文件大小,同时能使您的图像在大多数屏幕看起来无差别。有损,不能保留透明度,适用于静止图像、摄影、图像具有复杂的颜色和动态。

  • 优点:色彩多
  • 缺点:有损压缩

PNG

PNG(便携式网络图形)1996:就像GIF和JPEG格式之间的结合,PNG-8格式与GIF相似,使用256色板,PNG-24与JPEG相似,允许用数百万种颜色来渲染图像。无损,提供了保留透明度选项,适用于需要透明度的Web图形、颜色重和复杂的照片和图形、需要重新编辑和重新导出的图片。

  • 优点:透明、无损压缩、渐进显示和流式读写、保留图像名称、作者、版权、创作时间,可以把代码压缩到图片里去,参见开源项目 PNGDrive
  • 缺点:色彩支持少 PNG8,PNG24,PNG32,IE6 不支持

SVG

SVG(可缩放向量图形):不是纯位图格式,是一个矢量格式。基于XML的标记,可以在任何文本编辑器中编辑,并通过JavaScript或CSS修改。因为矢量可以缩放到任何大小,同时保持清晰的图像质量,它们是响应设计的理想选择。SVG文件中嵌入位图图形是有可能的,正如在HTML中嵌入JPEG图片,这给了SVG无可挑剔的灵活性和力量。矢量/无损,适合显示在矢量图形应用程序(如Illustrator,Sketch和Inkscape)中制作的徽标,图标,地图,标记,图表和其他图形,视网膜屏幕显示。

  • 优点:矢量图,无损压缩,绘制路径 xml 语言
  • 缺点:浏览器支持的不是很好,主要用于移动端 font-face

大小写敏感问题

发表于 2018-11-06   |   分类于 Git

在项目开发中,如果改变了文件或文件夹名称的大小写,默认情况下 git 是无法检测到的,因为 git 是不区分大小写的,windows 和 mac 系统默认也是不区分大小写的。

方式一

  • git config core.ignorecase false 关闭 git 忽略大小写
  • 修改文件名称 README.md 为 readme.md
  • git mv README.md readme.md 在 git 中对文件重命名,如图1
  • 修改文件夹名称 Folder 为 folder
  • git mv Folder temp && git mv temp folder 在 git 中对文件夹重命名,注意需使用临时名称,否则无法重命名,如图2、3
  • 后面正常提交就可以了

方式二

可以将电脑磁盘单独分出一个大小写敏感的分区作为开发空间,再关闭 git 忽略大小写即可。注意在大小写敏感的分区开发时,如果存在同名大小写不同的文件,有些编辑器如 vscode 可能只会加载一个文件。

最后,可以使用 case-sensitive-paths-webpack-plugin 强制所有模块的整个路径匹配磁盘上的实际路径的。

URL 设计规范

发表于 2018-09-01   |   分类于 URL
  • 字母全部用小写,尽量短
  • 使用 kebab-case(短横线分割),谷歌官方建议,有利于 SEO
  • 使用 / 标识资源层级
  • 在查询字符串或资源字段中使用 camelCase
  • 不应包含任何用户相关的信息,避免复制 url 时绑定错误的个人信息
  • 避免太多参数,目录层次尽量少
  • 总是使用复数名词来命名指向一个集合的 url:/users
  • 在源代码中,将复数转换为具有列表后缀名描述的变量和属性
  • 坚持这样一个概念:始终以集合名起始并以标识符结束,如 /students/123
  • URLs 里面请尽量少用动词
  • 为非资源型请求使用动词,这种情况下,API 并不需要返回任何资源,而是去执行一个操作并返回执行结果,这些不是 CRUD 操作
  • 请求体或响应类型如果是 JSON,那么请遵循 camelCase 规范为 JSON 属性命名来保持一致性
  • 即使资源类似于对象实例或数据库记录的单一概念,也不应该将 table_name 用作资源名称或将 column_name 作为资源属性
  • 只有在您的 URL 上面命名资源时才使用名词,不要尝试解释其功能
  • 对于嵌套资源,请在 URL 中把他们的关系表现出来,如 /schools/2/students/31,表示得到 2 学校的 31 学生的信息

微信服务号开发基础

发表于 2018-08-25   |   分类于 WeChat

微信服务号开发其实就是普通的网站开发,只不过其中可调用微信的 js-sdk 使用基于微信的 api,我们的项目中只是使用了支付、隐藏/显示菜单、自定义分享内容的功能,主要是为了支持小程序不能进行 iOS 支付的问题。由于一部分功能是在小程序中的,就需要小程序与服务号的互相跳转。服务号可通过菜单的定义、长按图片识别二维码跳转到小程序,由于小程序内部只能识别小程序码,不能直接跳转到服务号,只能使用图片+文字引导的方式让用户自己进入服务号。

在线工具

公众平台测试账号
微信公众平台接口调试工具
微信 JS 接口签名校验工具

开发环境

  • 扫码登录公众平台测试账号。
  • 接口配置信息,URL 为后端地址,如“http://lichao-server.example/api/weixin”
  • JS接口安全域名,前端域名,如“lichao.example”
  • 体验接口权限表中,网页服务/网页账号,修改网页授权获取用户基本信息为后端域名,如“lichao-server.example”
  • 后端需要 appID、appsecret、Token 进行微信授权、微信支付等操作
  • 如果是前后端分离的,后端需要设置跨域
  • 如果是前后端分离的,后端需要设置 cookie 在指定域名下的共享

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import * as cors from 'cors';
    ...
    // 跨域设置,origin 为前端地址
    app.use(
    cors({
    origin(origin, cb) {
    cb(undefined, server.whitelist.includes(origin));
    },
    credentials: true,
    }),
    );
    // 共享 cookie 设置,server.domain 为前后端都可使用的域名
    app.use(
    session({
    store: new (connectRedis(session))({ client: redis }),
    name: 'sid',
    resave: true,
    saveUninitialized: true,
    secret: server.sessionSecret,
    cookie: { maxAge: 30 * 24 * 60 * 60 * 1000, domain: server.domain },
    }),
    );
  • 前端需要 appID 执行 wx.config 进行 js-sdk 签名

真机调试

使用手机微信打开网页就是线上运行的效果,但这样不能使用 localhost 或 127.0.0.1 的地址,需要内网穿透工具进行本地端口映射,然后通过穿透的地址访问,可以使用 ngrok,但是有些慢,还是建议团队搭建完善的开发环境。

可使用微信开发者工具或微信web开发者工具进行调试。打开微信web开发者工具可能会报错,一直点确定就打开了。微信web开发者工具可进行移动调试,但需要注意,它在 Network 中显示的请求可能不准确,个人认为是过滤掉了微信内部的请求。以下为授权操作的请求对比。

登录授权

参考微信网页授权文档,工作主要是在后端,提供一个地址供前端访问,其余工作都由后端完成。后端确保 appID、appsecret、Token 值正确,服务号设置确保接口配置信息、JS接口安全域名、授权回调页面域名正确,即可完成登录授权。前后端都需要注意哪些设置的值是带协议的,哪些是不带协议的,如果服务号设置和后端设置的 appID 等值是正确的,可能是由于多带或少带协议名返回 redirect_uri 错误。我们项目中的 API_SERVER_URL 环境变量如果带了协议名,就会返回这个错误。在微信开发者工具中,授权是跳转到一个登录的页面,在真机上是弹框授权。

因为微信网页授权其实是进行的页面跳转,在项目中如果授权后仍然停留在当前页面,但要发生一些行为,如弹框,只能通过授权后的回调地址带参数的形式。建议授权后的回调地址如果需要传参数,使用 hash 的形式传参,这是因为这个页面如果需要使用 js-sdk,在 iOS 上页面路径发生变化可能会导致 wx.config() 执行失败,但 hash 的形式不会有影响。进入页面时在 componentDidMount 中判断 url 是否带有指定的 hash 参数,有则表示是授权后进入的当前页面,执行指定的行为,然后将页面 hash 参数置空。正常情况下授权后进入页面会重新加载整个页面,也就是会执行完整的生命周期方法进入 componentDidMount 中,但实际中发现有些情况并没有进入 componentDidMount 方法,因此在 componentDidMount 方法中添加了 hashchange 的监听,在 componentWillUnmount 中取消监听,如果在 componentDidMount 方法中需要网络请求的,也需要注意在授权返回后是否真正发起了该请求以及请求是走的网络还是缓存,可能需要进行特殊处理,就完整的解决了微信网页授权问题。

微信开发者工具中可通过,清缓存 -> 清除开发者工具cookie 取消授权;iOS 真机可通过微信中,我 -> 设置 -> 通用 -> 存储空间 -> 清理微信缓存,取消授权;anroid 真机可通过在微信中,打开网页 debugx5.qq.com,勾上最下面的四项 Cookie、文件缓存、广告过滤缓存、DNS缓存,点击清除取消授权。

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import queryString from 'query-string';
...
class Page extends React.Component {
public async componentDidMount() {
// 判断是否是后端登录返回的
this.replaceUrl();
window.addEventListener('hashchange', this.replaceUrl);
}
public componentWillUnmount() {
window.removeEventListener('hashchange', this.replaceUrl);
}
public replaceUrl = () => {
if (window) {
const parsedHash = queryString.parse(window.location.hash);
if (parsedHash.show === 'true') {
window.location.hash = '';
// 显示 actionSheet
this.actionSheet.handleShow();
}
}
};
public showActionSheet = async () => {
const callbackUri = `${config.clientUrl}/sharePlan#show=true`;
Router.push(
`${config.serverUrl}/api/weixin/auth?callbackUri=${callbackUri}`,
);
};
public render() {
// ...
}
}

js-sdk 使用

参考微信JS-SDK说明文档文档,前端所有需要使用 JS-SDK 的页面必须先执行 wx.config() 注入配置信息,前端传入页面 url 给后端,后端返回 timestamp、nonceStr、signature,建议 appId 也一起由后端返回,前端就不需要自己配置 appID 了。

从文档中看注入配置信息没有什么难点,在微信开发者工具、android 真机也非常顺利,但 iOS 真机处了问题,一直提示“invalid signature签名错误”,各种排查问题,后来通过复制页面连接,发现在 iOS 真机单页应用在路由切换时页面 url 一直保持不变,都是第一个打开页面的 url,这是单页应用的问题。因此使用了,在项目入口文件,定义一个变量保存页面 url,该变量只被赋值一次,来确保该变量保存的是初次进入页面的 url,然后通过 context 的形式传入到其它页面,在获取 wx.config 的签名参数时,判断如果是 iOS 平台,则传入 context 中的第一个打开页面的 url,否则传入当前页面 url,就解决了签名错误的问题。

还有一个可能遇到的问题,通过服务号进入页面时报签名错误,复制当前网页链接直接进入则签名正确,请检查服务号菜单配置中路径是否正确,可能是路径末尾缺少一个 /。程序猿已在风中凌乱。。。

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// _app.tsx
const ContextType = {
initialUrl: PropTypes.string,
};
let initialUrl;
class MyApp extends App {
public static childContextTypes = ContextType;
public static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps, query: ctx.query, asPath: ctx.asPath };
}
public getChildContext() {
return {
initialUrl,
};
}
...
}
// 使用组件
try {
// 1.获取签名需要的页面 url
let signUrl = `${config.clientUrl}${Router.asPath}`;
// 1.1判断 ios 终端
const userAgent = navigator.userAgent;
const isiOS = !!userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
if (isiOS) {
signUrl = `${config.clientUrl}${this.context.initialUrl}`;
}
// 2.调用后台接口获取签名需要的参数
const signSdkData: SignSdkData = await this.context.client.query({
fetchPolicy: 'network-only',
query: signSdkQuery,
variables: {
uri: signUrl,
},
});
// 3.进行 js-sdk 签名
if (signSdkData && signSdkData.data && signSdkData.data.signSdk) {
const { appId, nonceStr, signature, timestamp } = signSdkData.data.signSdk;
wx.config({
appId,
debug: true,
jsApiList: [
'onMenuShareAppMessage',
'onMenuShareTimeline',
'hideMenuItems',
'showMenuItems',
],
nonceStr,
signature,
timestamp,
});
// 4.签名成功执行回调
wx.ready(() => {
this.props.callback();
});
}
} catch (error) {
console.log(error);
}

生产环境

  • 注册服务号,进行微信认证
  • 开发者工具 -> web开发者工具, 添加开发者账号,才可开发该 appID 的服务号
  • 设置 -> 人员设置,添加运行人员,可登录后台和群发消息
  • 功能 -> 自定义菜单,配置菜单
  • 小程序 -> 小程序管理,添加关联的小程序
  • 小程序 -> 展示场景,在公众号资料中展示小程序
  • 设置 -> 公众号设置 -> 功能设置,JS接口安全域名为前端域名,网页授权域名为后端域名,业务域名暂时没用
  • 开发 -> 基本配置,IP白名单中添加后端 IP,服务器配置未启用
  • 微信商户平台 -> 产品中心 -> 开发配置,设置H5支付的授权目录,注意是目录,以/结尾,如 http://example.com/pages/

小程序数据分析

发表于 2018-08-25   |   分类于 WeChat

由于微信自己的机制,无论是用微信公众平台,还是用第三方的数据分析平台,都有可能存在数据不准确的情况。我们的小程序由于能够统计每天的收入情况,对比发现过微信公众平台和诸葛io都存在购买数据的偏差。

基于微信公众平台

微信公众平台中,也就是小程序管理后台,本身提供了基础的数据分析的功能,无需上报数据也能分析一部分数据。也可通过小程序开发文档中提供的自定义数据上报接口 wx.reportAnalytics 在代码中上报需要的数据,使用前,需要在小程序管理后台自定义分析中新建事件,配置好事件名与字段。使用小程序管理后台很简单,不用做用户标识,因为微信自己是能通过 openId 区分用户的,无需自己处理,也不用上报场景值和用户画像等基本信息。缺点是,小程序管理后台:

  • 不能自定义面板
  • 对自定义分析的查询日期跨度不能超过31天
  • 不能添加自定义的用户属性,不能创建用户分群
  • 不能查看原始数据,更不能下载了
  • 没有渠道分析,当然这个可以自己做

基于诸葛io

为了解决小程序管理后台数据分析存在的问题,我们对比了很多支持小程序的数据分析产品,列表如下,最后选择了诸葛io。

  • 腾讯移动分析
  • 阿拉丁小程序统计平台
  • 神策数据
  • TalkingData
  • 及策
  • 易观方舟
  • GrowingIO
  • 诸葛io

总体来说,诸葛io解决了上述小程序后台存在的所有问题,而且提供了下载原始数据的方式,集成简单,调试也快,后台也可以添加多个用户并授予不同权限。后台创建用户分群、创建面板方式比较简单,不需要工程师去创建,业务人员可以自己创建。缺点就是付费😂,上面也说过了,数据会有些偏差,但是很有可能没办法避免。

基于Google Analytics

小程序中集成 wxapp-google-analytics 后,按照文档进行操作,可上报数据到 Google Analytics,经试验以下功能都可正常使用:

  • 可上报页面访问,支持自定义维度和指标
  • 可上报事件,若要上报自定义维度和指标,需修改 ga.js 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
EventBuilder.prototype.build = function() {
// 去除无效字段字段
hit_delete_if(this, 'ev', 0);
hit_delete_if(this, 'el', '');
// 添加--处理自定义维度和指标
var cd_arr = this.custom_dimensions;
var cm_arr = this.custom_metrics;
var i;
for (i = 0; i < cd_arr.length; i++) {
var cd = cd_arr[i];
this.hit['cd' + cd[0]] = cd[1];
}
for (i = 0; i < cm_arr.length; i++) {
var cm = cm_arr[i];
this.hit['cm' + cm[0]] = cm[1];
}
// 添加--结束
return HitBuilder.prototype.build.apply(this, arguments);
};
  • 渠道分析
  • 跟踪场景值
  • 跟踪二维码参数
  • 可标识用户,清除 storage/_ga_cid 后,将产生一个新用户,这也意味着用户删除小程序后再次进入将作为一个新用户

Google Analytics 中受众群体下的报告反映都很慢,想看到用户数据上报情况很可能第二天才能看到,有时第二天也没看到数据,还需要重新测,很担心线上环境也会出现这种情况。

小程序审核相关

发表于 2018-08-25   |   分类于 WeChat

小程序如何提审

小程序中只要修改了代码,上线就需要审核,如果通过修改 url 的形式来决定是访问测试服务器还是线上服务器,就需要进行2次审核,而且需要后端先上线。解决这个问题,可以前端和后端都维护一个版本号,前端可以使用动态拼接 url 的方式访问后端接口,如 /api1/xxx,/api2/xxx,或者在请求参数里带上版本号,后端收到请求时拿到的版本号,与自己保存的版本号做对比决定是访问测试服务器还是线上服务器。

小程序审核被拒情形

  • 购买在线课程会被指定为虚拟支付
  • 打卡返现会被指定为赌博活动
  • 电子课程含“未解锁”课程,并引导至公众号解锁课程会被指定为内容不符合规则
  • 没有课程的用户如果直接显示暂无课程,会被指定为可用性和完整性不符合规则
  • 微信测试人员账号可能会出现奇怪的问题,可能会没有 unionId,导致使用小程序里面的功能出现问题

注意:提交审核如果被拒了,经过排查发现是微信自己的问题,可在社区中发帖子描述问题,可能会过审。在小程序后台提交审核没有填写描述的地方,但是使用微信开发者工具上传代码时可以添加项目备注,到小程序后台会出现在描述字段,这里的信息审核人员是会看的。

小程序开发遇到问题

发表于 2018-08-25   |   分类于 WeChat

以下记录的为开发过程中遇到的零散问题及解决方案。

登录流程

部分用户没有 unionId

如上面登录逻辑梳理所述,进入小程序时,如果判断当前进行了用户授权,会使用 wx.getUserInfo 获取用户加密信息 encryptedData 和 iv 以及 wx.login 返回的 code 调用后台接口,后台处理会调用微信接口,通常微信接口会返回用户的 unionId,但发现有的用户就没有返回 unionId。在社区搜了一下这个问题,发现可能会存在微信接口没有返回 unionId 的情况,但通过解密 encryptedData 一定能拿到 unionId,因此改变了获取 unionId 的方式就解决了这个问题。

登录加载慢

小程序线上环境,有部分用户会登录加载很慢,但是我自己没有复现过这个现象,也没办法排查问题。后来发现本地使用 ngrok 进行内网穿透 调试时,有时就会出现这个登录加载慢的问题,经过排查发现,前端在进入小程序时,先使用 wx.login 获取 code,然后调用后台 getInfo 接口拿到用户 openId 进行数据上报,同时也调用后台 login 接口进行用户登录,这两个后台接口都调用了 https://api.weixin.qq.com/sns/jscode2session 接口获取 session_key。后台本身是做了通过将 code 值存入数据库来防止重复使用 code 的兼容的,但是可能会存在同时进入后台的这两个请求,还没有完成存入数据库的操作,后台报了 code 被重复使用的错误没有继续向下执行,因此前端一直处于等待状态,导致登录加载卡死在等待中。

iOS 上头像不显示

问题:在【我的】页面,进入时查询用户信息,如果没有用户信息,显示默认头像图片,如果有用户信息,显示指定 url 的用户头像,但在 iOS 上返回用户信息后仍然显示默认图像,image 组件的 src 属性是正确的头像链接。

解决:在 iOS 上 image 组件在 src 变化后不一定能显示更新后的图片,使用两个 image 组件,根据有没有 url 值决定显示默认头像还是用户头像,就没有问题了。

重复进入页面

问题:在网络条件不好时可能存在点击按钮跳转页面,可能会多次跳转同一个页面,也要点击多次返回才能返回到正确的页面。

解决:在跳转前判断要进入的页面是否在路由栈已经存在。示例代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
Page({
...
navigateToPage() {
const pages = getCurrentPages();
if (pages[pages.length - 1].route === 'pages/xxx/xxx') {
return;
}
wx.navigateTo({
url: '/pages/xxx/xxx',
});
},
...
});

网络图片存在缓存

小程序中使用的网络图片,如果 url 没有发生变化,但后台更新了图片,使用小程序时可能会存在图片没有更新过来,把小程序从记录中删除了再打开,就可以了。也可以在使用图片的 url 后面添加查询参数 url + '?' + Dare.parse(new Date()) 的方式不让小程序缓存图片。web-view 中打卡的网页链接也可以这么处理。

一个值得思考的 bug

问题描述:A 页面 -> B 页面 -> C 页面,在 C 页面中,进行背景音频播放,并添加了背景音频播放的监听,onPlay、onPause、onTimeUpdate、onEnded、onStop,这些监听中主要是更新当前页面的 data 值,来控制页面中的显示,如显示播放/暂停按钮,显示当前播放进度等,并更新全局的当前播放音频的信息,在从 C 页面返回到 B 页面及 A 页面时,会显示一个悬浮播放的控件,显示正在播放的背景音频的信息及播放进度。问题是在从 C 页面返回后,如果是从背景音频点击的暂停,悬浮播放控件中显示的当前播放进度会显示从 C 页面返回时的进度,而不是当前播放进度。

分析原因:经过大概1小时的 bug 追踪,发现问题的原因是背景音频播放的监听是在 C 页面内的,在 onPause 监听中,更新全局播放音频信息的代码是如下代码中的第一段,但从 C 页面返回后,C 页面已经销毁了,这时再获取 this.data.tipRecord 是销毁页面前的数据(刚开始这么写的时候我以为会报错),也就是从 C 返回时的数据。将代码修改为第二段,主要是更新全局提示记录的处理是基于全局 store 中的数据,而不是当前页面的 data,该问题就解决了。

在 C 页面中的音频播放监听方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 第一段,有问题的
this.backgroundAudioManager.onPause(() => {
// 全局提示记录处理,更新 store 中的全局信息
this.setTipRecord({
...this.data.tipRecord,
show: true,
paused: true,
});
});
// 第二段,修正后的
this.backgroundAudioManager.onPause(() => {
// 获取全局 store 中的音频播放信息
const storeData = this.store.getState();
// 全局提示记录处理,更新 store 中的全局信息
this.setTipRecord({
...storeData.tipRecord,
show: true,
paused: true,
});
});

微信用户可能没有头像

在开发打卡生成图片的功能时,很多都需要使用用户的头像,注意会存在没有头像的微信用户,需要处理该种情况。

1…789…17
© 2021 小朱
由 Hexo 强力驱动
主题 - NexT.Pisces