前端基础学习

WeakMap类型

2020-04-26  本文已影响0人  小雪洁
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>WeakMap</title>
    </head>
    <body>
        <div>haoxuejie</div>
        <div>yangdingchuan</div>
    </body>
    <script>
        //WeakMap类型的数据键只能是对象
        let divs=document.querySelectorAll("div");
        let wmap = new WeakMap();
        divs.forEach(item=>{
            wmap.set(item,item.innerHTML);
        });
        console.log(wmap);//
        //WeakMap {div => "yangdingchuan", div => "haoxuejie"}
        //其中div是节点对象
        
        //WeakMap的方法只有set()、get()、has()、delete()
        //添加元素
        let arr=[]
        wmap.set(arr,'hxj');
        console.log(wmap);//{Array(0) => "hxj", div => "haoxuejie", div => "yangdingchuan"}
        //获取元素
        console.log(wmap.get(divs[0]));//取到的是值
        //WeakMap类型数据wmap中是否含有键为[]的元素
        console.log(wmap.has(arr));//true
        console.log(wmap.has([]));//false一定要注意map和WeakMap类型的键是个引用
        
        
    </script>
</html>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>WeakMap弱类型的特性</title>
    </head>
    <body>
    </body>
    <script>
        //WeakMap主要用来保存受外部影响的数据
        let hxj={name:'hxj'};
        let wm1=new WeakMap();
        wm1.set(hxj,30);
        hxj=null;
        console.log(wm1);//WeakMap {{…} => 30}
        setTimeout(()=>{
            console.log(wm1);
        },5000);//WeakMap {}
    </script>
</html>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>使用WeakMap开发选课组件</title>
    </head>
    <style>
        *{
            padding: 0;
            margin:0;
            box-sizing: border-box;
        }
        body{
            width:100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            padding: 10px;
        }
        body div{
            width: 150px;
            height: 100px;
            border: solid #CCCCCC 1px;
            margin: 5px;
        }
        div ul{
            height: 100%;
            list-style: none;
            padding: 5px;
            display:flex;
            flex-direction: column;
            justify-content: center;
        }
        div ul li{
            width: 100%;
            margin: 2px;
            border: solid 2px #009688;
            display: flex;
        }
        div ul li span{
            flex: 1;
        }
        div ul li a{
            text-decoration: none;
            font-size: 1.2em;
            background: #009999;
            flex:0 0 20%;
            text-align:center;
            color: #FFFFFF;
        }
        div ul li a,span{
            
        }
        
    </style>
    <body>
        <div>
            <ul>
                <li><span>html</span><a href="javascript:;">+</a></li>
                <li><span>css</span><a href="javascript:;">+</a></li>
                <li><span>js</span><a href="javascript:;">+</a></li>
            </ul>
        </div>
        <div>
            <strong id="count"></strong>
            <p id="lists"></p>
        </div>
    </body>
    <script>
        //lessons类,获取li元素,获取count元素
        //每次点击+号后,a标签里背景变红色符号变-,给li加上selected属性,;
        //每次点击-号,a标签里背景变绿色符号变+,给li移除selected属性,;
        //即给a标签添加点击事件,如果这个a是-号(即父级li有selected属性)a标签里背景变绿色符号变+,
        //如果这个a是+号(即父级li没有selected属性),就给li加上selected属性,a标签里背景变红色符号变-;
        class lessons{
            constructor() {
                this.liEles= document.querySelectorAll("li");
                this.countEle= document.getElementById("count");
                this.wm=new WeakMap();
                this.p=document.getElementById("lists");
            }
            run(){
                this.addEvent();
            }
            
            //给li循环,给里面的a加事件,获取li的selected属性,如果有就变绿变+
            //如果没有就变红变-
            //不使用箭头函数,以孙子函数的角度来解释   :
            //若父亲函数内部还有孙子函数,
            //孙子函数若要引用爷爷函数里定义的变量或方法
            //那在父亲函数里要存爷爷的this,如let _this=this;
            //孙子想访问父亲外部爷爷的变量,就用这个_this.xxx;
            //如果不转存,直接使用this只会在父亲函数里找,父亲外部的属于爷爷的变量
            addEvent(){
                let _this=this;
                this.liEles.forEach(function(li){
                    let aEle=li.querySelector("a");
                    aEle.addEventListener("click",function(event){
                        let a= event.target;
                        let selected=li.getAttribute("selected");
                        //状态是-号已经选中,点击后要变+移除已选中,删掉wm中的dom节点
                        if(selected){
                            li.removeAttribute("selected");
                            _this.wm.delete(li);
                            a.innerHTML="+";
                            a.style.background="#009999";
                        }else{ //状态是+没有选中,点击后要变-号设置已选中,存储wm的dom节点
                            //console.log(this.wm);
                            _this.wm.set(li);
                            //console.log(_this.wm);
                            li.setAttribute("selected",true);
                            a.innerHTML="-";
                            a.style.background="red";
                        }
                        _this.render();
                    });
                });
            }
            render(){
                this.countEle.innerHTML=`共选择了${this.count()}门课`;
                this.updateLessons();
            }
            count(){
                //统计一共选了几门课,用arr.reduce()函数
                return [...this.liEles].reduce((count,li)=>{
                      this.wm.has(li)?count++:"";
                      return count;
                },0);
            }
            updateLessons(){
                let html="";
                [...this.liEles].filter(li=>{
                    if(this.wm.has(li)){
                        //this.p.innerHTML+=`${li.querySelector("span").innerHTML}</br>`;
                        //上一行注释中的语句就会出现重复往右边框里加选中的课,
                        //因为我每次点击都会触发这个render(),都会遍历一次左边的li,
                        //第一次选中一个添加了,第二次遍历我选了两个,又累加了所以会出现重复;
                        //因此在每次遍历前先清空一下html,记录下我在这次点击后遍历的结果,
                        //循环结束后我把这个html赋值到p标签里
                        html+=`${li.querySelector("span").innerHTML}</br>`;
                    }
                });
                this.p.innerHTML=html;
            }
            
            //使用箭头函数可以使函数内部this与函数外部this指向一致
            //即父亲的this就是指向爷爷的this,孙子在自己的函数里就可以直接this到爷爷的变量
            /* addEvent(){
                this.liEles.forEach(li=>{
                    let aEle=li.querySelector("a");
                    aEle.addEventListener("click",(event)=>{
                        let a= event.target;
                        let selected=li.getAttribute("selected");
                        if(selected){
                            li.removeAttribute("selected");
                            this.wm.delete(li);
                            a.innerHTML="+";
                            a.style.background="green";
                            console.log(this.wm);
                        }else{
                            console.log(li);
                            this.wm.set(li);
                            console.log(a);
                            li.setAttribute("selected",true);
                            a.innerHTML="-";
                            a.style.background="red";
                        }
                    })
                });
            } */
        };
        let lesson= new lessons();
        lesson.run();
    </script>
</html>

效果如下:


选课小组件.gif
上一篇下一篇

猜你喜欢

热点阅读