【问题标题】:Strikethrough a Paragraph in React.js via onClick?通过 onClick 在 React.js 中删除一个段落?
【发布时间】:2019-12-09 07:21:51
【问题描述】:

我已经准备好撕掉我的头发了。所以我在我的 Javascript 课程中的最后一个项目是学习 React.js 的实验性东西,你可以在其中做一个基本的待办事项列表。我完成了所有工作并正常工作,我可以让它正确地添加东西。但我的最后一个障碍是让点击按钮上的打印段落会导致他们为打印的段落提供删除线属性,可以通过再次单击它来撤消它。

我到处查找,我尝试过这里的其他示例,没有我能想到的删除线发生了。我尝试了一个基本的 Javascript 函数,如果这是一个 HTML/非反应文件,它会做我想要的,但是当我尝试将它放入时它会破坏反应页面。所以我花了很长时间在一个试图弄清楚的教程上知道该怎么做,我也许找到了朝着正确方向迈出的一步?但我仍然无法发生任何事情,而且我不知道如何为此建立 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) =&gt; &lt;p key={index}&gt;{item} &lt;/p&gt;) 位的结果添加删除线效果,就像我在普通javascript中使用函数一样。如何通过 onclick 使打印的行删除线,然后如何通过再次单击它来撤消它? (我假设第二次点击)我真的只需要知道如何获得有效的删除线,因为其他一切都非常有效。

【问题讨论】:

  • 你试过 CSS 吗?单击时,添加一个类,例如 task-done,在其中,您可以使用 css 来完成这项工作。对于reference
  • @Rajesh 我确实尝试了一个带有 CSS 的 javascript 函数,假设它可以工作,所以我尝试使用的 CSS 是这样的:`` (function() { document .getElementById("list") .addEventListener("click", function(e) { e.originalTarget.classList.toggle("line"); }); })(); ```然后我会将“line”类添加到css文件中,该文件使用linethrough文本装饰为该类分配任何内容,并将列表值赋予该P标签的另一部分,但我似乎无法得到在页面上工作而不会爆炸的功能。
  • 好吧,我通过添加一个名为 endTask 的 CSS 进行了实验,并将其设置为删除线。我想我必须找到一种方法让它点击我刚刚添加到

    {item}

    行的现在新的“strike”段落 ID 标签.所以我需要找到一种方法来点击任何带有罢工 ID 的内容,导致它被添加到 endTask CSS 并被罢工......这就是障碍
  • @CollegeFox:你只是想删除,还是在删除时需要任何效果?
  • 添加一个新数组,您可以在其中存储所有已完成的任务并将其保存到状态。然后对于每个任务,如果满足条件,则添加一个三元条件(即,该任务在“任务完成”的数组中,然后添加此样式 textDecoration: "line-through";

标签: javascript reactjs strikethrough


【解决方案1】:

按照 cmets 的建议,最舒适的方法之一就是这样做。实现这一点的一个非常快速的方法是切换类列表。在下面的代码中,我添加了一个函数crossLine,它切换类名“crossed-line”并在映射的to-dos 上添加事件侦听器(在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>
        );
    }
}

【讨论】:

  • 这是我的终极救星。它向我展示了它是如何完成的,同时也让我知道如何为未来的项目提供支持。 (如果我最终在这个领域再次获得另一件事)非常感谢!
【解决方案2】:

如评论所述,您必须保持手柄点击并添加类以使用 CSS 添加删除线。

为此,我已将您的 JSX 更新为:

<p onClick={ () => this.handleClick(index) } className={ item.isComplete ? 'completed' : '' } key={index}>{item.value} </p>

以及toDoItem从字符串到对象的签名:

{
    value: string;
    isComplete: boolean
}

基于这个标志,我正在添加类。

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>

【讨论】:

    【解决方案3】:

    看看这个解决方案https://codesandbox.io/s/crazy-kare-go2vf

    我已修改您的代码以实现所需的功能。 此代码完全符合您的要求。

    【讨论】:

    • 只是一个小注释,看classList api并使用.toggle函数。然而,玩 DOM 元素有点错误
    • 感谢您的建议:)。但是,我认为仅出于样式目的操作元素并没有任何缺点。
    • 我不同意。直接更改 DOM 元素会使虚拟 dom 变脏,因为它与 DOM 不同。使用 UI 库的全部目标是以预定义的方式处理 UI 交互。如果您使用 DOM 操作,它首先会超出使用它的目的
    【解决方案4】:

    更新:使用 React Hooks 为现代代码方法创建了一个 TODO fiddler 代码。

    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;
    }
    

    说明:

    基本上,我正在创建一个带有 done 布尔标志的列表,默认情况下为 false,这有助于识别添加到列表中的 TODO 项目是否使用 reducers 完成。使用该逻辑类.done 进行切换。 您可以根据需要更改代码,方法是在设置状态时将 TODO 列表与已完成列表项分开

    这是一个可通过创建 Jest 快照进行单元测试的代码。永远不要直接操作 DOM,这会破坏 React 快照测试的目的。


    旧的fiddle code 使用类组件

    使用它来比较和学习基于类的现代钩子概念。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-22
      • 2014-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-16
      • 2015-12-16
      • 2013-02-22
      相关资源
      最近更新 更多