首先看一个实例!

react-code-editor
如下代码:

.stage {
  border: 1px dashed #333;
  padding: 10px;  
}

CodeEditor

Section / Range

<div class="stage">
    <pre id="dom-editable" contenteditable="true">Input Here.
Second Line.
</pre>
    <button id="btn-1">Select Second line</button>
</div>

<script type="text/javascript">
    function selectionHelper(el, pos) {
        var indexes = {}
        // getSelection
        if (typeof pos === 'undefined') {
            var selection = window.getSelection()
            var range = selection.getRangeAt(0);
            var clone = range.cloneRange();

            clone.selectNodeContents(el);
            clone.setEnd(range.endContainer, range.endOffset);
            indexes.end = clone.toString().length;
            clone.setStart(range.startContainer, range.startOffset);
            indexes.start = indexes.end - clone.toString().length;
            indexes.atStart = clone.startOffset === 0;
            indexes.commonAncestorContainer = clone.commonAncestorContainer;
            indexes.endContainer = clone.endContainer;
            indexes.startContainer = clone.startContainer;

            return indexes;
        }

        var setSelection = pos.end && pos.end !== pos.start;
        var length = 0;
        var range = document.createRange();
        var next;
        var startindex;
        var start = pos.start > el.textContent.length ? el.textContent.length : pos.start;
        var end = pos.end > el.textContent.length ? el.textContent.length : pos.end;
        var atStart = pos.atStart;


        for (var i = 0; i < el.childNodes.length; i++) {
            next = el.childNodes[i]
            if (next.nodeType === Node.TEXT_NODE) {
                var olen = length;
                length += next.textContent.length;

                // Set start point of selection
                var atLength = atStart ? length > start : length >= start;
                if (!startindex && atLength) {
                    startindex = true;
                    range.setStart(next, start - olen);
                    if (!setSelection) {
                        range.collapse(true);
                        makeSelection(el, range);
                        break;
                    }
                }

                // Set end point of selection
                if (setSelection && length >= end) {
                    range.setEnd(next, end - olen);
                    makeSelection(el, range);
                    break;
                }
            }
        }

        function makeSelection(el, range) {
            var selection = window.getSelection();
            el.focus();
            selection.removeAllRanges();
            selection.addRange(range);
        }
    }

    var dom = document.getElementById('dom-editable');
    dom.addEventListener('keyup', function (evt) {
        console.log(selectionHelper(dom))
    });

    dom.addEventListener('keydown', function (evt) {
        if (evt.keyCode === 13) {
            document.execCommand('insertHTML', false, '\n');
            evt.preventDefault()
        }
    });

    document.getElementById('btn-1').addEventListener('click', function (evt) {
        var lines = dom.textContent.split('\n')
        if (lines.length < 2) return
        var start = 0, end = 0;
        start += lines[0].length + 1
        end += start + lines[1].length
        console.log(start, end)
        selectionHelper(dom, {start: start, end: end})
    });
</script>
Input Here.
Second Line.