初始化editorState数据
const initialState = {
blocks: [
{
key: _.uniqueId('key'),
text: 'H2标题-0',
type: 'header-two',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'H3标题-0-1',
type: 'header-three',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'H1标题',
type: 'header-one',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'H3标题-1-1-1',
type: 'header-three',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'H2标题-1-1',
type: 'header-two',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: '文字段落:',
type: 'unstyled',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'blockquote',
type: 'blockquote',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'code-block',
type: 'code',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'figure',
type: 'atomic',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'item0',
type: 'unordered-list-item',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'item1',
type: 'unordered-list-item',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'H2标题-1-2',
type: 'header-two',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'H3标题-1-2-1',
type: 'header-three',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'H3标题-1-2-2',
type: 'header-three',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'H2标题-1-3',
type: 'header-two',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'H3标题-1-3-1',
type: 'header-three',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'H1标题-2',
type: 'header-one',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: _.uniqueId('key'),
text: 'H3标题-2-1-2',
type: 'header-three',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
],
entityMap: {},
};
将数据通过页面交互等方式传递给getToc方法
export const getToc = (editorState: EditorState): TocItem[] => {
const editorStateObj = editorState.getCurrentContent().toJS();
const { blockMap } = editorStateObj;
const blockValues = _.values(blockMap);
// 只保留标题类型
const dataSource: BlockMapValuesItem[] = [];
_.forEach(blockValues, (bv) => {
if (_.includes(typeArr, bv.type)) {
dataSource.push({ ...bv, level: typeMap[`${bv.type}`] });
}
});
if (_.isEmpty(dataSource)) {
return [];
}
const headerItem: BlockMapValuesItem = _.head(dataSource) || initBlockItem;
const targetToc: TocItem[] = [
{
label: headerItem.text,
type: headerItem.type,
level: headerItem.level,
children: [],
},
];
_.forEach(dataSource, (ds, dsi) => {
if (dsi !== 0) {
recursiveTitle(ds, targetToc);
}
});
console.log(JSON.stringify(targetToc));
return targetToc;
};
getToc拿到editorState变量后,根据其getCurrentContent方法,通过对blockMap处理后获取dataSource数据
通过recursiveTitle函数递归得到最终结构化数据
- 将当前标题数据dataSource的第一个项先放入targetToc中
- 从索引1开始遍历dataSource,将每一项curItem的level值跟targetToc的最后一项lastTargetItem的level值进行对比
- 如果curItem的level大于lastTargetItem的level,那么说明curItem的标题层级要比lastTargetItem深,此时对lastTargetItem的children进行判断,执行步骤4;否则执行步骤5
- 如果lastTargetItem的children为空,直接将curItem放入该children;如果children不为空,那么将children作为targetToc进行递归操作
- curItem的level小于或者等于lastTargetItem的level时,说明当前层级比lastTargetItem的层级要浅,那么层级之间就不是嵌套而是并列关系,则直接放入targetToc
/**
* 将当前节点放入所属父节点的children
* @param curItem 当前待插入的标题信息
* @param targetToc 参照层级
*/
function recursiveTitle(curItem: BlockMapValuesItem, targetToc: TocItem[]) {
const lastTargetItem: TocItem = _.last(targetToc) || initTocItem;
if (curItem.level > lastTargetItem.level) {
// 当前层级比参照层级深
if (_.isEmpty(lastTargetItem.children)) {
// 参照层级的children为空时
lastTargetItem.children.push({
label: curItem.text,
type: curItem.type,
level: curItem.level,
children: [],
});
} else {
// 参照层级的children不为空时,继续传递参照层级的children作为参照
recursiveTitle(curItem, lastTargetItem.children);
}
} else {
// 当前层级等于或者小于参照层级,
targetToc.push({
label: curItem.text,
type: curItem.type,
level: curItem.level,
children: [],
});
}
}
最终得到数据的结构样例:
[
{
"label": "H2标题-0",
"type": "header-two",
"level": 2,
"children": [
{
"label": "H3标题-0-1",
"type": "header-three",
"level": 3,
"children": []
}
]
},
{
"label": "H1标题",
"type": "header-one",
"level": 1,
"children": [
{
"label": "H3标题-1-1-1",
"type": "header-three",
"level": 3,
"children": []
},
{
"label": "H2标题-1-1",
"type": "header-two",
"level": 2,
"children": []
},
{
"label": "H2标题-1-2",
"type": "header-two",
"level": 2,
"children": [
{
"label": "H3标题-1-2-1",
"type": "header-three",
"level": 3,
"children": []
},
{
"label": "H3标题-1-2-2",
"type": "header-three",
"level": 3,
"children": []
}
]
},
{
"label": "H2标题-1-3",
"type": "header-two",
"level": 2,
"children": [
{
"label": "H3标题-1-3-1",
"type": "header-three",
"level": 3,
"children": []
}
]
}
]
},
{
"label": "H1标题-2",
"type": "header-one",
"level": 1,
"children": [
{
"label": "H3标题-2-1-2",
"type": "header-three",
"level": 3,
"children": []
}
]
}
]
欢迎扫码关注作者公众号
