通过 onClick 删除 React.js 中的段落?
Strikethrough a Paragraph in React.js via onClick?
我已经准备好撕掉头发了。所以我在 Javascript class 中的最终项目是学习 React.js 的实验性项目,您可以在其中列一个基本的待办事项列表。我完成了所有工作并开始工作,我可以让它正确地添加东西。但我的最后一个障碍是让点击按钮上的打印段落会导致他们给打印的段落添加删除线 属性,可以通过再次点击它来撤消。
我到处都看过,我试过这里的其他例子,没有我能想到的是删除线发生。我尝试了一个基本的 Javascript 函数,如果这是一个 HTML/non-react 文件,它会做我想做的事,但是当我试图把它放进去时它会破坏反应页面。所以我花了很长时间在一个教程试图弄清楚该怎么做,我也许想出了正确方向的步骤?但我仍然无法让任何事情发生,我不知道如何为此建立一个 onclick。
import React from 'react';
import './App.css';
class App extends React.Component {
setCurrentToDoItem = (toDoItem) => {
console.log("toDoItem", toDoItem);
this.setState({
currentToDoItem: toDoItem
});
};
saveToDoListItem = (toDoItem) => {
this.setState({
toDoList: [...this.state.toDoList,
toDoItem]
});
};
constructor(props) {
super(props);
this.state = {
currentToDoItem: null,
toDoList: [],
strikeThrough: []
};
}
render() {
return (
<div>
<h1>To Do List</h1>
<label>To Do Item: </label>
<input
onChange={(event) => this.setCurrentToDoItem(event.target.value)}>
</input>
<button onClick={() => this.saveToDoListItem(this.state.currentToDoItem)}>
<p>Add Item</p>
</button>
<p>{this.state.currentToDoItem}</p>
<div>
<p>To Do Items</p>
{
this.state.toDoList.map((item, index) => <p key={index}>{item} </p>)
}
</div>
</div>
);
}
}
export default App;
这是我的 App.js 代码。如您所见,其他一切都应该工作正常,但我不知道如何向 this.state.toDoList.map((item, index) => <p key={index}>{item} </p>)
位的结果添加删除线效果,就像我在正常 javascript 中使用函数一样。如何通过 onclick 使打印的线条成为删除线,然后如何通过再次单击取消删除线? (我假设有第二次点击)我真的只需要知道如何通过这个获得一个有效的删除线,因为其他一切都非常有效。
查看此解决方案https://codesandbox.io/s/crazy-kare-go2vf
我已经修改了您的代码以实现所需的功能。
此代码完全符合您的要求。
最舒适的方法之一就是按照评论中的建议进行操作。一个真正快速的实现方法是切换 class 列表。在下面的代码中,我添加了一个函数 crossLine
来切换 class 名称 "crossed-line" 并在映射的待办事项上添加事件侦听器(在 render
函数中)。然后在你的 App.css
添加一行
.crossed-line {
text-decoration: line-through;
}
这是您编辑的组件代码。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentToDoItem: null,
toDoList: [],
strikeThrough: []
};
}
setCurrentToDoItem = toDoItem => {
this.setState({
currentToDoItem: toDoItem
});
};
saveToDoListItem = toDoItem => {
this.setState({
toDoList: [...this.state.toDoList, toDoItem]
});
};
crossLine = event => {
const element = event.target;
element.classList.toggle("crossed-line");
};
render() {
return (
<div>
<h1>To Do List</h1>
<label>To Do Item: </label>
<input
onChange={event =>
this.setCurrentToDoItem(event.target.value)
}
/>
<button
onClick={() =>
this.saveToDoListItem(this.state.currentToDoItem)
}
>
<p>Add Item</p>
</button>
<p>{this.state.currentToDoItem}</p>
<div>
<p>To Do Items</p>
{this.state.toDoList.map((item, index) => {
return (
<p onClick={this.crossLine} key={index}>
{item}{" "}
</p>
);
})}
</div>
</div>
);
}
}
如评论所述,您必须按住句柄单击并添加 class 以使用 CSS 添加删除线。
为此,我已将您的 JSX 更新为:
<p onClick={ () => this.handleClick(index) } className={ item.isComplete ? 'completed' : '' } key={index}>{item.value} </p>
和 toDoItem
从字符串到对象的签名:
{
value: string;
isComplete: boolean
}
基于这个标志,我添加了 class。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentToDoItem: null,
toDoList: [],
strikeThrough: []
};
this.setCurrentToDoItem = this.setCurrentToDoItem.bind(this);
this.saveToDoListItem = this.saveToDoListItem.bind(this);
this.handleClick = this.handleClick.bind(this);
}
setCurrentToDoItem(toDoItem) {
this.setState({
currentToDoItem: toDoItem
});
}
saveToDoListItem(toDoItem) {
this.setState({
toDoList: [...this.state.toDoList, {
value: toDoItem,
isComplete: false
}]
});
}
handleClick(index) {
const {
toDoList
} = this.state;
toDoList[index].isComplete = !toDoList[index].isComplete;
this.setState({
toDoList
});
}
render() {
return (
<div>
<h1>To Do List</h1>
<label>To Do Item: </label>
<input
onChange={(event) => this.setCurrentToDoItem(event.target.value)}>
</input>
<button onClick={() => this.saveToDoListItem(this.state.currentToDoItem)}>
<p>Add Item</p>
</button>
<p>{this.state.currentToDoItem}</p>
<div>
<p>To Do Items</p>
{
this.state.toDoList.map((item, index) =>
<p onClick={ () => this.handleClick(index) } className={ item.isComplete ? 'completed' : '' } key={index}>{item.value} </p>)
}
</div>
</div>
);
}
}
ReactDOM.render( < App / > , document.querySelector("#app"))
body {
background: #20262E;
padding: 20px;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
.completed {
text-decoration: line-through;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
更新:为现代代码方法创建了 TODO fiddler code using React Hooks。
const initialState = {
items: [
{ text: "Learn JavaScript", done: false },
{ text: "Learn React", done: false },
{ text: "Play around in JSFiddle", done: true },
{ text: "Build something awesome", done: true }
]
};
function appReducer(state, action) {
switch (action.type) {
case 'ITEM_STATUS_CHANGE':{
let affected = state.items.slice();
affected[action.index].done = !affected[action.index].done;
return Object.assign({}, state, { items: affected });
}
case 'ADD_ITEM_TO_LIST':{
let affected = state.items.slice();
affected.push({ text: action.data, done : false})
return Object.assign({}, state, { items: affected });
}
default:
throw new Error();
}
}
function TodoApp(props){
const [state, dispatch] = React.useReducer(appReducer, initialState);
return (
<div>
<h2>Todos:
<input type="text" id="todoTextItem"/>
<button
onClick={()=>{
dispatch({
type: 'ADD_ITEM_TO_LIST',
data: window.todoTextItem.value
})
}}
>Add Item</button>
</h2>
<ol>
{state.items.map((item, index) => (
<li key={index}>
<label>
<input
type="checkbox"
checked={item.done}
onChange={()=>{
dispatch({
type: 'ITEM_STATUS_CHANGE',
index: index,
})
}}
/>
<span className={item.done ? "done" : ""}>{item.text}</span>
</label>
</li>
))}
</ol>
</div>
);
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
并在 CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.done {
color: rgba(0, 0, 0, 0.3);
text-decoration: line-through;
}
input {
margin-right: 5px;
}
解释:
基本上我正在创建一个带有完成布尔标志的列表,默认情况下为 false
,这有助于确定添加到列表中的 TODO 项目是否已完成或未使用 reducers
。使用该逻辑 class .done
被切换。 您可以根据需要更改代码,在设置状态时将 TODO 列表与已完成列表项分开
This is a Unit testable code by creating Jest snapshot. Never to manipulate DOM directly, which will defeat the purpose of React's snapshot testing.
旧 fiddle code 使用 Class 组件.
使用它来比较和学习基于 class 的现代钩子概念。
我已经准备好撕掉头发了。所以我在 Javascript class 中的最终项目是学习 React.js 的实验性项目,您可以在其中列一个基本的待办事项列表。我完成了所有工作并开始工作,我可以让它正确地添加东西。但我的最后一个障碍是让点击按钮上的打印段落会导致他们给打印的段落添加删除线 属性,可以通过再次点击它来撤消。
我到处都看过,我试过这里的其他例子,没有我能想到的是删除线发生。我尝试了一个基本的 Javascript 函数,如果这是一个 HTML/non-react 文件,它会做我想做的事,但是当我试图把它放进去时它会破坏反应页面。所以我花了很长时间在一个教程试图弄清楚该怎么做,我也许想出了正确方向的步骤?但我仍然无法让任何事情发生,我不知道如何为此建立一个 onclick。
import React from 'react';
import './App.css';
class App extends React.Component {
setCurrentToDoItem = (toDoItem) => {
console.log("toDoItem", toDoItem);
this.setState({
currentToDoItem: toDoItem
});
};
saveToDoListItem = (toDoItem) => {
this.setState({
toDoList: [...this.state.toDoList,
toDoItem]
});
};
constructor(props) {
super(props);
this.state = {
currentToDoItem: null,
toDoList: [],
strikeThrough: []
};
}
render() {
return (
<div>
<h1>To Do List</h1>
<label>To Do Item: </label>
<input
onChange={(event) => this.setCurrentToDoItem(event.target.value)}>
</input>
<button onClick={() => this.saveToDoListItem(this.state.currentToDoItem)}>
<p>Add Item</p>
</button>
<p>{this.state.currentToDoItem}</p>
<div>
<p>To Do Items</p>
{
this.state.toDoList.map((item, index) => <p key={index}>{item} </p>)
}
</div>
</div>
);
}
}
export default App;
这是我的 App.js 代码。如您所见,其他一切都应该工作正常,但我不知道如何向 this.state.toDoList.map((item, index) => <p key={index}>{item} </p>)
位的结果添加删除线效果,就像我在正常 javascript 中使用函数一样。如何通过 onclick 使打印的线条成为删除线,然后如何通过再次单击取消删除线? (我假设有第二次点击)我真的只需要知道如何通过这个获得一个有效的删除线,因为其他一切都非常有效。
查看此解决方案https://codesandbox.io/s/crazy-kare-go2vf
我已经修改了您的代码以实现所需的功能。 此代码完全符合您的要求。
最舒适的方法之一就是按照评论中的建议进行操作。一个真正快速的实现方法是切换 class 列表。在下面的代码中,我添加了一个函数 crossLine
来切换 class 名称 "crossed-line" 并在映射的待办事项上添加事件侦听器(在 render
函数中)。然后在你的 App.css
添加一行
.crossed-line {
text-decoration: line-through;
}
这是您编辑的组件代码。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentToDoItem: null,
toDoList: [],
strikeThrough: []
};
}
setCurrentToDoItem = toDoItem => {
this.setState({
currentToDoItem: toDoItem
});
};
saveToDoListItem = toDoItem => {
this.setState({
toDoList: [...this.state.toDoList, toDoItem]
});
};
crossLine = event => {
const element = event.target;
element.classList.toggle("crossed-line");
};
render() {
return (
<div>
<h1>To Do List</h1>
<label>To Do Item: </label>
<input
onChange={event =>
this.setCurrentToDoItem(event.target.value)
}
/>
<button
onClick={() =>
this.saveToDoListItem(this.state.currentToDoItem)
}
>
<p>Add Item</p>
</button>
<p>{this.state.currentToDoItem}</p>
<div>
<p>To Do Items</p>
{this.state.toDoList.map((item, index) => {
return (
<p onClick={this.crossLine} key={index}>
{item}{" "}
</p>
);
})}
</div>
</div>
);
}
}
如评论所述,您必须按住句柄单击并添加 class 以使用 CSS 添加删除线。
为此,我已将您的 JSX 更新为:
<p onClick={ () => this.handleClick(index) } className={ item.isComplete ? 'completed' : '' } key={index}>{item.value} </p>
和 toDoItem
从字符串到对象的签名:
{
value: string;
isComplete: boolean
}
基于这个标志,我添加了 class。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentToDoItem: null,
toDoList: [],
strikeThrough: []
};
this.setCurrentToDoItem = this.setCurrentToDoItem.bind(this);
this.saveToDoListItem = this.saveToDoListItem.bind(this);
this.handleClick = this.handleClick.bind(this);
}
setCurrentToDoItem(toDoItem) {
this.setState({
currentToDoItem: toDoItem
});
}
saveToDoListItem(toDoItem) {
this.setState({
toDoList: [...this.state.toDoList, {
value: toDoItem,
isComplete: false
}]
});
}
handleClick(index) {
const {
toDoList
} = this.state;
toDoList[index].isComplete = !toDoList[index].isComplete;
this.setState({
toDoList
});
}
render() {
return (
<div>
<h1>To Do List</h1>
<label>To Do Item: </label>
<input
onChange={(event) => this.setCurrentToDoItem(event.target.value)}>
</input>
<button onClick={() => this.saveToDoListItem(this.state.currentToDoItem)}>
<p>Add Item</p>
</button>
<p>{this.state.currentToDoItem}</p>
<div>
<p>To Do Items</p>
{
this.state.toDoList.map((item, index) =>
<p onClick={ () => this.handleClick(index) } className={ item.isComplete ? 'completed' : '' } key={index}>{item.value} </p>)
}
</div>
</div>
);
}
}
ReactDOM.render( < App / > , document.querySelector("#app"))
body {
background: #20262E;
padding: 20px;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
.completed {
text-decoration: line-through;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
更新:为现代代码方法创建了 TODO fiddler code using React Hooks。
const initialState = {
items: [
{ text: "Learn JavaScript", done: false },
{ text: "Learn React", done: false },
{ text: "Play around in JSFiddle", done: true },
{ text: "Build something awesome", done: true }
]
};
function appReducer(state, action) {
switch (action.type) {
case 'ITEM_STATUS_CHANGE':{
let affected = state.items.slice();
affected[action.index].done = !affected[action.index].done;
return Object.assign({}, state, { items: affected });
}
case 'ADD_ITEM_TO_LIST':{
let affected = state.items.slice();
affected.push({ text: action.data, done : false})
return Object.assign({}, state, { items: affected });
}
default:
throw new Error();
}
}
function TodoApp(props){
const [state, dispatch] = React.useReducer(appReducer, initialState);
return (
<div>
<h2>Todos:
<input type="text" id="todoTextItem"/>
<button
onClick={()=>{
dispatch({
type: 'ADD_ITEM_TO_LIST',
data: window.todoTextItem.value
})
}}
>Add Item</button>
</h2>
<ol>
{state.items.map((item, index) => (
<li key={index}>
<label>
<input
type="checkbox"
checked={item.done}
onChange={()=>{
dispatch({
type: 'ITEM_STATUS_CHANGE',
index: index,
})
}}
/>
<span className={item.done ? "done" : ""}>{item.text}</span>
</label>
</li>
))}
</ol>
</div>
);
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
并在 CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.done {
color: rgba(0, 0, 0, 0.3);
text-decoration: line-through;
}
input {
margin-right: 5px;
}
解释:
基本上我正在创建一个带有完成布尔标志的列表,默认情况下为 false
,这有助于确定添加到列表中的 TODO 项目是否已完成或未使用 reducers
。使用该逻辑 class .done
被切换。 您可以根据需要更改代码,在设置状态时将 TODO 列表与已完成列表项分开
This is a Unit testable code by creating Jest snapshot. Never to manipulate DOM directly, which will defeat the purpose of React's snapshot testing.
旧 fiddle code 使用 Class 组件.
使用它来比较和学习基于 class 的现代钩子概念。