基于React實現(xiàn)一個todo打勾效果
正好呢,最近做的一些東西讓我燃起了一些些記錄的熱情,不能再咕咕了。
背景是我自己做的 landing 項目里有一個實現(xiàn)類似飛書里的 todo 的效果,然后我研究了下飛書,寫出來了一個 demo。
我們先來提出幾個問題,解決了之后,我們也就實現(xiàn)了一個todo
- 前面的
icon用什么來實現(xiàn)。 - 如何實現(xiàn)文字不可點擊,前方
icon可點擊的效果? - 如果有多個元素循環(huán)渲染的情況下,我們怎么在點擊的時候?qū)蝹€元素做樣式的修改?(React)
這里有幾個部分需要來討論:
首先是整個用什么來實現(xiàn)這個前面的 icon,是使用偽元素,還是使用一個真實的元素?
這里我看飛書直接用的偽元素來實現(xiàn)的,感覺可能是能用 css 解決的問題就沒有必要再去用 html 去寫了,那么大致實現(xiàn)邏輯如下。
<div class="todo" id="todo">11111</div>
我們使用偽元素實現(xiàn)這個樣式的時候,左側(cè)并不會撐開,也就是說,我們需要去給這個 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;
}
那么上面這些代碼,就可以得到下圖的展示效果:

是不是看起來已經(jīng)有了完整的樣子啦。
這是我們的 todo 狀態(tài),我們還需要實現(xiàn)一個 done的狀態(tài),所以還需要額外的 css 去書寫,這里需要注意的是,為了交互更加好看,我們在 hover 的時候會讓偽元素的樣式變藍。于是增加了如下代碼,有了下圖所示的效果
.todo:hover:before {
border: 1px solid rgb(100, 149, 237);
}
第二個點就是,我們?nèi)绾螌崿F(xiàn)一個文字不可點擊,前方icon可點擊的效果呢?
其實在上面的代碼中已經(jīng)展示出來了,為這個 div設(shè)置pointer-events: none;,然后給偽元素設(shè)置pointer-events: auto;就可以啦。
這些考慮完之后,我再給你們展示一下點擊狀態(tài)的css咋寫的:
.done {
text-decoration: line-through;
}
.done::before {
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjU4OSAzLjkwM2wuODA4LjgwOGEuMzUuMzUgMCAwMTAgLjQ5NUw2LjE4IDEwLjQyNWEuMzUuMzUgMCAwMS0uNDk1IDBMMi43MDMgNy40NDRhLjM1LjM1IDAgMDEwLS40OTVsLjgwOC0uODA4YS4zNS4zNSAwIDAxLjQ5NSAwbDEuOTI1IDEuOTI0IDQuMTYzLTQuMTYzYS4zNS4zNSAwIDAxLjQ5NSAweiIgZmlsbD0iIzMzNzBGRiIvPjwvc3ZnPg==);
}
那么你給這個 div 再加上 done 的類名,就可以得到下圖的效果了:

最后呢,如果我們有多個 div,我們?nèi)绾稳プ鲱惷奶幚砟兀?/p>
答案是監(jiān)聽點擊事件,然后在點擊的時候更換類名,代碼如下:
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>
到此這篇關(guān)于基于React實現(xiàn)一個todo打勾效果的文章就介紹到這了,更多相關(guān)React todo打勾內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React工作流程及Error Boundaries實現(xiàn)過程講解
這篇文章主要介紹了React工作流程及Error Boundaries實現(xiàn)過程講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-02-02
React?Native集成支付寶支付的實現(xiàn)方法
這篇文章主要介紹了React?Native集成支付寶支付的實現(xiàn)現(xiàn),ativeModules是JS代碼調(diào)用原生模塊的橋梁。所以,我們只需要在原生工程中集成支付寶和微信支付的sdk,然后使用NativeModules調(diào)用即可,需要的朋友可以參考下2022-02-02
解決React報錯You provided a `checked` prop&n
這篇文章主要為大家介紹了React報錯You provided a `checked` prop to a form field的解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12

