feat(): 性能优化

This commit is contained in:
yanmao 2021-11-20 22:28:26 +08:00
parent cdd9f3ba03
commit 2b24d6a3db
9 changed files with 90 additions and 70 deletions

View File

@ -1237,7 +1237,8 @@ class Block implements BlockModelInterface {
if (!first) {
return;
}
const children = block.children();
const blockElement = block.get<Element>();
const children = blockElement?.childNodes || [];
// 只有一个节点
if (children.length === 1) {
const node = first;
@ -1256,8 +1257,8 @@ class Block implements BlockModelInterface {
) {
return;
}
if (block.find('br').length === 0) return;
// 没有br标签
if (!blockElement?.querySelector('br')) return;
let container;
let prevContainer;

View File

@ -72,12 +72,9 @@ class ChangeModel implements ChangeInterface {
private _change() {
if (!this.isComposing()) {
this.engine.card.gc();
console.time('change');
const value = this.getValue({
ignoreCursor: true,
});
console.timeEnd('change');
if (!this.valueCached || value !== this.valueCached) {
const trigger =
this.changeTrigger.length === 2

View File

@ -82,7 +82,8 @@ export default class Paste {
}
});
//处理后如果不是一个有效的节点就移除包裹
if (!this.schema.getType(node)) {
let type = this.schema.getType(node);
if (!type) {
nodeApi.unwrap(node);
return;
}
@ -90,13 +91,16 @@ export default class Paste {
if (nodeApi.isList(node)) {
node.css('padding-left', '');
}
let attributes: { [k: string]: string } | undefined =
node.attributes();
// 删除空 style 属性
if (node.attributes('style').trim() === '') {
if ((attributes.style || '').trim() === '') {
node.removeAttributes('style');
}
// br 换行改成正常段落
if (nodeApi.isBlock(node, this.schema)) {
if (type === 'block') {
this.engine.block.brToBlock(node);
}
// 删除空 span
@ -107,24 +111,23 @@ export default class Paste {
node = parent;
parent = node.parent();
if (!parent) return;
type = undefined;
attributes = undefined;
}
// 删除 google docs 根节点
// <b style="font-weight:flat;" id="docs-internal-guid-e0280780-7fff-85c2-f58a-6e615d93f1f2">
if (/^docs-internal-guid-/.test(node.attributes('id'))) {
nodeApi.unwrap(node);
return;
}
if (!attributes) attributes = node.attributes();
// 跳过Card
if (node.attributes(READY_CARD_KEY)) {
if (attributes[READY_CARD_KEY]) {
return;
}
const nodeIsBlock = nodeApi.isBlock(node, this.schema);
const nodeIsBlock = type
? type === 'block'
: nodeApi.isBlock(node, this.schema);
const nodeIsVoid = nodeApi.isVoid(node, this.schema);
let parentIsBlock = nodeApi.isBlock(parent, this.schema);
// 删除零高度的空行
if (
nodeIsBlock &&
node.attributes('data-type') !== 'p' &&
attributes['data-type'] !== 'p' &&
!nodeIsVoid &&
!parentIsBlock &&
//!node.isSolid() &&
@ -134,7 +137,7 @@ export default class Paste {
return;
}
// 段落
if (node.attributes('data-type') === 'p') {
if (attributes['data-type'] === 'p') {
node.removeAttributes('data-type');
}
if (nodeIsBlock && parent?.name === 'p') {

View File

@ -949,7 +949,7 @@ class Inline implements InlineModelInterface {
repairBoth(node: NodeInterface | Node) {
const nodeApi = this.editor.node;
if (isNode(node)) node = $(node);
if (node.parent() && !nodeApi.isVoid(node)) {
if (node.get()?.parentNode && !nodeApi.isVoid(node)) {
const zeroNode = $('\u200b', null);
const prev = node.prev();
const prevPrev = prev?.prev();
@ -991,7 +991,7 @@ class Inline implements InlineModelInterface {
if (next && next.isText()) {
next.text('\u200b' + next.text());
} else {
node.after(this.editor.node.clone(zeroNode, true, false));
node.after(nodeApi.clone(zeroNode, true, false));
if (next?.name === 'br') {
next.remove();
}

View File

@ -659,14 +659,15 @@ class NodeModel implements NodeModelInterface {
* @param props
*/
setAttributes(node: NodeInterface, attrs: any) {
let { style, ...attributes } = attrs;
Object.keys(attributes).forEach((key) => {
let style = attrs.style;
Object.keys(attrs).forEach((key) => {
if (key === 'style') return;
if (key === 'className') {
const value = attributes[key];
const value = attrs[key];
if (Array.isArray(value)) {
value.forEach((name) => node.addClass(name));
} else node.addClass(value);
} else node.attributes(key, attributes[key].toString());
} else node.attributes(key, attrs[key].toString());
});
if (typeof style === 'number') style = {};
if (typeof style === 'string') style = getStyleMap(style);

View File

@ -9,7 +9,12 @@ import {
ConversionRule,
SchemaRule,
} from '../types';
import { CARD_ELEMENT_KEY, CARD_KEY, READY_CARD_KEY } from '../constants';
import {
CARD_ELEMENT_KEY,
CARD_KEY,
CARD_SELECTOR,
READY_CARD_KEY,
} from '../constants';
import {
escape,
unescape,
@ -105,6 +110,46 @@ class Parser implements ParserInterface {
}
if (paserBefore) paserBefore(this.root);
}
convert(
conversion: ConversionInterface,
node: NodeInterface,
schema?: SchemaInterface,
) {
let value = conversion.transform(node);
const oldRules: Array<ConversionRule> = [];
const nodeApi = this.editor.node;
while (value) {
const { rule } = value;
oldRules.push(rule);
const { name, attributes, style } = value.node;
delete attributes[DATA_ID];
const newNode = $(`<${name} />`);
nodeApi.setAttributes(newNode, {
...attributes,
style,
});
//把旧节点的子节点追加到新节点下
newNode.append(node.children());
if (node.isCard()) {
node.before(newNode);
node.remove();
value = undefined;
continue;
} else {
if (!nodeApi.isBlock(newNode, schema)) {
//把包含旧子节点的新节点追加到旧节点下
node.append(newNode);
} else {
// 替换
node.before(newNode);
node.remove();
break;
}
}
//排除之前的过滤规则后再次过滤
value = conversion.transform(node, (r) => oldRules.indexOf(r) < 0);
}
}
normalize(
root: NodeInterface,
schema: SchemaInterface,
@ -112,7 +157,18 @@ class Parser implements ParserInterface {
) {
const nodeApi = this.editor.node;
const inlineApi = this.editor.inline;
//转换标签和分割 mark 和 inline 标签
//转换标签和分割 mark 和 inline
// 不分割,就只转换卡片
if (!this.isNormalize) {
if (!conversion) return;
const cards = root.find(CARD_SELECTOR);
cards.each((_, index) => {
const cardNode = cards.eq(index);
if (!cardNode) return;
this.convert(conversion, cardNode, schema);
});
return;
}
root.traverse((node) => {
if (
node.equal(root) ||
@ -122,48 +178,10 @@ class Parser implements ParserInterface {
if (node.isElement()) {
const isCard = node.isCard();
//转换标签
if (
conversion &&
((this.isNormalize && !schema.getType(node)) || isCard)
) {
let value = conversion.transform(node);
const oldRules: Array<ConversionRule> = [];
while (value) {
const { rule } = value;
oldRules.push(rule);
const { name, attributes, style } = value.node;
delete attributes[DATA_ID];
const newNode = $(`<${name} />`);
nodeApi.setAttributes(newNode, {
...attributes,
style,
});
//把旧节点的子节点追加到新节点下
newNode.append(node.children());
if (isCard) {
node.before(newNode);
node.remove();
value = undefined;
continue;
} else {
if (!nodeApi.isBlock(newNode, schema)) {
//把包含旧子节点的新节点追加到旧节点下
node.append(newNode);
} else {
// 替换
node.before(newNode);
node.remove();
break;
}
}
//排除之前的过滤规则后再次过滤
value = conversion.transform(
node,
(r) => oldRules.indexOf(r) < 0,
);
}
if (conversion && (!schema.getType(node) || isCard)) {
this.convert(conversion, node, schema);
}
if (!this.isNormalize || isCard) return;
if (isCard) return;
//分割
const filter = (node: NodeInterface) => {
//获取节点属性样式

View File

@ -372,7 +372,6 @@ class TableComponent extends Card<TableValue> implements TableInterface {
};
this.scrollbar.on('change', handleScrollbarChange);
}
this.scrollbar?.refresh();
this.selection.on('select', () => {
this.conltrollBar.refresh();
if (!isEngine(this.editor)) return;

View File

@ -82,7 +82,7 @@ div[data-card-key="table"].card-selected .data-table, div[data-card-key="table"]
width: 14px;
height: 14px;
cursor: pointer;
z-index: 2;
z-index: 4;
background-color: #ffffff;
}

View File

@ -344,6 +344,7 @@ class Table extends Plugin<Options> {
element?.css('background-color');
if (background) tds?.css('background', background);
});
this.editor.nodeId.generateAll(node, true);
this.editor.card.replaceNode(node, TableComponent.cardName, {
html: node
.get<HTMLElement>()!