<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WeakMap</title>
</head>
<body>
<div>haoxuejie</div>
<div>yangdingchuan</div>
</body>
<script>
//WeakMap類(lèi)型的數(shù)據(jù)鍵只能是對(duì)象
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是節(jié)點(diǎn)對(duì)象
//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類(lèi)型數(shù)據(jù)wmap中是否含有鍵為[]的元素
console.log(wmap.has(arr));//true
console.log(wmap.has([]));//false一定要注意map和WeakMap類(lèi)型的鍵是個(gè)引用
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WeakMap弱類(lèi)型的特性</title>
</head>
<body>
</body>
<script>
//WeakMap主要用來(lái)保存受外部影響的數(shù)據(jù)
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開(kāi)發(fā)選課組件</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類(lèi),獲取li元素,獲取count元素
//每次點(diǎn)擊+號(hào)后,a標(biāo)簽里背景變紅色符號(hào)變-,給li加上selected屬性,;
//每次點(diǎn)擊-號(hào),a標(biāo)簽里背景變綠色符號(hào)變+,給li移除selected屬性,;
//即給a標(biāo)簽添加點(diǎn)擊事件,如果這個(gè)a是-號(hào)(即父級(jí)li有selected屬性)a標(biāo)簽里背景變綠色符號(hào)變+,
//如果這個(gè)a是+號(hào)(即父級(jí)li沒(méi)有selected屬性),就給li加上selected屬性,a標(biāo)簽里背景變紅色符號(hào)變-;
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循環(huán),給里面的a加事件,獲取li的selected屬性,如果有就變綠變+
//如果沒(méi)有就變紅變-
//不使用箭頭函數(shù),以孫子函數(shù)的角度來(lái)解釋 :
//若父親函數(shù)內(nèi)部還有孫子函數(shù),
//孫子函數(shù)若要引用爺爺函數(shù)里定義的變量或方法
//那在父親函數(shù)里要存爺爺?shù)膖his,如let _this=this;
//孫子想訪(fǎng)問(wèn)父親外部爺爺?shù)淖兞浚陀眠@個(gè)_this.xxx;
//如果不轉(zhuǎn)存,直接使用this只會(huì)在父親函數(shù)里找,父親外部的屬于爺爺?shù)淖兞? 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");
//狀態(tài)是-號(hào)已經(jīng)選中,點(diǎn)擊后要變+移除已選中,刪掉wm中的dom節(jié)點(diǎn)
if(selected){
li.removeAttribute("selected");
_this.wm.delete(li);
a.innerHTML="+";
a.style.background="#009999";
}else{ //狀態(tài)是+沒(méi)有選中,點(diǎn)擊后要變-號(hào)設(shè)置已選中,存儲(chǔ)wm的dom節(jié)點(diǎn)
//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()}門(mén)課`;
this.updateLessons();
}
count(){
//統(tǒng)計(jì)一共選了幾門(mén)課,用arr.reduce()函數(shù)
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>`;
//上一行注釋中的語(yǔ)句就會(huì)出現(xiàn)重復(fù)往右邊框里加選中的課,
//因?yàn)槲颐看吸c(diǎn)擊都會(huì)觸發(fā)這個(gè)render(),都會(huì)遍歷一次左邊的li,
//第一次選中一個(gè)添加了,第二次遍歷我選了兩個(gè),又累加了所以會(huì)出現(xiàn)重復(fù);
//因此在每次遍歷前先清空一下html,記錄下我在這次點(diǎn)擊后遍歷的結(jié)果,
//循環(huán)結(jié)束后我把這個(gè)html賦值到p標(biāo)簽里
html+=`${li.querySelector("span").innerHTML}</br>`;
}
});
this.p.innerHTML=html;
}
//使用箭頭函數(shù)可以使函數(shù)內(nèi)部this與函數(shù)外部this指向一致
//即父親的this就是指向爺爺?shù)膖his,孫子在自己的函數(shù)里就可以直接this到爺爺?shù)淖兞? /* 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