为什么点进去innerHTML就覆盖不了

Why can I not overwrite the innerHTML after I once clicked into it

我的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Real Time Texteditor</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap');

        body{
            background-color: white; 
            margin: 25px;
        }

        h1{
            margin-bottom: 0px;
            color: black; 
            align-content: center; 
            font-family: 'Roboto Mono', monospace;
        }

        #ErrorParag{
            margin-top: 0px;
            font-family: 'Roboto Mono', monospace;
        }

        #textarea{
            width: 100%; 
            height: 90vh; 
            color: black; 
            font-size:20px; 

            border: 5px solid;
            border-radius: 5px;
        } 
    </style>
    <script>
        const params = new Proxy(new URLSearchParams(window.location.search), {
            get: (searchParams, prop) => searchParams.get(prop),
        })
        const ID = params.id
        const NAME = params.name
        //console.log(String(ID)+" "+String(NAME))

        const xhr =  new XMLHttpRequest();

        last_input = ""
        

        window.onload = function(){
            xhr.open('POST', '/api/retrieve', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(JSON.stringify({"id":ID, "name":NAME}));
            response = JSON.parse(xhr.responseText);
            //console.log(response);
            if(response.status==="error"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                document.getElementById("textarea").innerHTML = response.data
            }
        }

        function compareString(x, y){ //x = originally, y = new => 
            if(x.length>y.length){ //smaller String => char was deleted x>y
                for(let i = 0; i<x.length; i++){
                    //console.log(String(x)+" "+String(y[i])+" --- "+String(x.length)+" "+String(i)) //kleiner Bug bei der Darstellung wird der gesamte Text angezeigt
                    if(x[i]!==y[i]){
                        return {"pos":String(i),"change":String(-1),"char":String(x[i])}
                    }
                    else if(i===x.length-1){
                        return {"pos":String(i+1),"change":String(-1),"char":String(x[x.length])}
                    }
                }
                
            }
            else if(x.length<y.length){ //bigger String => char was added x<y
                for(let i = 0; i<y.length; i++){
                    //console.log(String(x[i])+" "+String(y[i])+" --- "+String(y.length)+" "+String(i))
                    if(x[i]!==y[i]){
                        return {"pos":String(i),"change":String(1),"char":String(y[i])}
                    }
                    else if(i===y.length-1){
                        return {"pos":String(i+1),"change":String(1),"char":String(y[y.length])}
                    }
                }
            }
            return {"Error":"Something went completely wrong"} 
        }

        function onTextUpdate(e){
            let results = compareString(last_input, e.value)
            //console.log(results)
            globalThis.last_input = e.value;

            send_data = JSON.stringify({"update":results, "id":ID, "name":NAME}) // {"update":{"pos": ..., "change": ..., "char": ...}, "id": ... , "name": ... }
            //console.log("Data which is gonna be send:")
            console.log(send_data)
            
            //post the results to back end
            xhr.open('POST', '/api/update', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(send_data);
            response = JSON.parse(xhr.responseText);
            console.log(response);
            if(response.status==="failure"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                document.getElementById("ErrorParag").innerHTML = "success"
                document.getElementById("ErrorParag").style.color = "#00ff00";
            }
        }
        
        const loadData = function(){
            console.log("get data from server")
            xhr.open('POST', '/api/retrieve', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(JSON.stringify({"id":ID, "name":NAME}));
            response = JSON.parse(xhr.responseText);
            console.log(response.data);
            
            if(response.status==="error"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                console.log("success!")
                document.getElementById("textarea").innerHTML = response.data
            }
        }

        const load_data = setInterval(loadData, 1000)
    
    </script>
</head>
<body>
    <h1>Real Time Texteditor</h1>
    <p id="ErrorParag"></p>
    <textarea id="textarea" placeholder="Just write ..." oninput="onTextUpdate(this)"></textarea>
</body>
</html>

您可能已经读到,该代码适用于我正在与朋友合作的实时文本编辑器项目。但我不明白为什么一切都很好,直到我点击文本字段并想写点东西。服务器获取所有内容,另一个实例也获取。唯一的问题是,第二个实例不会覆盖文本字段的 innerHTML。如果我重新加载第二个实例,所有内容都会出现在文本字段中。我很困惑。有谁知道为什么会这样?

首先,你不应该设置一个间隔来每秒加载数据,因为在普通的文本编辑器中,每次文本区域的改变时你都加载数据。当设置间隔以每秒加载数据时,您实际上是在无缘无故地向用户和服务器发送垃圾邮件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Real Time Texteditor</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap');

        body{
            background-color: white; 
            margin: 25px;
        }

        h1{
            margin-bottom: 0px;
            color: black; 
            align-content: center; 
            font-family: 'Roboto Mono', monospace;
        }

        #ErrorParag{
            margin-top: 0px;
            font-family: 'Roboto Mono', monospace;
        }

        #textarea{
            width: 100%; 
            height: 90vh; 
            color: black; 
            font-size:20px; 

            border: 5px solid;
            border-radius: 5px;
        } 
    </style>
    <script>
        const params = new Proxy(new URLSearchParams(window.location.search), {
            get: (searchParams, prop) => searchParams.get(prop),
        })
        const ID = params.id
        const NAME = params.name
        //console.log(String(ID)+" "+String(NAME))

        const xhr =  new XMLHttpRequest();

        last_input = ""
        

        window.onload = function(){
            xhr.open('POST', '/api/retrieve', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(JSON.stringify({"id":ID, "name":NAME}));
            response = JSON.parse(xhr.responseText);
            //console.log(response);
            if(response.status==="error"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                document.getElementById("textarea").innerHTML = response.data
            }
        }

        function compareString(x, y){ //x = originally, y = new => 
            if(x.length>y.length){ //smaller String => char was deleted x>y
                for(let i = 0; i<x.length; i++){
                    //console.log(String(x)+" "+String(y[i])+" --- "+String(x.length)+" "+String(i)) //kleiner Bug bei der Darstellung wird der gesamte Text angezeigt
                    if(x[i]!==y[i]){
                        return {"pos":String(i),"change":String(-1),"char":String(x[i])}
                    }
                    else if(i===x.length-1){
                        return {"pos":String(i+1),"change":String(-1),"char":String(x[x.length])}
                    }
                }
                
            }
            else if(x.length<y.length){ //bigger String => char was added x<y
                for(let i = 0; i<y.length; i++){
                    //console.log(String(x[i])+" "+String(y[i])+" --- "+String(y.length)+" "+String(i))
                    if(x[i]!==y[i]){
                        return {"pos":String(i),"change":String(1),"char":String(y[i])}
                    }
                    else if(i===y.length-1){
                        return {"pos":String(i+1),"change":String(1),"char":String(y[y.length])}
                    }
                }
            }
            return {"Error":"Something went completely wrong"} 
        }

        function onTextUpdate(e){
            let results = compareString(last_input, e.value)
            //console.log(results)
            globalThis.last_input = e.value;

            send_data = JSON.stringify({"update":results, "id":ID, "name":NAME}) // {"update":{"pos": ..., "change": ..., "char": ...}, "id": ... , "name": ... }
            //console.log("Data which is gonna be send:")
            console.log(send_data)
            
            //post the results to back end
            xhr.open('POST', '/api/update', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(send_data);
            response = JSON.parse(xhr.responseText);
            console.log(response);
            if(response.status==="failure"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                document.getElementById("ErrorParag").innerHTML = "success"
                document.getElementById("ErrorParag").style.color = "#00ff00";
            }
            console.log("get data from server")
            xhr.open('POST', '/api/retrieve', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(JSON.stringify({"id":ID, "name":NAME}));
            response = JSON.parse(xhr.responseText);
            console.log(response.data);
            
            if(response.status==="error"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                console.log("success!")
                document.getElementById("textarea").value = response.data
            }
        }

        
    
    </script>
</head>
<body>
    <h1>Real Time Texteditor</h1>
    <p id="ErrorParag"></p>
    <textarea id="textarea" placeholder="Just write ..." oninput="onTextUpdate(this)"></textarea>
</body>
</html>

我所做的更改是将 load_data 函数与 onTextUpdate 函数组合在一起,并将 document.getElementById("textarea").innerHTML = response.data 更改为 document.getElementById("textarea").value = response.data,因为正如 Teemu 在评论中解释的那样:textarea 不能包含 HTML,它只包含纯文本。使用 value 而不是 innerHTML.