zoukankan      html  css  js  c++  java
  • js的TodoList组件开发

    js的TodoList组件开发

    需求:

    1.页面中头部有输入框,下面有待办的内容块,和办完的内容块
    2.输入框中输入内容,回车键后,输入框内容清空,代办内容块中添加一条输入内容
    3.代办条中有选择框,内容区,删除按钮
    4.点击代办条中选择框,说明内容转变为办完事项,代办块中这条内容消失,办完块中有这条语句
    5.办完块中点击选择框后,这条内容消失,出现在代办块中
    6.本地存储功能,重新打开页面后,之前的事项依旧存在

    效果图:

    • 初始页面:

    • 输入框有内容,回车后

    • 点击内容条中选择框

    • 点击办完中内容条中的选择框

    分析:

    • 两个js文件,List是内容条组件,等待数据传入,todoList是外部操作组件,操作后传入数据到List中,List开始执行
    • List中的内容条设置点击事件,抛发出事件,在todoList的外部操作中执行.
    • 每个页面创建时,要判断localStorage中有无存储的数据,如果有,这些数据直接传入List中,当输入框中输入内容,或者内容区改变后,数据从新进行存储

    List.js文件代码

    import Utils from "./Utils.js";
    
    export default class List{
        mask;
        static TODO_LIST_CHANGE="todo_list_change";
        static TODO_LIST_REMOVE="todo_list_remove";
        constructor(_mask=false){
            this.mask=_mask;
            this.elem=this.createElem();
            this.elem.addEventListener("click",e=>this.clickHandler(e));  //事件委托
        }
        createElem(){
            if(this.elem) return this.elem;
            return Utils.ce("ul",{
                listStyle:"none",
                margin:"0px",
                padding:0,
                "600px",
            });  
        }
        appendTo(parent){
            if(typeof parent==="string") parent=document.querySelector(parent);
            parent.appendChild(this.elem);
        }
    
        setData(list){  //输入数据回车后的数组或者遮罩后的数据的数组
            this.elem.innerHTML="";
            for(var i=0;i<list.length;i++){   //li中有多选框,文本span,a标签(删除)  多选框和a标签要获取其下标和checked
                let li=Utils.ce("li",{
                    display: "list-item",
                    textAlign: "-webkit-match-parent",
                    userDrag: "element",
                    userSelect: "none",
                    height: "32px",
                    lineHeight: "32px",
                    background: "#fff",
                    position: "relative",
                    marginBottom: "10px",
                    padding: "0 45px",
                    borderRadius: "3px",
                    boxShadow: "0 1px 2px rgba(0,0,0,0.07)",
                    borderLeft:!this.mask ? "5px solid #999" :"5px solid #629A9C",
                    opacity:!this.mask ? "0.5"  :  "1",   //进行时this.mask为true,值为1
                });
                let ck=Utils.ce("input",{
                    position:'absolute',
                    top:'2px',
                    left:'10px',
                    '22px',
                    height:'22px',
                    cursor:'pointer',
                    backgroundColor:'initial',
                    cursor:'default',
                    appearance:'checkbox',
                    boxSizing:'border-box',
                    margin:'3px 3px 3px 4px',
                    padding:'initial',
                    border:'initial',
                    WebkitWritingMode:'horizontal-tb !important',
                    textRendering:'auto',
                    color:'-internal-light-dark(black, white)',
                    letterSpacing:'normal',
                    wordSpacing:'normal',
                    textTransform:'none',
                    textIndent:'0px',
                    textShadow:'none',
                    display:'inline-block',
                    textAlign:'start',
                    font:'400 13.3333px Arial',
                });
                ck.type="checkbox";
                ck.index=i;   //获取了 多选框的index和checked
                ck.checked=!this.mask       //进行时传进来的是true,遮罩时传进来的是false,所以去反
                li.appendChild(ck);
                let span=Utils.ce("span",{
                    display:"inline-block",
                    "500px",
                    overflow:"hidden"
                });
                span.textContent=list[i];
                li.appendChild(span);
                let a=Utils.ce("a",{
                    position: "absolute",
                    top: "2px",
                    right: "5px",
                    display: "inline-block",
                     "14px",
                    height: "12px",
                    borderRadius: "14px",
                    border: "6px double #FFF",
                    background: "#CCC",
                    lineHeight: "14px",
                    textAlign: "center",
                    color: "#FFF",
                    fontWeight: "bold",
                    fontSize: "14px",
                    cursor: "pointer",
                    textDecoration: "underline",
                });
                a.textContent="-";
                a.index=i;
                a.checked=this.mask;
                li.appendChild(a);
                this.elem.appendChild(li);
            }
        }
        clickHandler(e){
            if(e.target.constructor!==HTMLInputElement && e.target.constructor!==HTMLAnchorElement) return;//必须点checkbox和a才有用
            if(e.target.constructor===HTMLInputElement){  //点击checkbox
                var evt=new Event(List.TODO_LIST_CHANGE);
                evt.index=e.target.index;
                evt.checked=e.target.checked;
                document.dispatchEvent(evt);  //抛发给document
                return;
            }
            var evt=new Event(List.TODO_LIST_REMOVE);
                evt.index=e.target.index;
                evt.checked=e.target.checked;
                document.dispatchEvent(evt);
                
        }
    
    }
    

    todoList.js文件代码

    import Utils from "./Utils.js";
    import List from "./List.js";
    
    export default class TodoList{
        arr=[];  //存储实例的List   一共就两个
        todoArr=[];  //进行时的数据
        doneArr=[];  //完成的数据
        constructor(){
            if(localStorage.todoArr) this.todoArr=JSON.parse(localStorage.todoArr); //localStorage的获取
            if(localStorage.doneArr) this.doneArr=JSON.parse(localStorage.doneArr);
            this.elem=this.creatElem();  //最外层容器
            this.createListCon("正在进行");//创建内容区
            this.createListCon("已经完成");
            document.addEventListener(List.TODO_LIST_CHANGE,e=>this.todoListChange(e))//点击后抛发出来的两个事件
            document.addEventListener(List.TODO_LIST_REMOVE,e=>this.todoListChange(e))
            document.addEventListener("keyup",e=>this.keyHandler(e));//回车
        }
        creatElem(){
            if(this.elem) return this.elem;
            let div=Utils.ce("div",{  //this.elem
                position:"absolute",
                "100%",
                left:0,
                top:0,
                right:0,
                bottom:0,
                backgroundColor:"#CDCDCD"
            });
            let head=Utils.ce("div",{ //头部容器
                position:"relative",
                left:0,
                right:"0px",
                height:"50px",
                backgroundColor:"rgba(47,47,47,0.98)",
                padding:"0 321px",
            })
            let label=Utils.ce("label",{  //头部文字
                float: "left",
                 "100px",
                lineHeight: "50px",
                color: "#DDD",
                fontSize: "24px",
                cursor: "pointer",
                fontFamily: '"Helvetica Neue",Helvetica,Arial,sans-serif',
            })
            label.textContent="ToDoList";
            this.input=Utils.ce("input",{  //头部输入框
                textRendering: "auto",
                color: "-internal-light-dark(black, white)",
                letterSpacing: "normal",
                wordSpacing: "normal",
                textTransform: "none",
                textShadow: "none",
                display: "inline-block",
                textAlign: "start",
                appearance: "textfield",
                backgroundColor: "-internal-light-dark(rgb(255, 255, 255), rgb(59, 59, 59))",
                cursor: "text",
                marginLeft: "100px",
                font: "400 13.3333px Arial",
                float: "left",
                 "360px",
                height: "24px",
                marginTop: "12px",
                textIndent: "10px",
                borderRadius: "5px",
                boxShadow: "0 1px 0 rgba(255,255,255,0.24), 0 1px 6px rgba(0,0,0,0.45) inset",
                border: "none",
                padding: "1px 2px",
            })
            this.input.setAttribute("placeholder","添加ToDo");
            head.appendChild(label);
            head.appendChild(this.input);
            div.appendChild(head);
           
            return div;
        }
        appendTo(parent){
            if(typeof parent==="string") parent=document.querySelector(parent);
            parent.appendChild(this.elem);
        }
        createListCon(title){  //创建内容区
            let div=Utils.ce("div",{
                "600px",
                margin:"auto",
    
            });
            let h2=Utils.ce("h2");
            h2.textContent=title;  //同一个函数执行两次,传参不同,所以页面上有两个h2
            let list=new List(title=="正在进行");//如果传参title=="正在进行",创建进行时的li,同一个函数执行两次,两次传参,所以要判断,返回false/true
            this.arr.push(list);  //arr中有两个数据(进行时和遮罩时的)
            if(title==="正在进行")list.setData(this.todoArr);  //插入localStorage中的数据
            else list.setData(this.doneArr);
            div.appendChild(h2);
            list.appendTo(div);
            this.elem.appendChild(div);
        }
        keyHandler(e){
            if(e.keyCode!==13) return;
            if(this.input.value.trim().length===0) return; //判断input中内容不为0
            this.todoArr.push(this.input.value);//输入的数据传入到进行时数组中
            this.input.value="";//输入框清空
            this.arr[0].setData(this.todoArr);
            this.saveData();
        }
        todoListChange(e){     
            if(e.checked){  //删除进行时e.checked为true,改变进行时,传进去的是false,e.ckecked=!mask,也是true
               let arr=this.todoArr.splice(e.index,1);
              if(e.type===List.TODO_LIST_CHANGE) this.doneArr.push(arr[0]);
            }else{
                let arr=this.doneArr.splice(e.index,1);
                if(e.type===List.TODO_LIST_CHANGE) this.todoArr.push(arr[0]);
            }
            this.arr[0].setData(this.todoArr);
            this.arr[1].setData(this.doneArr);
            this.saveData();
        }
        saveData(){  //数据存储到本地
            localStorage.todoArr=JSON.stringify(this.todoArr);
            localStorage.doneArr=JSON.stringify(this.doneArr);
        }
    }
    

    HTML页面只要new todoList对象,就能实现

    <!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>
        <script type="module">
            import TodoList from './js/TodoList.js';
            
        let todo=new TodoList();
        todo.appendTo("body");
        </script>
    </body>
    </html>
    

    Utils.js是工具包

    export default class Utils{
       static time=0;
       static ids=0;
       static timeManage={};
    //    在静态方法中调用的变量都需要写成静态的
    // 在静态方法中理论上不能使用this的,我们需要坚决贯彻这个思想
    // 实际在静态方法中this就是当前类名
       static timeStart(){
            if(Utils.time) return;
            Utils.time=new Date().getTime();
        }
       static timeEnd(){
            var t=new Date().getTime()-Utils.time;
            Utils.time=0;
            return t;
        }
        static ts(){
            Utils.ids++;
            Utils.timeManage[Utils.ids]=new Date().getTime();
            return ids;
        }
        static te(id){
            if(!Utils.timeManage[Utils.id]) return 0;
            var t=new Date().getTime()-Utils.timeManage[Utils.id];
            delete Utils.timeManage[Utils.id];
            return t;
        }
        static randomColor(){
            var col="#";
            for(var i=0;i<6;i++){
                col+=Math.floor(Math.random()*16).toString(16);
            }
            return col;
        }
        static random(min,max){
            return Math.floor(Math.random()*(max-min)+min);
        }
         static ce(type,style,parent){
            var elem=document.createElement(type);
            if(style){
                for(var prop in style){
                    elem.style[prop]=style[prop];
                }
            }
            if(typeof parent==="string") parent=document.querySelector(parent);
            if(parent) parent.appendChild(elem);
            return elem;
        }
        static setStyle(styles){
            var style=document.createElement("style");
            document.head.appendChild(style);
            var styleSheet=document.styleSheets[document.styleSheets.length-1];
            for(var prop in styles){
                Utils.addCss(styleSheet,prop,styles[prop]);
            }
        }
        static addCss(styleSheet,selector,style){
            var str=selector+" {";
            for(var prop in style){
                var value=style[prop]
                prop=prop.replace(/([A-Z])/g,function($1){
                    return "-"+$1.toLowerCase();
                })
                str+=prop+":"+value+";"
            }
            str+=" }";
            styleSheet.insertRule(str,styleSheet.cssRules.length);
        }
        static CSStoString(str){
           return str.replace(/(?<=:)(.*?)(?=;)|-[a-z](?=.+:)|;/g,function(item){
                if(item===";") return ","
                if(item[0]==="-")  return item[1].toUpperCase();
                return "'"+item.trim()+"'";
            });
        }
        // TODO 将CSS转换为对象
        static CSStoObject(str){
            str=Utils.CSStoString(str);
           return  str.split(",").reduce((value,item)=>{
               item=item.replace(/
    /g,"");
                var arr=item.split(":");
                arr[0]=arr[0].replace(/s/g,"");
                if(arr[1]===undefined) return value;
                arr[1]=arr[1].replace(/'/g,"");
                value[arr[0]]=arr[1];
                return value;
            },{})
        }
        static getCookie(){
            return document.cookie.split(/;s*/).reduce((value,item)=>{
               var arr=item.split("=");
                value[arr[0]]=isNaN(arr[1]) ? arr[1] : Number(arr[1]);
                return value;
          },{})
        }
        static getCookieValue(key){
           return Utils.getCookie()[key];
        }
        static setCookie(key,value,date){
            if(!date){
                document.cookie=`${key}=${value}`;
                return;
            }
            document.cookie=`${key}=${value};expires=${date.toUTCString()}`;
        }
        static setCookies(obj,date){
            for(var key in obj){
                Utils.setCookie(key,obj[key],date);
            }
        }
        // TODO 删除Cookie
        static removeCookie(key){
            Utils.setCookie(key,"",new Date());
        }
        static clearCookie(){
            for(var key in Utils.getCookie()){
                Utils.removeCookie(key);
            }
        }
    }
    
  • 相关阅读:
    php工作笔记5-css定位
    php工作笔记4-mysql笔记1
    php工作笔记3-php基础加强
    php工作笔记2-php编码效率
    php工作笔记1-数组常用方法总结,二维数组的去重,上传图片到oss服务器
    android浏览器 源码共享
    违章查询源码分享
    CENTOS 6.5 配置YUM安装NGINX
    Linux下安装Oracle11g服务器
    ARCGIS SDE空间化处理
  • 原文地址:https://www.cnblogs.com/94-Lucky/p/13446085.html
Copyright © 2011-2022 走看看