kityMinder 针对标签撤销重做时,会出现有undefined的标签出现

本文章系列将会记录在做kityminder二次开发过程中,遇到的问题以及解决方法

最近自己在验证脑图编辑器的时候,发现当一个节点中设置多个标签以后,通过撤销进行操作后,界面就会出现一个空白的标签内容,同时在已存在的标签列表中就会出现一个undefined的标签文字。效果图如下:

在这里插入图片描述

问题分析

首先要理清楚这个问题的话,我们需要先理清楚,设置完多个标签以后,通过点击撤销按钮以后,代码逻辑里面发生了什么事情。

其实整理的逻辑是这样子的。

  1. 每次页面发生变化的时候,都会去生成一个差异的patch,放到历史的操作记录中。代码如下:

    makeUndoDiff() {
            var headSnap = editorCommand.exportJson();
            var diff = compare(headSnap, this.lastContent);
            if (diff.length) {
                this.undoList.push(diff);
                this.setUndo();
                while (this.undoList.length > this.MAX_HISTORY) {
                    this.undoList.shift();
                }
                this.lastContent = headSnap;
                return true;
            }
            return false;
        }
    
  2. 用户一旦点击撤销按钮后,就会从undoList中取出最新的一条diff数据,然后调用kityminder的 applyPatches 的方法去构建这个差异的内容

    undo() {
        this.patchLock = true;
        var undoDiff = this.undoList.pop();
        this.setUndo();
        if (undoDiff) {
            this.props.sendPatch(undoDiff);
            editorCommand.applyPatches(undoDiff);
            this.makeRedoDiff();
        }
        this.patchLock = false;
    }
    

所以到这里我们就有一定的猜想了,这里基本就是两个原因导致的。

  1. 在对比变化后的内容与之前脑图的diff的时候错误了,导致applyPatches 的时候就有问题了
  2. diff的计算是没有问题的,但是在 applyPatches 的逻辑处理上是有问题的,但是这块的处理就比较麻烦了,因为 applyPatches 的逻辑处理是在 kityminder-core 中。所以处理起来可能就比较复杂些了。

那我们首先先确认diff的结果是否正确,当我们添加一个标签以后,我们看下diff的内容是怎么样的

在这里插入图片描述

从这个diff内容来看是没有问题,因为我们就是在resource属性中新增一个标签内容,那么undo要做的事情就是将对应的内容给移除掉。

所以我们还是要把目光放到 kityminder-core 中的 applyPatches 中,所以我们去看下这块的逻辑是如何的。

switch (express) {
    case 'theme.replace':
        minder.useTheme(patch.value);
        break;
    case 'template.replace':
        minder.useTemplate(patch.value);
        break;
    case 'node.add':
        insertNode(minder, patch.value, patch.node, patch.index).renderTree();
        minder.layout();
        break;
    case 'node.remove':
        minder.removeNode(patch.node.getChild(patch.index));
        minder.layout();
        break;
    case 'data.add':
    case 'data.replace':
    case 'data.remove':
        var data = patch.node.data;
        var field;
        path = patch.dataPath.slice();
        while (data && path.length > 1) {
            field = path.shift();
            if (field in data) {
                data = data[field];
            } else if (patch.op != 'remove') {
                data = data[field] = {};
            }
        }
				
				// 我们关键看这个地方,这块地方的赋值最后会变成 resource[2] = undefined
        if (data) {
            field = path.shift();
            data[field] = patch.value;
        }
        if (field == 'expandState') {
            node.renderTree();
        } else {
            node.render();
        }
        minder.layout();
}

问题解决

通过以上的逻辑我们就明白了为啥会存在有这样子的问题。所以解决起来就比较简单了。

case 'data.remove':
    var data = patch.node.data;
    var field;
    path = patch.dataPath.slice();
    while (data && path.length > 1) {
        field = path.shift();
        if (field in data) {
            data = data[field];
        } else if (patch.op != 'remove') {
            data = data[field] = {};
        }
    }
    if (data) {
        // 如果是资源的操作, 资源的对象实际上是一个数组的情况
        if (field === 'resource' && express === 'data.remove') {
            field = path.shift();
            data.splice(parseInt(field), 1);
        } else {
            field = path.shift();
            data[field] = patch.value;
        }
        
    }
    if (field == 'expandState') {
        node.renderTree();
    } else {
        node.render();
    }
    minder.layout();

修改成如上的内容即可。针对resource字段的remove做特殊的处理。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值