基于React实现一个todo打勾效果

 更新时间:2024年03月24日 09:20:29   作者:阳树阳树  
这篇文章主要为大家详细介绍了如何基于React实现一个todo打勾效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

正好呢,最近做的一些东西让我燃起了一些些记录的热情,不能再咕咕了。

背景是我自己做的 landing 项目里有一个实现类似飞书里的 todo 的效果,然后我研究了下飞书,写出来了一个 demo。

我们先来提出几个问题,解决了之后,我们也就实现了一个todo

  • 前面的 icon 用什么来实现。
  • 如何实现文字不可点击,前方icon可点击的效果?
  • 如果有多个元素循环渲染的情况下,我们怎么在点击的时候对单个元素做样式的修改?(React)

这里有几个部分需要来讨论:

首先是整个用什么来实现这个前面的 icon,是使用伪元素,还是使用一个真实的元素?

这里我看飞书直接用的伪元素来实现的,感觉可能是能用 css 解决的问题就没有必要再去用 html 去写了,那么大致实现逻辑如下。

 <div class="todo" id="todo">11111</div>

我们使用伪元素实现这个样式的时候,左侧并不会撑开,也就是说,我们需要去给这个 div 一个靠左的 margin 值。然后再去做具体的打勾框。

    .todo {
        pointer-events: none;
        margin-left: 20px;
    }

    .todo:before {
        content: " ";
        display: inline-block;
        line-height: normal;
        font-size: 16px;
        border: 1px solid black;
        border-radius: 4px;
        background-position: 50%;
        white-space: normal;
        width: 16px;
        height: 16px;
        margin-right: 8px;
        margin-left: -24px;
        box-sizing: border-box !important;
        position: relative;
        cursor: pointer;
        pointer-events: auto;
        top: 2px;
    }

那么上面这些代码,就可以得到下图的展示效果:

是不是看起来已经有了完整的样子啦。

这是我们的 todo 状态,我们还需要实现一个 done的状态,所以还需要额外的 css 去书写,这里需要注意的是,为了交互更加好看,我们在 hover 的时候会让伪元素的样式变蓝。于是增加了如下代码,有了下图所示的效果

    .todo:hover:before {
        border: 1px solid rgb(100, 149, 237);
    }

第二个点就是,我们如何实现一个文字不可点击,前方icon可点击的效果呢?

其实在上面的代码中已经展示出来了,为这个 div设置pointer-events: none;,然后给伪元素设置pointer-events: auto;就可以啦。

这些考虑完之后,我再给你们展示一下点击状态的css咋写的:

    .done {
        text-decoration: line-through;
    }

    .done::before {
        background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjU4OSAzLjkwM2wuODA4LjgwOGEuMzUuMzUgMCAwMTAgLjQ5NUw2LjE4IDEwLjQyNWEuMzUuMzUgMCAwMS0uNDk1IDBMMi43MDMgNy40NDRhLjM1LjM1IDAgMDEwLS40OTVsLjgwOC0uODA4YS4zNS4zNSAwIDAxLjQ5NSAwbDEuOTI1IDEuOTI0IDQuMTYzLTQuMTYzYS4zNS4zNSAwIDAxLjQ5NSAweiIgZmlsbD0iIzMzNzBGRiIvPjwvc3ZnPg==);
    }

那么你给这个 div 再加上 done 的类名,就可以得到下图的效果了:

最后呢,如果我们有多个 div,我们如何去做类名的处理呢?

答案是监听点击事件,然后在点击的时候更换类名,代码如下:

    const div = document.getElementById('todo');
    div.addEventListener('click', (target) => {
        const classArr = target.currentTarget.className.split(' ');
        if (classArr.length > 1) {
            target.currentTarget.className = 'todo'
        } else {
            target.currentTarget.className = 'todo done'
        }
    })

