爱大客 - 2024年8月
type: channel
link: https://www.idarc.cn/index.php/2024/08/
description: Every piece of all creatures in this freezing world, are racing for freedom.
items: 微信小程序固定元素位置的两种形式
items: 微信小程序的页面如何知道是从哪儿进入的?
items: CSS flex-box
items: 京东E卡的小滑头
items: 微信小程序的组件
items: 数据库设计:绘制实体关系图(Entry Relationship Diagram, ER图/E-R图/ERD)
items: js如何在对象的键值变化时调用函数, 并且操作对象的代码不需要变动(无感)
items: 做了个event发送和超时等待程序, 结果小程序不能用, 只适用于node
items: 英语ob开头却有不同的发音和不同的意思
items: JSDoc注释js代码的规范

微信小程序固定元素位置的两种形式
type: item
date: 2024-08-28T14:00:22+08:00
description: 一种是页面json不变, 使用css属性position: fixed;,同时规定css属性 top bottom left right. 第二种是可以在页面的json文件中写: "disableScroll": true, 然后再元素上使用css属性position: absolute;,再规定css属性top bottom left right. 这种方式是结合recycle-view来用的, 原因太久不太记得了, 似乎因为Recycle-view的一些特性导致position:fixed不能正常固定或页面不能正常滚动.

微信小程序的页面如何知道是从哪儿进入的?
type: item
date: 2024-08-26T21:58:00+08:00
description: 进入一个页面有几种方式: navigateTo,navigateBack, 熄屏再显示(从其他应用切换回来也是类似). GPT给的建议是通过app.globalData存储全局变量来判断, 或者用storage存储判断, 感觉都不优雅, 把单个页面问题的解决扩展到了全局去了. 但目前还没有其他好办法, 因为navigateBack和熄屏再显示都是触发onHide,所以无法区分. GPT还给了一个幻觉建议, 说onShow会带形参进来,判断形参就可以, 但事实上onShow不会带任何形参 通过navigateTo,navigateBack从其他页面导航到这个页面, 通常都需要更新页面数据. 因为上一页导航过来, 这一页的数据还没有生成过; 从下一页返回, 可能在下一页对数据做了更新.

CSS flex-box
type: item
date: 2024-08-24T12:22:00+08:00
description: 因为CSS的flex每次用的时候总是忘记, 这儿总结一下: 将flex理解为一个画框(父元素)里面的元素(子元素)的排列. 父元素设置整体遵从的规则, 子元素设置个别规则. 总体规格包括: flex-direction: 确定主轴方向. 元素是沿着主轴方向依次放置的. 交叉轴(副轴)即主轴的垂直轴, 确定一行主轴放不下的元素,下一行放的方向. flex-wrap: 元素在主轴放不下, 要不要回车放在下一行. justify-content: 确定元素主轴排列, 以及元素间距 align-items: 确定副轴的元素排列 align-content: 确定wrap后多行的元素怎么放置,以及行间距等.

京东E卡的小滑头
type: item
date: 2024-08-21T09:13:57+08:00
description: 银行送了10元京东E卡,进了京东APP完全找不到绑定的地方, 搜索兰搜索京东E卡也只是给了一堆的卖E卡的连接. 说是付款的时候京东自营商品可用, 然后下了好几个单,专门找京东自营,充话费,京东超市和京喜自营买纸巾,付款的时候都没有选择E卡的界面. 找了一圈只好问机器客服, 这才找到绑卡的地方: 我的钱包-点击查看全部-礼品卡,此时注意不要点那个大大的京东E卡图标, 而要点击绑定新卡! 然后输入卡的密码, 只用输入密码, 而不用输入卡号, 虽然给了卡号但并没有什么用. 然后, 我去找下单但没有付款的链接, 还是不能选择! 接着下新单, 也没有选E卡的地方! 我勒个去, 赶快百度找下经验, 发现百度经验这个下单支付界面怎么和我不一样? 终于发现了, 原来从购物车购买,点击去结算才有这个选礼品卡(京东卡/E卡)订单界面, 这个订单界面选择地址, 查看订单详情,选择开票等等. 从商品链接直接购买真的不能选择吗? 我又研究了下,发现不是的!商品链接里面直接点击下单购买(这个名字在不同的商品链接还不一样, 有的叫到手价购买, 有的叫立即购买预估), 这时候不会转到新页面,而是从下方弹出来一个半屏, 上面显示收货地址,选择商品数量和规格, 平常这个时候就选"支付"了, 但注意, 这个半屏是可以上滑的! 你如果上滑一点点, 发现滑出来的只是其他商品的广告, 但如果继续上滑, 才出现商品价格详情,支付方式,发票,留言...等等这些订单信息, 全部堆在这个半屏的最下面, 跟从购物车结算的订单界面是类似的. 但是等等, 为什么礼品卡的选择消失了? 哈哈,这时候还要去选择商品金额栏目里的四个灰色小字:展开更多,才看得到优惠券和礼品卡两个选项,不得不说比购物车结算订单界面要隐蔽得多. 京东这个界面设计真的很滑头, 其逻辑是想方设法让你别用券直接支付, 让你确认地址/品类/数量这些最重要信息后就直接付款, 这样 一方面京东拿到最多的钱, 另一方面你买了以后即使想到有优惠券, 也只能下次用了, 又引诱你下次继续在京东购物. 之前几次买东西找不到开票的地方也是这个原因.

