MJY_Coco控件
MJY控件表
MJY-开发「MD按钮」踩过的坑
本文档使用 OkDoc 发布
-
+
首页
MJY-开发「MD按钮」踩过的坑
## MD按钮 - 踩过的坑 MJY-MD按钮支持的功能是「水波纹动画」|「按下缩小」并且全部使用贝塞尔曲线。 Made By MARKJY > MD按钮各版本下载链接:https://pan.aymao.com/s/ZxeIV ## 概述 本文档对比分析了MD按钮组件的非正常版本(2.1.0和3.0.0)与正常版本(4.0.0正式版)之间的差异,重点分析为什么非正常版本的水波纹动画无法正常反馈。 ## 版本对比 ### 非正常版本特征 - **v2.1.0**: 可以修改属性设置项,但水波纹动画异常 - **v3.0.0**: 可以修改属性设置项,但水波纹动画异常 ### 正常版本特征 - **v4.0.0**: 属性设置项可修改,动画完全正常,丝滑流畅 ## 详细对比分析 ### 1. 属性命名规范差异 #### 非正常版本(2.1.0和3.0.0) ```javascript properties: [ { key: '__width', label: '宽度', valueType: 'number', defaultValue: 120 }, { key: '__height', label: '高度', valueType: 'number', defaultValue: 48 }, { key: 'text', label: '按钮文字', valueType: 'string', defaultValue: '按钮' }, { key: 'textColor', label: '文字颜色', valueType: 'color', defaultValue: '#ffffff' }, // ... 其他属性没有双下划线前缀 ] ``` **问题**: 只有width和height使用双下划线前缀(__),其他属性如text、textColor、backgroundColor等都没有前缀。 #### 正常版本(4.0.0) ```javascript properties: [ { key: '__width', label: '宽度', valueType: 'number', defaultValue: 120 }, { key: '__height', label: '高度', valueType: 'number', defaultValue: 48 }, { key: '__text', label: '按钮文字', valueType: 'string', defaultValue: '按钮' }, { key: '__textColor', label: '文字颜色', valueType: 'color', defaultValue: '#ffffff' }, { key: '__backgroundColor', label: '背景颜色', valueType: 'color', defaultValue: '#2196F3' }, // ... 所有属性都使用双下划线前缀 ] ``` **解决方案**: 所有属性都统一使用双下划线前缀(__)。 ### 2. 构造函数属性初始化差异 #### 非正常版本(2.1.0) ```javascript constructor(props) { super(props); this.__width = props.__width || 120; this.__height = props.__height || 48; this.text = props.text || '按钮'; // ❌ 没有前缀 this.textColor = props.textColor || '#ffffff'; // ❌ 没有前缀 this.backgroundColor = props.backgroundColor || '#2196F3'; // ❌ 没有前缀 // ... } ``` #### 非正常版本(3.0.0) ```javascript constructor(props) { super(props); this.__width = props.__width || 120; this.__height = props.__height || 48; this.text = props.text || '按钮'; // ❌ 没有前缀 this.textColor = props.textColor || '#ffffff'; // ❌ 没有前缀 // ... } ``` #### 正常版本(4.0.0) ```javascript constructor(props) { super(props); this.__width = props.__width || 120; this.__height = props.__height || 48; this.__text = props.__text || '按钮'; // ✅ 有前缀 this.__textColor = props.__textColor || '#ffffff'; // ✅ 有前缀 this.__backgroundColor = props.__backgroundColor || '#2196F3'; // ✅ 有前缀 // ... } ``` ### 3. setProps方法实现差异(核心问题) #### 非正常版本(2.1.0) ```javascript setProps(props) { if (!props) return; let hasChanges = false; // 只检查有变化的属性 if (props.__width !== undefined && props.__width !== this.__width) { this.__width = props.__width; hasChanges = true; } if (props.text !== undefined && props.text !== this.text) { this.text = props.text; hasChanges = true; } // ... 其他属性检查 if (hasChanges) { this.render(); // 只在有变化时渲染 } } ``` **致命缺陷**: 这个实现假设只有在属性值真正改变时才需要重新渲染,但在Coco环境中,即使属性值相同,重新渲染也可能需要触发以更新动画状态。 #### 非正常版本(3.0.0) ```javascript setProps(props) { if (!props) return; let hasChanges = false; // 同样的问题:只检查有变化的属性 if (props.__width !== undefined && props.__width !== this.__width) { this.__width = props.__width; hasChanges = true; } // ... if (hasChanges) { this.render(); // 只在有变化时渲染 } } ``` #### 正常版本(4.0.0) ```javascript setProps(props) { if (props) { // 直接更新所有可能的属性(不检查是否变化) if (props.__width !== undefined) this.__width = props.__width; if (props.__height !== undefined) this.__height = props.__height; if (props.__text !== undefined) this.__text = props.__text; // ... 所有属性都直接更新 // 强制重新渲染(不管属性是否变化) this.render(); } } ``` **关键改进**: 不检查属性是否真正改变,每次都强制重新渲染。 ### 4. 动画触发机制差异 #### 非正常版本的动画触发 ```javascript _handleMouseDown(event) { // ... 设置水波纹状态 this._ripple = { x: x, y: y, isActive: true, scale: 0 }; this.render(); // 第一次渲染 setTimeout(() => { if (this._ripple && this._ripple.isActive) { this._ripple.scale = 1; this.render(); // 第二次渲染 } }, 16); } ``` #### 正常版本的动画触发 ```javascript _handleMouseDown(event) { // ... 设置水波纹状态 const newRipple = { id: rippleId, x: clickX, y: clickY, size: '10px', opacity: 0.3, isExpanding: false, isFinalPhase: false, // ... }; // 强制重新渲染(使用super.setProps) super.setProps({forceUpdate: Date.now()}); } ``` ### 5. 渲染更新机制差异 #### 非正常版本 使用 `this.render()` 直接调用渲染方法。 #### 正常版本 使用 `super.setProps({forceUpdate: Date.now()})` 通过父类的属性更新机制触发渲染。 ## 核心问题总结 ### 1. **属性命名不一致** - 非正常版本中属性命名混乱,有些有双下划线前缀,有些没有 - 这导致setProps方法无法正确处理所有属性 ### 2. **setProps方法实现缺陷** - 非正常版本的setProps方法只在检测到属性真正变化时才调用render() - 但在Coco环境中,即使属性值相同,也可能需要重新渲染来触发动画 ### 3. **动画触发机制不完善** - 非正常版本依赖setTimeout来创建动画效果 - 正常版本使用React的强制更新机制确保动画被正确触发 ### 4. **渲染触发方式不同** - 非正常版本直接调用this.render() - 正常版本通过super.setProps()触发渲染,确保兼容性 ## 解决方案 ### 1. 统一属性命名规范 所有属性都使用双下划线前缀(__),确保一致性。 ### 2. 简化setProps方法 移除属性变化检测逻辑,直接更新所有属性并强制重新渲染。 ### 3. 使用强制更新机制 使用`super.setProps({forceUpdate: Date.now()})`来确保每次都能触发重新渲染。 ### 4. 优化动画状态管理 使用数组管理多个水波纹状态,确保动画的连续性和正确性。 ## 结论 非正常版本的主要问题是**setProps方法的实现过于复杂且不符合Coco环境的要求**。通过简化属性更新逻辑、统一命名规范、使用强制更新机制,可以确保水波纹动画在Coco环境中正常工作。 正常版本(4.0.0)的成功关键在于: 1. **简单直接的属性更新机制** 2. **统一的属性命名规范** 3. **强制重新渲染策略** 4. **完善的多水波纹状态管理**
MARKJY
2025年11月6日 10:43
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码