完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div class="todo" id="todo">11111</div>
</body>
<script>
    const div = document.getElementById('todo');
    div.addEventListener('click', (target) => {
        const classArr = target.currentTarget.className.split(' ');
        if (classArr.length > 1) {
            target.currentTarget.className = 'todo'
        } else {
            target.currentTarget.className = 'todo done'
        }
    })
</script>
<style>
    .todo {
        margin-left: 20px;
    }

    .todo:before {
        content: " ";
        display: inline-block;
        line-height: normal;
        font-size: 16px;
        border: 1px solid black;
        border-radius: 4px;
        background-position: 50%;
        white-space: normal;
        width: 16px;
        height: 16px;
        margin-right: 8px;
        margin-left: -24px;
        box-sizing: border-box !important;
        position: relative;
        cursor: pointer;
        pointer-events: auto;
        top: 2px;
    }

    .todo:hover:before {
        border: 1px solid rgb(100, 149, 237);
    }

    .done {
        text-decoration: line-through;
    }

    .done::before {
        background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjU4OSAzLjkwM2wuODA4LjgwOGEuMzUuMzUgMCAwMTAgLjQ5NUw2LjE4IDEwLjQyNWEuMzUuMzUgMCAwMS0uNDk1IDBMMi43MDMgNy40NDRhLjM1LjM1IDAgMDEwLS40OTVsLjgwOC0uODA4YS4zNS4zNSAwIDAxLjQ5NSAwbDEuOTI1IDEuOTI0IDQuMTYzLTQuMTYzYS4zNS4zNSAwIDAxLjQ5NSAweiIgZmlsbD0iIzMzNzBGRiIvPjwvc3ZnPg==);
    }
</style>

</html>

到此这篇关于基于React实现一个todo打勾效果的文章就介绍到这了,更多相关React todo打勾内容请搜索程序员之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持程序员之家!

相关文章

  • React Hooks: useEffect()调用了两次问题分析

    React Hooks: useEffect()调用了两次问题分析

    这篇文章主要为大家介绍了React Hooks: useEffect()调用了两次问题分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • React中遍历数组生成标签问题

    React中遍历数组生成标签问题

    这篇文章主要介绍了React中遍历数组生成标签问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • react解析html字符串方法实现

    react解析html字符串方法实现

    在使用reactjs库的时候,会遇到将一段html的字符串,然后要将它插入页面中以html的形式展现,本文主要介绍了react解析html字符串方法实现,感兴趣的可以了解一下
    2023-12-12
  • React中classnames库使用示例

    React中classnames库使用示例

    这篇文章主要为大家介绍了React中classnames库使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • 详解React服务端渲染从入门到精通

    详解React服务端渲染从入门到精通

    这篇文章主要介绍了详解React服务端渲染从入门到精通,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • 使用React-Window实现虚拟滚动效果的示例代码

    使用React-Window实现虚拟滚动效果的示例代码

    React-Window?是一个为?React?应用程序中高效渲染大数据集而设计的库,它基于窗口化或虚拟化的原则运行,本文将使用React-Window实现虚拟滚动效果,感兴趣的可以了解下
    2024-01-01
  • VSCode搭建React Native环境

    VSCode搭建React Native环境

    这篇文章主要介绍了VSCode搭建React Native环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • 解决React报错Rendered more hooks than during the previous render

    解决React报错Rendered more hooks than during

    这篇文章主要为大家介绍了React报错Rendered more hooks than during the previous render解决方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • react+zarm实现底部导航栏的示例代码

    react+zarm实现底部导航栏的示例代码

    本文主要介绍了react?+?zarm?实现底部导航栏的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • 解决react中label标签for报错问题

    解决react中label标签for报错问题

    这篇文章主要介绍了react中label标签for报错问题,解决办法就是react中label标签没有for属性,用htmlFor代替for属性,感兴趣的朋友跟随小编一起看看吧
    2022-02-02

最新评论

?


http://www.vxiaotou.com