使用*ngFor与ngx-Quill的onEditorCreated时索引异常问题咨询
问题原因分析
这个问题我之前帮朋友排查过,本质是JavaScript闭包捕获变量引用的特性,再加上Quill编辑器初始化事件的异步性导致的:
- 当你在
*ngFor里写(onEditorCreated)="onEditorCreatedPosted($event, i)"时,i是循环中的迭代变量,JavaScript闭包会捕获这个变量的引用,而不是当前迭代的具体数值。 - Quill编辑器的
onEditorCreated事件是异步触发的(编辑器需要时间完成初始化渲染),而*ngFor的循环是同步执行的。当循环执行完毕后,i已经指向了最后一次迭代的数值,但此时有些编辑器的初始化事件还没触发,当它们触发时,读取的i就是当前变量引用的最新值,而不是迭代时的数值。 - 你看到的
0,0,1,2,0这种混乱输出,大概率是部分编辑器出现了重复初始化(比如组件重渲染、DOM变动导致编辑器重新实例化),每次初始化都会触发事件,而此时捕获的i可能刚好是某个阶段的数值。
解决方案
针对这个问题,有几个靠谱的解决办法,按推荐程度排序:
方法1:用工厂函数绑定当前索引
在组件类里写一个工厂函数,专门返回绑定了当前迭代索引的事件处理函数,这样每个迭代都会创建独立的闭包,捕获当前的索引值:
// 组件类中的代码 getEditorCreatedHandler(postIndex: number) { // 返回一个绑定了当前postIndex的函数 return (editorInstance: any) => { this.onEditorCreatedPosted(editorInstance, postIndex); }; } // 原来的处理函数保持不变 onEditorCreatedPosted(editor: any, index: number) { console.log(index); // 现在会输出正确的0,1,2,3... // 你的其他逻辑 }
然后在模板里修改事件绑定:
<quill-editor *ngFor="let post of posts; let i = index" (onEditorCreated)="getEditorCreatedHandler(i)($event)"> </quill-editor>
方法2:把索引存在DOM元素上
给每个quill-editor元素添加一个自定义属性存储索引,然后在事件处理函数中从DOM元素上读取:
<quill-editor *ngFor="let post of posts; let i = index" [attr.data-post-index]="i" (onEditorCreated)="onEditorCreatedPosted($event, $event.target.getAttribute('data-post-index'))"> </quill-editor>
然后在处理函数里记得把字符串转成数字:
onEditorCreatedPosted(editor: any, indexStr: string) { const index = parseInt(indexStr, 10); console.log(index); }
方法3:利用trackBy优化循环渲染
如果你的帖子列表有频繁的重渲染(导致编辑器重复初始化),可以给*ngFor加上trackBy,确保每个帖子只渲染一次,减少重复触发事件的情况:
// 组件类中添加trackBy函数 trackPostById(index: number, post: any): number { return post.id; // 假设你的帖子有唯一id字段 }
模板修改:
<quill-editor *ngFor="let post of posts; let i = index; trackBy: trackPostById" (onEditorCreated)="onEditorCreatedPosted($event, i)"> </quill-editor>
这个方法可以辅助减少重复触发的问题,但最好和方法1结合使用,彻底解决闭包的变量引用问题。
内容的提问来源于stack exchange,提问作者oudekaas
相关产品推荐
相关产品推荐