微信小程序的组件
type: item
date: 2024-08-20T15:11:00+08:00
description: 引用自定义组件 组件名 组件json-> 页面json-> 页面wxml mycomp.js/.json/.wxml/.css {"component": true,usingComponents": {}} {"usingComponents": {"mycomp": "../../components/mycomp/mycomp"}} 组件展现页面的数据和自身的数据 没有区分. 如 `Component({ properties: {propFromPage: 1}, data: {propFromData: 2} }) 在组件wxml中都是同样方式引用{{propFromPage}} {{propFromData}}. 但在组件js中引用方式有区分:this.properties.propFromPage, this.data.propFromData 调用函数 组件中的函数引用方式在js中不需要加methods, 如 `Component({ properties:{prop:{type: Number, value:1, observer(newValue, oldValue){this.f1();}}}, lifetimes:{attached(){this.f1();}}, methods: { f1(){}, f2(){this.f1()}, } }) 页面向组件传数据 页面js-> 页面wxml-> 页面wxml 组件js Page({data:{pageprop: 1}}) {{prop}} Component({ properties: {prop: 默认值}, methods:{f(){this.properties.prop },}}) 组件向页面传数据(通过事件) 组件js-> 页面wxml-> 页面js Component({method:{f(){this.triggerEvent('someevent', somevalue) },}}) processIt(e){let value = e.detail}

数据库设计:绘制实体关系图(Entry Relationship Diagram, ER图/E-R图/ERD)
type: item
date: 2024-08-20T13:31:17+08:00
description: 有两种不同文档描述了两种不同的ER图, 一种是把属性放在实体外面https://zhuanlan.zhihu.com/p/270299029, 另一种是把属性和实体放在一起https://blog.csdn.net/character_/article/details/124142908. 后者看起来更美观些. draw.io可以画ER图.

js如何在对象的键值变化时调用函数, 并且操作对象的代码不需要变动(无感)
type: item
date: 2024-08-17T17:35:00+08:00
description: GPT4o给了三种方法, 在后面给出. 第三种方法是改赋值=为调用函数, 意味着所有的赋值都要改为函数调用,不实用. 分析下方法一Proxy和方法二getter/setter. Proxy的好处是不会改变原对象,而是建立了一个新的proxy对象, 对新对象的赋值会触发set函数. 问题有三个: 一是任何键值变化都会触发set,需要自己判断键值; 二是需要将原对象的名称指向新proxy对象, 才能实现无感. 三是无法通过instanceof判断pr一个实例是不是Proxy的实例, 只能自己在创建实例时添加一个自定义key如_isProxy来判断.(后面段落说明) getter/setter是最早一代vue.js用的方法, 所有在app.data中的键都会用Object.defineProperty()的get/set重定义一遍, 做到自动更新UI. 好处是可以逐个key定义,不影响其他key, 问题是原key值就会消失,除非定义前先保存一下. 并且需要保存到另一个键下面(一般前面加个下划线_)而不能保存在本key下面, 否则会导致反复触发直到调用栈溢出Maximum call stack size exceeded. 这个话题在vue的官方文档中也有讨论: https://cn.vuejs.org/guide/extras/reactivity-in-depth, 里面也提到在vue3中,从getter/setter已经转向了proxy机制. 另外一个问题, 是如果键值是一个对象(数组也是),也就是下面有子键, 对子键键值的修改, 只会调用get而不是set!并且对Proxy和getter/setter机制都一样. 如: proxyObject.k = {k1:1} // 调用set proxyObject.k.k1 = 2 //调用get 怎么解决这个问题,GPT4o的回答是递归代理. 见后面一节. 方法1: 使用Proxy 在 JavaScript 中，如果希望在对象的某个键变化时自动调用一个函数，可以使用 Proxy 对象来实现。Proxy 允许你创建一个代理对象，以便对其属性的访问和修改进行拦截。 下面是一个使用 Proxy 的示例代码，当对象的 someKey 属性变化时，会自动调用函数 a： // 定义要监控的对象 const targetObject = { someKey: '初始值', }; // 定义要自动调用的函数 function a(newValue) { console.log(`someKey 的新值是: ${newValue}`); } // 创建 Proxy 代理对象 const proxyObject = new Proxy(targetObject, { set(target, property, value) { // 当设置 someKey 时，调用函数 a if (property === 'someKey') { a(value); } // 修改属性的值 target[property] = value; // 返回 true 表示设置成功 return true; } }); // 测试：修改 someKey proxyObject.someKey = '新的值'; // 这将输出: someKey 的新值是: 新的值 // 可以继续修改其他属性也不会触发 a() proxyObject.anotherKey = '另一个值'; console.log(proxyObject.anotherKey); // 输出: 另一个值 说明： 在上面的示例中，创建了一个对象 targetObject 和一个函数 a。 使用 Proxy 创建了代理对象 proxyObject，并在其 set 拦截器中定义了逻辑。当 someKey 被修改时，会自动调用函数 a(newValue)。 修改其他属性不会触发这个函数，只会在指定的键发生变化时执行。 通过这种方式，你可以灵活地监控对象属性的变化，并根据需要触发相应的逻辑。 方法2 使用getter/setter 你可以使用 JavaScript 的 Object.defineProperty() 方法来定义 getter 和 setter，使得每次修改对象属性时都能执行相应的函数。 const targetObject = { _someKey: '初始值', // 私有变量 }; // 定义要自动调用的函数 function a(newValue) { console.log(`someKey 的新值是: ${newValue}`); } // 使用 Object.defineProperty 定义 getter 和 setter Object.…

做了个event发送和超时等待程序, 结果小程序不能用, 只适用于node
type: item
date: 2024-08-16T16:00:57+08:00
description: node版本 作为tools.js的功能, 代码如下 const EventEmitter = require('events'); const eventEmitter = new EventEmitter(); // 事件发射 emitEvent(event, arg){ eventEmitter.emit(event, arg) }, //等待事件, 成功则返回args, 失败则返回null async waitEvent(event, timeout = 500){ return new Promise((resolve, reject) => { let timer = setTimeout(() => { reject(timeout) // 如果用await waitEvent(),则抛出异常值为timeout }, timeout) // 监听消息事件 const messageListener = (arg) => { clearTimeout(timer); // 清除定时器 eventEmitter.removeListener(event, messageListener); // 移除监听器 resolve(arg); // 解决Promise，返回数据 }; eventEmitter.on(event, messageListener); // 添加监听器 }) } 使用示例: f = async ()=>{ setTimeout(()=>tools.emitEvent('laugh',"hahaha"), 100) try{ let res = await tools.waitEvent('laugh', 500) console.log("res is", res) }catch(e){console.log('timeout', e)} } f() // 打印: res is hahaha

英语ob开头却有不同的发音和不同的意思
type: item
date: 2024-08-16T10:08:00+08:00
description: obligation(义务) obviously(显然地),其中的ob-读作/ɒb/, 词根是强调的作用, 重音在o. 而oblivious(健忘的)的obliv- 读作/əˈblɪv/,词根是遗忘的意思, 重音在b.

JSDoc注释js代码的规范
type: item
date: 2024-08-14T16:07:21+08:00
description: 参考https://juejin.cn/post/6995464881205936164 /** * @description 描述fn的作用或功能 * @param {string} a 参数描述 * @param {number} [b] 参数描述 * @param {boolean} [c=false] 参数描述 * @param {array} arr 参数描述 * @param {string} arr[0] 参数描述 * @param {number} [arr[1]=undefined] 参数描述 * @return {number} 描述返回值 */