成长记录#001|2025-09至2025-10
原始记录:
2025-09-22:
- 尝试实现数据超过指定长度自动清除并缓存的逻辑。
- 尝试解决了x轴不删除的问题,这部分仍需要后续加强理解。
2025-09-23:
- 尝试用
npm构建,使用vant组件添加了一个DropdownMenu。 - 通过源码暴露的样式表改变了按钮样式的固定高度。仍需要解决
border无法覆盖矩形按钮的问题。
2025-09-24:
- 通过
filter里关闭--dropdown-menu-background-color属性,发现background与border的渲染冲突。 - 通过
wxss里设置--dropdown-menu-background-color: transparent;解决昨天的border在启用radius时圆角无法渲染的问题。 - 替换启动增氧的
button为switch并自定义颜色。
2025-09-25:
- 确定了通过标志位实现历史数据-实时数据切换的实现逻辑。
- 尝试在
onLoad里加入缓存读取功能,并将读取到的keypush到selectorOptions数组内,但失败了,读取到为undefined的值。并且加入标志位后,阻塞了原有数据显示和刷新逻辑的执行。 - 原因:
log的时间不对,在const声明变量之前就log当然是无效的。
下面列出逻辑方便回顾:
- 如果用户选中「实时状态」→
flag = true,定时器里会不断触发渲染。 - 如果用户选中历史
key→ 设置flag = false,定时器只写缓存、不更新图表,历史数据通过独立的渲染函数一次性画出来。
2025-09-26:
- 实现了页面加载时读取缓存中的key、自动排序、并通过
DropdownMenu预览的功能!
下面列出一些要点:
-
...是JS里的扩展运算符,简单理解就是把数组里的每一项单独“展开”。在JS里通常用它来合并两个数组。例如
let arr1 = [1, 2, 3];使用let arr3 = [...arr1];,得到的新数组将是[1, 2, 3]。需要注意,
[...arr1, arr2]与[...arr1, ...arr2]的区别。前者将形成一个嵌套数组,后者还是一个一维数组。 -
map是数组的方法,全名是Array.prototype.map。它的作用是:对数组里的每个元素执行一次函数,然后返回一个由结果组成的新数组。1
2
3
4
5
6// 这是一个例子
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(x => x * 2);
console.log(doubled); // [2, 4, 6, 8]
console.log(numbers); // [1, 2, 3, 4] (原数组没变) -
箭头函数
=>。它是写函数的一种简化写法。可理解为“参数 => 返回值”。1
2
3
4
5
6
7
8
9// 只有一个参数,可以省略括号,以及return
const square = x => x * x;
console.log(square(4)); // 16
const double = n => n * 2;
console.log(double(7)); // 14
// 把每个日期字符串 k,加工成一个带 text、value、icon 字段的对象数组
const opts = dateKeys.map((k, idx) => ({text: k, value: baseLength + idx, icon: ""}))
2025-09-27:
-
通过:
1
2
3
4
5/* 覆盖掉遮罩层颜色 */
/* !important 是 CSS 里的一个“加权符”,意思是 这条规则的优先级最高 */
.van-overlay {
background-color: transparent ;
}在保留
overlay功能的同时,去除了遮罩的颜色。下拉菜单的背景变为透明的。
2025-09-28:
-
通过
display: block;将元素撑开,解决了border和border-radius无法设置的问题。 -
通过
filter里找到的暴露变量--popup-background-color,将其设置为transparent,干掉了下拉菜单的白色背景。 -
通过将
.van-dropdown-item__option的overflow属性设置为auto,解决了border-radius与border同时存在时,border缺角的问题。补充说明:
overflow是一个 CSS 盒模型的属性,它决定了 当元素的内容超出它的盒子(content box + padding box + border box定义的边界)时,浏览器该怎么办。默认是visible,不作裁剪,所以会露出来,看起来缺角。**参考文献:**https://stackoverflow.com/questions/8582176/should-border-radius-clip-the-content
-
bug:在真机测试时,出现了很多样式无法应用的问题。重新构建后在模拟器上出现了很多报错且部分交互失效。
2025-09-29:
-
通过在页面
js内写入1
import '../../miniprogram_npm/@vant/weapp/mixins/transition';
并重新构建
npm,解决了页面交互失效的问题。 -
bug:真机测试时,样式无法生效的问题依然存在,且vant未提供对应的css变量,这个需要更深入的研究。
2025-10-06:
前几天旅游去了,故没有更新。
- 通过使用
Vant Weapp提供的样式覆盖办法,在wxml内加入custom-class修饰,在真机上实现组件部分样式自定义。 - 通过在
app.wxss内添加关于.van-dropdown-item__option的全局样式,能够为option添加圆角等属性,但真机调试时,单边border的圆角无法绘制,模拟器正常。 - 通过拉取
--popup-background-color和--overlay-background-color变量,在真机上实现对下拉菜单和遮罩背景色的设置。
2025-10-07:
-
汇总真机上的问题:
- 下拉菜单的出现动画消失,收起动画能保持。
- 单边
border的圆角无法绘制,只绘制直线,直接写border可以绘制完整圆角的边框。 dropdown-menu的伪元素(小箭头)看起来在真机上失效了,不显示。- 由于伪元素在真机上不显示,导致图标丢失等系列问题。
-
删除下面代码
1
2
3
4
5
6
7
8
9
10
11
12"renderer": "skyline",
"rendererOptions": {
"skyline": {
"defaultDisplayBlock": true,
"defaultContentBox": true,
"tagNameStyleIsolation": "legacy",
"disableABTest": true,
"sdkVersionBegin": "3.0.0",
"sdkVersionEnd": "15.255.255"
}
},
"componentFramework": "glass-easel",将渲染模式调整为
WebView,解决了上面的所有问题。 -
新
bug:在真机上,canvas图表会穿透下拉菜单显示。且下拉菜单为fixed,导致无法被拖动。
2025-10-08:
- 通过删掉
DropdownItem的overflow属性,解决了下拉菜单无法滚动的问题。 - 通过直接限制
popup的高度,使界面更美观。 - 压缩图片素材分辨率,减小包体大小
- 未修复昨天的新问题。
2025-10-09:
-
通过删除
WXML中的force-use-old-canvas="true"语句,图表在真机上层级过高的问题得到解决。但导致在模拟器上无法随着页面滚动。该问题由微信小程序对
canvas图表的不兼容导致。解决方法为,在需要真机测试时,删除该语句,模拟器调试时,还原该语句。**参考文献:**https://github.com/ecomfe/echarts-for-weixin/issues/940
-
遗留
bug:在下拉菜单展开时滚动页面,由于position为fixed,会导致页面滚动而下拉菜单不滚动。
2025-10-10:
-
通过在页首加入下面代码,实现页面
overflow属性控制:1
<page-meta page-style="{{ enableScroll ? '' : 'overflow:hidden;' }}" />
结合下面的两段代码,绑定下拉菜单开关事件与
scroll-y开关变量:1
2
3<van-dropdown-item custom-class="my-dropdown-item" value="{{initialValue}}" options="{{selectorOption}}" bind:open="openDropdown" bind:close="closeDropdown" />
<scroll-view scroll-y="{{enableScroll}}" class="body">配合绑定的
js事件:1
2
3
4
5
6
7
8
9openDropdown() {
this.setData({enableScroll: false });
console.log("set enableScroll false");
},
closeDropdown() {
this.setData({enableScroll: true });
console.log("set enableScroll true");
},三者组合拳,通过统一的变量
enableScroll控制。实现禁止页面滚动的功能。解决了前面的遗留bug。 -
bug:页面高度不好设置,设置过高(例如100vh),导致滚动到最下面时候navBar跟着跑。
2025-10-11:
-
通过下面的函数,计算
navigation-bar高度,并适当补偿,实现针对不同机型自动配置body高度,有较小偏差,但暂时能接受。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/* 了解计算方法就好了,方法要用可以再查 */
getBodyHeight() {
const statusBarHeight = wx.getWindowInfo().statusBarHeight;
const menuButtonInfo = wx.getMenuButtonBoundingClientRect();
const navBarHeight = menuButtonInfo.height + (menuButtonInfo.top - statusBarHeight) * 2;
const windowHeight = wx.getWindowInfo().windowHeight;
const bodyHeight = windowHeight - statusBarHeight - navBarHeight - 3;
this.setData({bodyHeight});
},
/*
导航栏高度 = 胶囊高度 + 胶囊的上下边距
胶囊的上下边距相等,所以乘2
通过wx.getMenuButtonBoundingClientRect()可以获取胶囊的宽高等信息
*/ -
通过修改
navigation-bar.wxss内.weui-navigation-bar__left的align-item为center,从而使导航栏返回键对齐。 -
通过j将
this.isRealtimeRender替换为this.data.isRealtimeRender,解决了变量未定义的问题。下面是一些解释。
this指的是整个页面的实例对象。它不仅包含data,还包含自定义函数和属性、微信系统注入的生命周期方法。换句话说,data是this的子对象。所以引用data里的内容,必然是this.data.XXX这样的形式。1
2
3
4
5
6
7
8this = {
data: { ... },
onLoad() {},
onReady() {},
chart: xxx,
timer: xxx,
...
}如果引用了自定义函数,例如下面这样:
1
2
3
4
5
6
7
8Page({
getBodyHeight() {
},
onLoad(options) {
this.getBodyHeight();
}
})因为自定义函数也是
this的子对象,所以如果不通过this引用,反而直接写,就会有未定义的报错。
2025-10-12:
-
下拉菜单交互函数设计:
- 根据返回的
value进行判断。假设选择了显示实时数据,isRealtimeRender设置为true。 - 假如选择了其他选项,会把
isRealtimeRender设置为false。同时,根据key读取缓存,然后清空图表并重新渲染数据。 - 选择其他选项后,再启用实时数据时,会先从缓存中数据,并渲染,然后
isRealtimeRender设置为true,继续刷新数据。 - 今天已经实现了1和2两条,目前的逻辑是:选择其他选项后,会把当前所有暂存数据扔进当天的缓存。如果想修改得到第三条的效果,只需要额外添加一个数组用于存放临时数据。等页面关闭后统一存进缓存。
- 根据返回的
-
知识点:
-
关于箭头函数
=>。在2025-09-26已经有初步的了解。今天回顾一下。1
2
3
4
5/* 参数 => 返回值 。下面这句参数为item,引用item中的value,判断是否与e.detail相等 */
item => item.value === e.detail
/* 变量是数组item,返回值是它的第一个参数,再用map组合为新数组 */
const times = this.data.dataList.map(item => item[0]); -
关于
find函数。Array.prototype.find()是 ES6 引入的新方法,用来在数组中查找第一个符合条件的元素(找到后直接返回,不再继续找)。1
array.find( callbackFn )
callbackFn会被自动调用多次——每次传入数组中的一个元素。
如果你在callbackFn里返回true,find()就停下来并返回当前元素;
如果全都返回false,最后返回undefined。聪明如你应该知道,回调函数应该是返回一个布尔值。1
2/*箭头函数 + find函数,用来筛选指定value*/
array.find( item => item.value === e.detail ) -
箭头函数?
this?作用域!看下面两段代码,假设它们都要用
Page中的chart绘制图表:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17wx.getStorage({
key: selectedKey,
success:(res) => {
this.chart.setOption({
xAxis: { data: times },
series: [{ data: value }]
})
}
wx.getStorage({
key: selectedKey,
success(res) {
this.chart.setOption({
xAxis: { data: times },
series: [{ data: value }]
})
}聪明如你一定看出来了,两段代码实现了相同的功能。第一段代码用了箭头函数,第二段没用。但是第一段会报
this.chart未定义的错误。为什么呢?因为箭头函数没有自己的
this,它会继承外层作用域的this。这段代码想用Page实例中的this。不过,如果一个函数不需要用全局的
this,也不必用箭头函数,但是要注意,普通函数的this必须“靠调用者指定”,没人调用,可能指向未定义。
-
2025-10-13:
- 修改逻辑:
- 在每次
push数据时,不再定期判断数组长度和缓存数据,改为在OnUnload中统一缓存。 - 移除在读取缓存、切换显示历史数据时,即时缓存数据的功能。改为在
OnUnload中统一缓存。 - 上述功能已实现。
- 在每次
- 关闭页面后,数据是否继续存储,还有待考虑。目前关闭页面后会继续存储数据。
- 暂时无法实现
y轴数据自动吸附,或者formatter格式化数据并通过label显示,以方便用户查看y轴数据的功能。原因是图表初始化函数写在Page外,难以引用挂在页面内的数据。再评估之后,决定研究formatter的用法,以及直接让它调用Page上的数据的办法。 bug:在当天回看当天已缓存的内容,会出现内容覆盖或者丢失的情况。
2025-10-14:
-
查文档发现,
bug是由于微信缓存功能的自身特性导致。在同一个key下缓存新数据,会覆盖旧数据。结合之前写的逻辑,每超过20个数据,缓存前10个数据,导致回看历史数据时,每天只有10个数组在缓存中。这进一步验证了这点。
解法为,在缓存前先读原来缓存的旧数据,再与新数据进行拼接,然后塞进同一个
key,成功修复了昨天的bug。实现方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15const removed = this.data.dataList.splice(0,this.data.dataList.length);
wx.getStorage({
key: currentDate,
success(res) {
const oldData = res.data || [];
const newData = [...oldData, ...removed];
wx.setStorageSync(currentDate , newData);
console.log("已有数据,追加新的数据:", newData);
},
fail() {
wx.setStorageSync(currentDate , removed);
console.log("没有数据,存入新的数据:", removed);
}
}) -
重新阅读官方文档。通过配置
formatter实现了格式化数据,并通过label显示,以方便用户查看y轴数据。参考文档:Documentation - Apache ECharts。重点在于
params.seriesData及其内容。 -
bug:点击某个点,显示对应的label后,概率性出现label显示范围异常宽大的问题。刷新页面后,坐标指示器不消失,概率性出现返回的y轴值为undefined的情况。
2025-10-15:
-
实现了对昨天未定义
bug的稳定复现。复现方法为:在数据较多的图表,选择第
n个(顺序均为从左到右)的数据。此时可正常显示。对应的params.seriesData[0].data都有值。然后通过下拉菜单切换到数据量小于n的图表,此时会出现undefined现象。目前怀疑是加载问题导致。进一步观察,容易发现,当页面出现数据后,首次点击图表,坐标指示器会直接出现在该轴对应位置。但在图表刷新后,即使点击图表空白处,令坐标指示器消失,再点击某个位置重新,启用坐标指示器后,指示器是通过动画,从消失的位置移动到目标点。说明指示器并没有被完全关闭。
label异常宽大的问题暂时无法复现。 -
每次加载时重置图表,或许是一个好的选择。
echartsInstance初始化时创建的实例,或许是一个突破口。但是今天事情比较多,太累了,先休息吧,放松一下。
2025-10-16:
-
【修复】 修复了14号
undefined的bug。测试结果表明,bug已经无法再被复现。修复方法:单独写一个函数用于重绘图表。在
setOption之前执行。具体流程如下:
1
2
3
4
5
6
7
8redrawEchart() {
var option = {
/* 此处复制原配置项 */
}
this.chart.clear();
this.chart.setOption(option, true);
console.log("成功重启图表");
}再次多次测试表明,
label异常宽大的问题依然存在。目前没有稳定的复现方法。不论是否触发bug,它们的params没有明显异常。可能的测试方法:吧
function移除,然后通过固定字串测试。然后通过固定字串+value测试。 -
更换了较新版本的
echarts.js。 -
【BUG】:在通过下拉菜单刷新图表后,图表会缩小。
-
【BUG】:实时页面的数据,会连同时间一起显示在“值”的位置。
2025-10-17:
- 目前找到了一种可能的复现
label问题的方法。进入任意一个下拉菜单选项,图表绘制后,任意点击一个点,有较大的概率复现该问题。 - 【修复】 修复了
bug2。造成原因为:实时刷新时传入了dataList数组,而不是数组对应的value。应该将其从数组中提取出来,然后传入。 - 尝试给
label添加borderWidth,但并没有奏效。
2025-10-18:
- 发现删除
formatter函数之后,不再出现bug。此时axisPointer.label仅输出x轴对应值。 - 发现配置
axisPointer.label.width后,背景区域宽度为固定值,表明未配置时,该宽度与文字长度相关。因此bug可能是首次点击时宽度计算错误导致的。 - 【修复】 通过删除
WXML内的force-use-old-canvas="true"语句,使用新渲染模式,修复了label宽度 异常的问题。 - 【更新】 修改了图表部分样式。包括图表位置。
- 【更新】 修改随机数生成逻辑,限定在
[7,7.2]范围内。 - 【更新】 绑定图表数据与传感器卡片数据。下拉菜单切换选项浏览历史数据时,实时数据依然继续更新。
- 【更新】 在开发者工具添加了注释模板。
2025-10-19:
- 【需求】 ~~新增2个初始化函数,用于初始化溶解氧和水温的图表。~~不新增初始化函数,仅新增图表数据类,抬高图表高度,让所有数据同时显示在一个图内**(√)**
- 【需求】 ~~新增2个额外的下拉菜单。~~三个图表公用一个下拉菜单。(√)
- 【需求】 修改
formatter函数以及配套初始化内容,以及数据刷新机制,以适应三组数据同时显示。(√) - 【需求】
开发通用性的onOptionChange函数,以适配不同下拉菜单的变化。或针对原有的函数进行修改,适配多个下拉菜单的处理。 - 【需求】 将
onLoad内的函数移出,独立封装。 - 【需求】 修改存储数据的格式,适应三种传感器数据同时存储和操作。同时避免过于复杂的逻辑。考虑用一个二维数组来存储。记住顺序即可。(√)
- 【需求】 设计连接状态标识、增氧设备启停状态标志或文字。(√)
- 【需求】 新增使用说明按钮,打开即可转到说明书页面
- 【需求】 或许计划新增配置菜单,打开即可配置当前链接的设备以及热点名。
- 【更新】 修改了图表和下拉菜单的部分样式。
- 【更新】 修改了传感器卡片的文字尺寸,添加了单位显示。
- 【更新】 新增页面渐变背景色。
2025-10-20:
- 【更新】 更改了随机数刷新机制,使之生成的模拟数据为1个包含三个数据的数组
- 【更新】 更改了
updateSensorData函数,集成了setOption功能,使之能直接处理数组,添加了部分参数,用于判断是否需要刷新图表,以及是否为实时数据更新。 - 【BUG】 在浏览仅有单值的历史数据时,会出现异常。会出现一条不存在的曲线,横坐标会变为纯数值。
2025-10-21:
-
BUG的原因为,未修改逻辑时,存入的历史数据是字符串类型。1
2
3
4
5const valuesMap = {
PH: value.map(v => v[0]),
DO: value.map(v => v[1]),
WT: value.map(v => v[2])
};上面的代码仅针对数值类型,字符串只会提取第一个字符。
-
【更新】 加入
toNumber递归函数,实现字符串转为数字的功能,实现对旧数据的兼容,并保留原数组结构不变。1
2
3
4
5
6toNumbers(value) {
if (Array.isArray(value)) {
return value.map(v => this.toNumbers(v));
}
return Number(value);
}, -
【更新】 通过判断是否为嵌套数组,并在非嵌套时在外围包裹
[],实现对旧的一维数据的兼容。1
2
3if(!Array.isArray(value[0])) {
value = [value];
}; -
【更新】
updateSensorData函数内新增isSetOption参数,用于确认是否将数据传入图表。重绘图表、传入数据、刷新实时数值单独控制,避免冲突。可实现浏览历史数据是,继续刷新最新数据而不更新图表。 -
【更新】 将坐标轴指示器
axisPointer替换为tooltip。对三维数据的展示效果更佳。 -
【BUG】
tooltip在真机情况下,文字会出现异常的描边/阴影。视觉效果差。 -
【BUG】
formatter函数删除后,会导致模拟器在新渲染模式下也出现边框异常宽大的情况。
2025-10-22:
-
【修复】 通过查找微信开放社区。在
tooltip.textStyle下添加以下样式:1
2
3
4textStyle: {
textShadowBlur: 10,
textShadowColor: 'transparent'
}修复了
tooltip文字异常阴影的问题。在开放社区的开发者指出,必须配置textShadowBlur且不为0才可以 让textShadowColor生效。参考:微信开放社区
-
【修复】 修正了在仅有一维数组传入的情况下,无法正常绘制图表的问题。
但历史数据的问题依旧存在,表现为:当
DO、WT均输入了``undefined时,可以正常显示,由于后续时间轴上对应的内容仅PH有值,其余为空,也没有未定义值,所以不能刷新出来。考虑到现在即使传入数组仅有1个值,而不是预期的三个值,也可以默认返回undefined`值,故不打算对旧数据做适配。 -
【需求】 调整
tooltip。formatter,或通过其他方式,给tooltip的数据添加单位。
2025-10-23:
-
【更新】 重写了
formatter函数,为tooltip添加了自动显示单位的功能。对params的结构有了更好的理解。 -
【更新】 针对传值时可能的数据缺失或者
undefined的情况做了适配,当读取undefined值时,自动替换为 ‘-’ 。下面是一种很笨的写法,但是自己写的,能用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17formatter: (params) => {
var text = '时间:' + params[0].name;
for (var i = 0, length = params.length; i < length; i++) {
if (params[i].seriesName === 'DO') {
var unit = ' mg/L';
var seriesName = '溶解氧'
} else if (params[i].seriesName === 'WT') {
var unit = ' ℃';
var seriesName = '水温'
} else {
var unit = '';
var seriesName = 'PH'
};
text += '\n' + params[i].marker + seriesName + ':' + (params[i].data === undefined ? '--' : params[i].data + unit);
}
return text;
},
2025-10-24:
- 【更新】 新增了设备状态显示函数。针对不同的状态自动切换不同的颜色和显示文本。
- 【修改】 以增大圆角为主,修改了页面部分组件的样式。
2025-10-25:
-
【更新】 重做了传感器数据卡片布局。初步了解了伪元素的用法。
此处代码实现的样式为:在每两个传感器数据卡片之间绘制1条线。实现分割。效果和代码如图。

1
2
3
4
5
6
7
8
9.sensorData-card:not(:last-child)::after {
content: "";
position: absolute;
right: 0;
top: 0%;
bottom: 0%;
width: 1px;
background-color: rgb(233, 233, 233);
}需要注意的是,在这里,父级元素应该将
position设置为relative。否则这个伪元素无法定位。伪元素可以理解为被 CSS 虚拟创建出来的元素。它存在于渲染树中(浏览器的视觉层),但不出现在 HTML DOM 树里。它可以帮你“凭空生成”视觉或结构性元素,而不需要去动 DOM。它必须有
content属性,即使是空的。同时还复习了
justify-content和align-items的区别。前者控制主轴方向的对齐方式,后者控制交叉轴方向的。 -
【修改】 将开关全部替换为按钮,并调整自定义样式。但还未写相关功能。
-
【更新】 在主页新增“广告位招租”图片。
-
【更新】 新增了2个选项卡,但还未写跳转功能。
-
【修改】 调整了页面的部分样式。
2025-10-26:
-
【更新】 添加了一个新的页面,用来做配置项页面使用。同时实现了页面的跳转功能。
同时复习了
currentTarget.dataset的用法。也就是:dataset是一个对象,包含了该元素上所有以data-开头的自定义属性。用点可以引出包含的属性。以下面代码为例:1
<van-field value="{{ item.value }}" label="{{item.label}}" data-key="{{item.name}}" bind:change="onDataInput"/>
在
js内,currentTarget.dataset.key就可以取到data-key的值了。 -
【更新】 在G老师的指导下,学会用
hover-class并实现了选项卡点下时变为灰色的效果。hover-class是小程序视图容器原生自带的属性,用来指定按下去的样式类。实现点击态效果。 -
【更新】 添加了
onDataInput函数,将用户输入的值自动存入对应变量。复习了用$拼接字串的办法。 -
【更新】 添加了
onButtonPressed函数,点击保存按钮时,将自动判断用户是否填写全部配置项,如未完全填写将不保存至缓存,并在退出页面后销毁。以下面的代码为例,学习了
some和trim的使用,复习了箭头函数和map的使用。1
2const data = this.data.deviceInfo.map(item => [item.name, item.value]);
const isEmpty = data.some(item => !item[1].trim());trim()是 字符串方法,用于去掉首尾的空格(包括空格、换行、制表符)。some()是 数组方法,用于判断:数组中是否存在至少一个元素满足条件。那么上面的代码逻辑就是:把
data里的每个数组的第二个元素取出来,去除空格,然后取非,如果是空的,就返回true。 -
【更新】 调整了该页面的部分样式。
-
【计划】 计划明天完成用户配置数据保存和读取功能的部分。并新建一个页面,用来写项目说明。
2025-10-27:
-
【更新】 初步写完了用户配置储存功能。并能自动识别用户是否完成全部配置。根据保存成功与否,会弹出不同的自定义
popup。在过程中学习了几个问题。
-
过程中我分别用了以下两个语句。巧妙地用
find和findIndex方法来实现对索引和对应结构体的查找。1
2const popup = this.data.popup.find(item => item.name === currentPopup);
const index = this.data.deviceInfo.findIndex(item => item.name === key); -
const声明的变量是不可改变的。是只读的,如果在循环中用const声明变量,后面通过++实现自增,这就是在改变变量,会报错。建议用let。 -
这是一种比较稳妥的写法:
1
2
3
4
5const deviceInfo = this.data.deviceInfo;
for (let i = 0; i < res.data.length; i++) {
deviceInfo[i].value = res.data[i];
}
this.setData({deviceInfo: deviceInfo});我需要给
data下的deviceInfo赋值。我先把这个复制一份到函数内,然后操作这个新的变量,可以避免在重新赋值的时候出现未定义的错误。
-
-
【计划】 初步设计配网的逻辑流程和界面样式。
2025-10-28:
-
认真思考了配网机制。计划采用最简单的AP配网。因为微信限制比较多,不能直接访问局域网IP,所以配网无法在小程序上实现,仅在手机浏览器网页操作。设备启动后,如果长时间未连上网,将自动进入配网模式,此时用手机连接指定SSID的WIFI,然后扫二维码或者直接输入,进入指定网页,就可以输入路由器的SSID和PWD,实现配网。
那么小程序上需要保留的配置项只有UID(公用的,设备厂商的,实际上是我的)和设备编号(在云平台上指定,不同设备唯一的)。这两者都是MQTT协议用的。订阅需要提供用户ID和指定的topic。
-
计划先完善小程序本体功能。主要包含传感器数据读取,MQTT通信,以及指令发送的部分。
-
【更新】 配置页新增’清空‘按钮,用来清除已保存的数据,下次进入时配置项将为空。但此次显示内容并不清空,所以此处逻辑有待优化。
-
【更新】 针对新增按钮,新增了弹出层样式。改写了按钮按下时绑定函数的处理逻辑。能够根据按下的不同按钮弹出不同的popup。
-
【更新】 通过
page-meta,禁止配置页滚动。
2025-10-29:
- 初步了解了一下ESP8266的异步
WebServer库。 - 【更新】 通过在点击清空按钮后
setData将空数组传入,实现了在点击清空按钮后,视图层也能同步更新清空效果。 - 【更新】 新增
aquacultureIntro页面,用来放项目介绍相关内容。值得注意的是,把页面的最外层元素设置为scroll-view似乎比较合适一些。它不会导致内层元素宽度异常的问题。但是内层元素(例如卡片)需要单独设置宽度。 - 【更新】 主页新增
wiper,能够滚动展示图片。 - 【计划】 完成MQTT连接和订阅部分内容,实现根据用户配置的UID和设备编号,来进行数据的接受和指令发送的功能。然后就算是完工了。
2025-10-30:
-
【更新】 借助巴法云示例代码,成功让小程序以MQTT协议连接至服务器并更新状态。但是仍然有一些BUG。例如未配置UID,仍然跳转‘已连接’状态。
另外,考虑应当设计可关闭的状态,故计划将按钮替换为
switch开关。此外,还需要认真读一下
mqtt.min.js或学习其功能,实现对该模块的灵活应用,以及对状态显示的更好的适配。 -
【更新】 在页面内加入
popup,实现进入页面和点击连接按钮时,对未配置的提示。 -
【计划】 进一步调试MQTT连接,修复存在的BUG。然后实现云平台推送消息的接收和更新。
2025-10-31:
- 今天给买来的IR摄像头画了2块PCB板子,尝试了一些创新设计,即在板子正反面阻焊层上印图标,这样可以实现透光效果;通过实践,还学会了一些精准控制孔位的办法,以及针对元件封装的编辑(如不显示丝印和3D模型),所以今天并没有更新小程序。
- 值得一提:嘉立创不更新最新版本,可能出现无法使用白嫖券的情况。
处理过程:
2025.09.22 - 09.28:组件库样式覆盖与渲染冲突
-
遇到问题:引入 Vant 组件库后,遇到按钮固定高度无法修改、带圆角的按钮边框缺角、下拉菜单背景色无法覆盖,以及真机测试时部分样式失效的问题。
-
如何解决:
- 通过源码查找 CSS 变量(如 --dropdown-menu-background-color),在 wxss 或 filter 中覆盖为 transparent。
- 通过设置 display: block; 撑开元素,并将溢出属性设置为 overflow: auto。
- 引入组件的 transition 补丁解决交互失效。
-
解决原理:CSS 盒模型中,当内容超出盒子边界时,默认的 visible 属性会导致圆角边框被内容遮盖(看起来像缺角),修改 overflow 可以改变裁剪规则;真机与模拟器存在渲染引擎差异,需要对齐环境依赖。
-
总结复用:在使用第三方 UI 库时,不要硬写 CSS 强行覆盖,优先查阅源码暴露的 CSS 变量。overflow: auto 是修复边框与背景渲染冲突的通用“偏方”。
PS:后续研究发现,这个问题实际上也是skyline渲染导致的。所以这些方式是否有效也有待考证(应该是没用)。一般还是用WebView就好。
2025.09.25 - 10.13:数据流控制与作用域踩坑
- 遇到问题:
- 历史数据与实时数据渲染冲突,导致页面卡死。
this.chart报未定义错误。- 页面高度写死导致滚动条异常,下拉菜单展开时背景页面跟着滚动。
- 如何解决:
- 引入布尔标志位(flag),将定时器轮询(实时)与一次性读取缓存(历史)逻辑分离。
- 将普通的回调函数替换为 ES6 的箭头函数 =>。
- 利用
wx.getWindowInfo()动态计算状态栏和导航栏高度;利用<page-meta>结合下拉菜单的开关状态动态控制overflow:hidden。
- 解决原理:
- 作用域链:普通函数由调用者决定 this,回调中常丢失挂载页面的 this;而箭头函数没有自己的 this,会向外层寻找,完美继承 Page 实例。
- DOM 控制:position: fixed 只能固定元素自己,无法阻止事件穿透引发的页面滚动,必须在最外层(meta 或 body)切断滚动轴。
- 总结复用:标志位切换状态、箭头函数解决 this 指向、page-meta 锁定滚动,这三套组合拳是前端交互开发的标准范式,几乎在所有页面开发中都能无缝复用。
2025.10.14 - 10.23:微信缓存机制与 ECharts 深度调优
- 遇到问题:
- 历史数据被覆盖,每天只能查看到最新的少量数据。
- ECharts 在真机出现图表缩小、坐标指示器(label/tooltip)宽度异常宽大、文字带奇怪阴影、老数据格式不兼容导致报错。
- 如何解决:
- 修改缓存逻辑:先读旧数据,用
[...oldData, ...newData]拼接后再存入同一 key。 - ECharts Bug修复:降级渲染模式(移除 Skyline,改用 WebView);写一个彻底清空图表并重绘的
redrawEchart函数;为 tooltip 增加单位的 formatter 函数;加入textShadowColor: 'transparent'修复真机阴影。 - 编写
toNumbers递归函数,把老格式的一维字符串强转为兼容的新二维数字数组。
- 修改缓存逻辑:先读旧数据,用
- 解决原理:
- 微信 Storage 是键值对覆盖模式,不支持“增量追加”,必须全量读取、合并、全量覆写。
- 图表实例(Canvas)有状态记忆,通过 .clear() 释放内存和旧配置能消灭 90% 的玄学 Bug。
- 真机的 UI 渲染底层对默认属性的支持不如模拟器完善,需要把阴影、边框等属性显式声明为0或透明。
- 总结复用:
- 针对本地存储,“先读-合并-再写” 是万能套路。
- 对于复杂数据清洗,递归+高阶函数(map/some/find) 的组合极为高效。
- 当模拟器正常、真机 UI 错乱时,第一时间考虑降级渲染引擎(WebView)或补全 CSS 默认值。
2025.10.24 - 10.29:界面重构与用户配置态管理
- 遇到问题:卡片之间需要分割线但不想增加无用的 HTML 节点;用户填写配置时可能漏填,需要进行校验;需要跳转网页进行硬件 AP 配网。
- 如何解决:
- 使用 CSS 伪元素 ::after 配合绝对定位画出分割线。
- 使用
data.some(item => !item[1].trim())一行代码校验数组内是否存在空值,并配合自定义 popup 提示。 - 把网络配置下放到 ESP8266 的硬件 AP 模式,小程序只保留 UID 和设备号配置。
- 解决原理:
- 伪元素直接在浏览器的渲染树生成,不污染 DOM 树,且性能更好。
- trim() 去掉误触的空格,some() 只要遇到一个 true 就会短路返回,是做表单非空校验的最佳实践。
- 总结复用:学会了利用伪元素做 UI 修饰(分割线/小图标),以及 trim+some 的优雅表单校验法。这也让我意识到“全栈思维”的重要性——软件难以解决的局域网限制,交给硬件自己开热点解决,架构设计大过死磕代码。
2025.10.30 - 10.31:MQTT联调与拓展探索
- 遇到问题:未配置 UID 依然显示“已连接”;软硬件联调存在状态同步 BUG。
- 如何解决:增加了强校验和 Popup 阻断未配置情况下的连接请求。同时抽空利用立创 EDA 设计了带透光效果的 PCB。
- 总结复用:联调阶段最容易出现“假成功”的状态,前端的容错和边界情况(如未登录、空配置、断网)处理,比主逻辑的实现更考验产品的鲁棒性。
结论总结:
近期我尝试开发了一款物联网监测小程序,初步完成了 Vant 界面构建、ECharts 数据可视化、本地缓存管理及 MQTT 硬件通信。
我积累了一些基础知识:尝试应用了 CSS 盒模型与伪元素;尝试熟悉了 ES6 核心语法(如箭头函数与扩展运算符)来优化数据流;同时也摸索出了应对真机渲染差异与 Storage 缓存合并的实战套路。
