本地存储与todolist-02

todolist

代码如下,使用的是rem布局,按照375px的设计稿,锻炼一下rem布局的使用
布局结构:

	<div class="main">
        <div class="header">
            <div class="logo">MyTodo</div>
            <input type="text" placeholder="请输入待办事项" id="myInput">
        </div>
        <div class="doing todo">
            <h3><span class="title">正在进行</span><span class="num">0</span></h3>
            <div class="list">

            </div>
        </div>
        <div class="done todo">
            <h3><span class="title">已完成</span><span class="num">0</span></h3>
            <div class="list">

            </div>
        </div>
    </div>

css:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    background-color: #f1f1f1;
    font-size: 16px;
}

.main {
    width: 3.75rem;
}

.header {
    width: 3.75rem;
    height: 0.5rem;
    background-color: aquamarine;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.header>.logo {
    width: 1.2rem;
    height: 0.5rem;
    text-align: center;
    line-height: 0.5rem;
    font-size: 0.25rem;
    font-weight: 900;
}

.header>input {
    width: 2.2rem;
    height: 0.3rem;
    margin: 0 0.2rem;
    border-radius: 0.05rem;
    border: none;
    outline: none;
    padding: 0 0.1rem;
}

.todo h3 {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 0.6rem;
    line-height: 0.6rem;
    padding: 0 0.1rem;
}

.todo .list {
    padding: 0 0.1rem;
}

.todo .todoItem {
    display: flex;
    align-items: center;
    height: 0.38rem;
    margin: 0.05rem 0;
    background-color: rgb(187, 209, 248);
    border-left: 0.03rem solid green;
    border-radius: 0.05rem;
    overflow: hidden;
}

.todo .todoItem>input {
    width: 0.25rem;
    height: 0.25rem;
    margin: 0 0.15rem;
}

.todo .todoItem>.content {
    width: 2.5rem;
}

.todo .todoItem>.delete {
    background-color: rgb(233, 149, 54);
    padding: 0.02rem 0.05rem;
    border-radius: 0.1rem;
    cursor: pointer;
}

.done .todoItem {
    opacity: 0.3;
    /* 利用滤镜 */
    -webkit-filter: grayscale(1);
}

接下来就是比较重要的js代码。
先不考虑本地存储。大体思路就是:所有的事件列表都存放在一个数组中,无论是删除,还是添加,或者已完成事件与未完成时间的切换,都是对该数组中每一个对象或对象的属性进行修改。

添加: 获取输入框内的内容,添加到数组中,重新渲染,清空输入框。
切换: 使用事件代理,监听change事件,通过自定义的data-index属性获取到勾选的是数组中的哪一个对象,并修改其isDone属性值。重新渲染。
删除: 同样使用事件代理,监听click事件,但不是所有的点击都触发,只有当点击了删除按钮那个div才会触发,获取到自定义的data-index通过数组的splice方法删除当前点击的对象,重新渲染。

渲染操作: 清除原来的内容,循环事件数组,判断每个对象的isDone属性值为ture还是false。若为true:说明是已完成事件,添加到已完成事件列表中;若为false,则相反。
基本代码如下:

<script>
        var html = document.querySelector('html');
        var myInput = document.querySelector('#myInput');
        var doingList = document.querySelector('.doing .list');
        var doneList = document.querySelector('.done .list');
        var mainDiv = document.querySelector('.main'); //找到mian这个div,用于删除功能的事件委托
        var todoList = []; //专门用来存储所有事项,包括完成与未完成

        function setRem() {
            var screenWidth = window.innerWidth; //获取屏幕宽
            var rem1 = screenWidth / 3.75; //屏幕的宽度/设计稿占满全屏幕所需的rem数量,就可以得到1rem为多少像素。
            html.style.fontSize = rem1 + 'px';
        };

        //用来将todoList数组中的所有待办事件对象渲染到界面中
        function render() {
            // 每次渲染之前先清除原来的内容
            doingList.innerHTML = '';
            doneList.innerHTML = '';
            //循环所有事件列表,判断是否完成,添加到不同的列表中
            todoList.forEach(function(item, index) {
                var doDiv = document.createElement('div');
                doDiv.className = 'todoItem';
                if (item.isDone) {
                    //已完成事件列表
                    doDiv.innerHTML = `
                        <input type="checkbox" checked data-index="${index}">
                        <div class="content">${item.content}</div>
                        <div class="delete" data-index="${index}">删除</div>
                    `
                    doneList.appendChild(doDiv);
                } else {
                    // 未完成事件列表
                    doDiv.innerHTML = `
                        <input type="checkbox" data-index="${index}">
                        <div class="content">${item.content}</div>
                        <div class="delete" data-index="${index}">删除</div>
                    `
                    doingList.appendChild(doDiv);
                }
            })
        }

        setRem();
        window.onresize = function() {
            setRem();
        };

        //监听输入,输入回车的时候,获取输入框内容并添加到正在进行列表中
        myInput.addEventListener('keyup', function(e) {
            if (e.key == 'Enter') {
                //这个对象用来存储新添加的事项,
                var obj = {
                    content: myInput.value,
                    isDone: false
                };
                todoList.push(obj); //将新的事项添加到数组中
                render();
                myInput.value = '';
            }
        });

        // 使用事件代理,通过在渲染列表时自定义的data-index属性,来获取到当前点击的是第几个事件,也就是获取索引值
        doingList.addEventListener('change', function(e) {
            var index = parseInt(e.target.dataset.index); //获取索引值,因为是字符串,所以需要取整
            todoList[index].isDone = true;
            render();
        });
        doneList.addEventListener('change', function(e) {
            var index = parseInt(e.target.dataset.index); //获取索引值,因为是字符串,所以需要取整
            console.log(index);
            todoList[index].isDone = false;
            render();
        });

        //删除功能
        mainDiv.addEventListener('click', function(e) {
            var index = parseInt(e.target.dataset.index);
            //只有当点击的是删除按钮,也就是删除那个div时,才会进行下一步操作。
            if (e.target.className == 'delete') {
                todoList.splice(index, 1);
                render();
            }
        })
    </script>

接下来考虑本地存储。
其实也不复杂,想要将数据存到本地,只需要在render函数中为localStorage添加一个属性,值为todoList这个数组即可。
但是要注意,本地存储只能存字符串形式,不能存储对象数组,因此需要将其转化为json字符串,取出时也是同样的道理,做相反操作。
最后再加上数值的控制逻辑,完整的代码如下:

<script>
        var html = document.querySelector('html');
        var myInput = document.querySelector('#myInput');
        var doingList = document.querySelector('.doing .list');
        var doneList = document.querySelector('.done .list');
        var doingNum = document.querySelector('.doing .num');
        var doneNum = document.querySelector('.done .num');
        var mainDiv = document.querySelector('.main'); //找到mian这个div,用于删除功能的事件委托

        //判断本地存储中是否已经存在数据
        if (localStorage.todoList == undefined) {
            var todoList = []; //专门用来存储所有事项,包括完成与未完成
        } else {
            var todoList = JSON.parse(localStorage.todoList); //将json字符串转换为对象
            render();
        }


        function setRem() {
            var screenWidth = window.innerWidth; //获取屏幕宽
            var rem1 = screenWidth / 3.75; //屏幕的宽度/设计稿占满全屏幕所需的rem数量,就可以得到1rem为多少像素。
            html.style.fontSize = rem1 + 'px';
        };

        //用来将todoList数组中的所有待办事件对象渲染到界面中
        function render() {

            //将事件列表放到本地存储中,因为本次存储只能存储字符串,因此json可以很好的解决这个问题
            localStorage.todoList = JSON.stringify(todoList); //将json对象转化为字符串

            // 每次渲染之前先清除原来的内容
            doingList.innerHTML = '';
            doneList.innerHTML = '';
            doingNum.innerHTML = 0;
            doneNum.innerHTML = 0;
            
            //循环所有事件列表,判断是否完成,添加到不同的列表中
            todoList.forEach(function(item, index) {
                var doDiv = document.createElement('div');
                doDiv.className = 'todoItem';
                if (item.isDone) {
                    //已完成事件列表
                    doDiv.innerHTML = `
                        <input type="checkbox" checked data-index="${index}">
                        <div class="content">${item.content}</div>
                        <div class="delete" data-index="${index}">删除</div>
                    `
                    doneList.appendChild(doDiv);
                    doneNum.innerHTML = parseInt(doneNum.innerHTML) + 1;
                } else {
                    // 未完成事件列表
                    doDiv.innerHTML = `
                        <input type="checkbox" data-index="${index}">
                        <div class="content">${item.content}</div>
                        <div class="delete" data-index="${index}">删除</div>
                    `
                    doingList.appendChild(doDiv);
                    doingNum.innerHTML = parseInt(doingNum.innerHTML) + 1;
                }
            })
        }

        setRem();
        window.onresize = function() {
            setRem();
        };

        //监听输入,输入回车的时候,获取输入框内容并添加到正在进行列表中
        myInput.addEventListener('keyup', function(e) {
            if (e.key == 'Enter') {
                //这个对象用来存储新添加的事项,
                var obj = {
                    content: myInput.value,
                    isDone: false
                };
                todoList.push(obj); //将新的事项添加到数组中
                render();
                myInput.value = '';
            }
        });

        // 使用事件代理,通过在渲染列表时自定义的data-index属性,来获取到当前点击的是第几个事件,也就是获取索引值
        doingList.addEventListener('change', function(e) {
            var index = parseInt(e.target.dataset.index); //获取索引值,因为是字符串,所以需要取整
            todoList[index].isDone = true;
            render();
        });
        doneList.addEventListener('change', function(e) {
            var index = parseInt(e.target.dataset.index); //获取索引值,因为是字符串,所以需要取整
            console.log(index);
            todoList[index].isDone = false;
            render();
        });

        //删除功能
        mainDiv.addEventListener('click', function(e) {
            var index = parseInt(e.target.dataset.index);
            //只有当点击的是删除按钮,也就是删除那个div时,才会进行下一步操作。
            if (e.target.className == 'delete') {
                todoList.splice(index, 1);
                render();
            }
        })
    </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值