我正在研究 React,并且使用来自 @material-ui/core 的 TextField 创建了一个表单。用户将输入文本,它将传递到后端的服务器,然后会出现一个新文本。我可以通过更改 TextField 的值轻松地做到这一点。我的问题是,当我在 TextField 中显示输出时,我希望如图所示突出显示某些字符串。 之前 之后
我可以从后端获取索引和标记,但我没有找到突出显示 TextField 值的一部分的方法。我发现的所有内容都是使用 InputProps 设置整个值的样式。我曾尝试使用此答案和react-highlight-words 包,但我无法使用它们设置值,因为它将返回一个对象,并且显示的值将是 [object object] 而不是部分突出显示的字符串我也尝试过find-substring-in-text-and-change-style-programmatically 并使用 TextField 而不是 Text,但我只想要一个 TextField,而不是每个单词的不同 TextField。我已经在我的代码中添加了我根据这个答案所做的。
这是我的代码的简化版本
索引.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();`
应用程序.js
import React, { Component } from 'react';
import './App.css';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import HomePage from './HomePage';
import 'bootstrap/dist/css/bootstrap.css';
class App extends Component {
render() {
return (
<div className="App">
<>
<Router>
<Switch>
<Route path='/' exact component={HomePage} />
</Switch>
</Router>
</>
</div>
);
}
}
export default App;
主页.js
import React from 'react'
import { TextField, Button } from "@material-ui/core";
const HomePage = () => {
const [value, setValue] = React.useState();
const [indices, setIndices] = React.useState();
const [substrings, setSubstrings] = React.useState();
const handleChange = (event) => {
setValue(event.target.value)
}
const handleChange2 = (event) => {
// What to set?
}
const handleClear = () => {
setValue("")
}
const handleSubmit = () => {
let axios = require('axios')
let data = {
"text": value
}
axios.post('http://127.0.0.1:8000/predict', data)
.then(response => (setValue(response.data.value),
setIndices(response.data.indices),
setSubstrings(response.data.substrings)
))
}
return (
<form noValidate autoComplete="off">
{/*This is the block that I tried from this link https://stackoverflow.com/questions/57808195/react-native-find-substring-in-text-and-change-style-programmatically*/}
{/*
{['red','black','green'].map(item => (
<TextField
InputProps={{
style: {
background: item,
},
}}
value={item}
onChange={handleChange2}
/>
))}
*/}
<TextField
value={value}
rowsMax={15}
InputProps={{
style: {
fontWeight: 500,
},
}}
variant="outlined"
onChange={handleChange}
/>
<Button onClick={handleClear}>Clear</Button>
<Button onClick={handleSubmit}>Submit</Button>
</form>
);
};
export default HomePage;
有没有办法做到这一点?或者更简单的方法,比如将 HTML 代码传递给值?
更新: 我使用原生 contentEditable native 解决了这个问题
正如 Julien Ripet 所建议的那样。这是更新后的 HomePage.js 代码。
import React from 'react'
import {Button } from "@material-ui/core";
const HomePage = () => {
// This handler will listen to the paste event. It will serves as "paste as plain text" to avoid pasting the style.
const handlePaste = (event) => {
// cancel paste
event.preventDefault();
// get text representation of clipboard
var text = (event.originalEvent || event).clipboardData.getData('text/plain');
// insert text manually
document.execCommand("insertText", false, text);
}
// Set the textbox to empty when the clear button is clicked
const handleClear = () => {
var inputText = document.getElementById("textbox");
inputText.innerHTML = "";
}
// Send the text to the server, pass the returned value with its indices to the highlight function to be highlighted and rendered on the same box
const handleSubmit = () => {
// Get the object of the textbox
var inputText = document.getElementById("textbox");
// use innerHTML instead of innerText if you want a string with the html tags
var onlyText = inputText.innerText.trim().replaceAll("\n\n","\n")
// Send data to the server, the response will be (value, indices). Pass it to the highlight function to be highlighted and rendered to the textbox.
/*
let axios = require('axios')
let data = {
"text": onlyText
}
axios.post('http://127.0.0.1:8000/predict', data)
.then(response => (highlight(response.data.value, response.data.indices)))
*/
// Example
var text = "We are trying this text just to see the output";
var indices = [{"start":1, "end":3},{"start":7, "end":8}];
highlight(text, indices)
}
const highlight = (text, indices) => {
// Get the object of the textbox
var inputText = document.getElementById("textbox");
// Split the string to an array of strings for easier processing
text = text.split(" ");
// enclose to be highlighted words with an HTML span of class highlight
for (var i = 0; i < indices.length; i++) {
text[indices[i].start] = "<span class='highlight'>" + text[indices[i].start]
text[indices[i].end -1] = text[indices[i].end -1] + "</span>"
}
// Join the array of strings into one string
var new_text = text.join(' ')
// Update the content of the textbox object with the highlighted text
inputText.innerHTML = new_text;
}
return (
<form noValidate autoComplete="off">
<p
className="textbox"
variant="outlined"
id="textbox"
onPaste={handlePaste} /** Handle the paset event to avoid pasting the style*/
fontWeight = {500}
contentEditable = {true}
></p>
<Button onClick={handleClear}>Clear</Button>
<Button onClick={handleSubmit}>Submit</Button>
</form>
);
};
export default HomePage;
添加到 App.css
.highlight {
background-color: yellow;
}
.textbox {
border: 1px solid #000000;
}
以下是一些对我有帮助的 stackoverflow 问题:
通过execCommand 中的“粘贴为纯文本”的javascript Javascript 技巧从可编辑的 div 中获取文本内容