壹、目錄及代辦事項

Table of Contents

待學習項目

貳、基礎內容文件要點說明

一、文字與語意化

1.段落的語意

參、變數

一、變數簡介

1. 變數裡可以放進的值

  • 數字
  • 字串
  • 布林

二、變數 number 介紹

1.指定id來變換變數

<p>這個紅豆餅的價錢是<em id="price"></em></p> <script> var cookiePrice = 35; document.getElementById('price').textContent = cookiePrice; </script>
  • 或是使用getElementsByClassName來指定,但是要[]選擇第幾個class,class代表很多,所以getElementsByClassName的elements要加s
var cookiePrice = 35; document.getElementsByClassName('price')[0].textContent = cookiePrice;

三、 變數 string 介紹

  • 宣告string變數,內容記得要加""
  • string也可以使用+號來將文字串成句子。
var expensive = "很貴" var cookiePrice = "三十五塊"; var total = expensive + cookiePrice +",你要買嗎?"; document.getElementById('price').textContent = total;
  • 透過變數指定id,並使用innerHTML增加html語法
<div id="wrap"></div> <script> var title = document.getElementById('wrap'); title.innerHTML = '<span>hello<span><br><span>hello<span>' </script>

四、變數規則:注意事項

1.命名變數注意事項

  • 開頭不能用數字
  • 不能使用JS已經定義的關鍵字。ex:if、in、float..
    參考網址
  • 大小寫有區分
  • 不能使用-和.
  • 變數需要有語意化

五、變數 - 數字的運算

var snackPrice = 35; var myMoney = 10; var needMoney = snackPrice - myMoney; var total = snackPrice * 5;

肆、函式

一、全域與區域變數

  • 全域變數
var total=1; console.log("變數total值是"+total);
  • 函式內的區域變數
function count(num1,num2){ var total = num1 * num2; console.log("這個值是"+total); } count(4,5);
  • 如果全域變數內的值也想讓函式使用的話。全域變數去宣告,函式直接使用全域變數
var total; function count(num1,num2){ total = num1 * num2; console.log("這個值是"+total); } count(4,5); console.log("變數total值是"+total);
  • 但如果區域和全域都宣告了同一個變數,就會變成獨立的變數,值不互相干擾
var total=1; function count(num1,num2){ var total = num1 * num2; console.log("這個值是"+total); } count(4,5);//這個值是20 console.log("變數total值是"+total);//變數total值是1

二、hoisting 、var 觀念

console.log(phone); // undefined var phone = 'myphone'; console.log(phone); // myphone //如果在 var 的變數前加入 console.log(),這個時候並不會出錯,則是會跳出 undefined,這表示這個變數在記憶體中已經有一個位置,只不過目前並沒有值。 call('mike');//call mike function call(name){ console.log("call "+name); } call('mike');//call mike //function declaration 函式陳述式中(function 放在最前方的寫法),無論函式放在哪,整個函式都會被提升到最前方。所以就算call()放在函式前也可以呼叫的到。

三、 function 計算機案例

  • parseInt: 使用parseInt將type轉換成Int
  • typeof: 使用來查詢變數的type
document.getElementById('countId').onclick = function(){ var burgerPrice = 50; var cokePrice =30; var burger = parseInt(document.getElementById('burgerId').value)*burgerPrice;//使用parseInt將type轉換成Int var coke = parseInt(document.getElementById('cokeId').value)*cokePrice; console.log(typeof(burger));//可以藉由typeof()來查詢變數的type console.log(typeof(coke)); document.getElementById('totalId').textContent = burger + coke; }

四、function搭配return寫法

伍、陣列與物件

一、陣列

1.寫法

  • var field = [0,0,2];

2. 增加陣列內容

  • 方法一
var field = []; field.push(1); field.push(2); field.push(3); 出來的結果 [1,2,3]
  • 方法二
var field = []; field[0]=1; field[1]=2; // 出來的結果 [1,2] // 此方法也可以指定陣列位置修改內容 field[0]=100; // 出來的結果 [100,2]

3. 計算陣列長度

var field = [0,0,2]; console.log(field.length); //計算結果 //3

二、物件

1. 寫法

  • 注意物件裡面是用:來宣告,分隔每個變數是用,
var = farm{ farmer:'Mike', chick: 2, }

2.增加物件內的內容

var = farm{ farmer:'Mike', chick: 2, } farm.dog = ['happy','lucky'] // 出來的結果: farm{ farmer:'Mike', chick : 2 , dog : ['happy','lucky'], }

3.尋找物件裡的陣列

console.log(farm.dog[0]); 出來的結果: happy

三、物件 + function 運用技巧

1.在物件中加入function

farm{ farmer:'Mike', chick : 2 , dog : ['happy','lucky'], goDinner: function(){ console.log(farmer+'回家吃飯') } } farm.goDinner(); //出來的結果 Mike回家吃飯

1.在物件中再加入陣列

var text = document.querySelector('.text'); var farms = [ { farmer:'milk', dog : ['happy','lucky'] }, { farmer:'Tom', dog : ['funny','nicer'], goDinner : function(){ text.innerText=farms[1].dog[1]+'回家吃飯'; } } ]; farms[1].goDinner(); // 運算結果 nicer回家吃飯

陸、控制判斷(運算子、if、switch)

一、比較運算子:、!,程式碼範例

  • 使用==,會自動幫忙轉型
  • 使用!==,不會自動幫忙轉型,必須兩側的type都一樣。
<p>您預定 5 個人來逛,而現在只有<input type="number" id="peopleNumber">,所以人到齊了嗎?<button id="peopleNumberVerify">確認</button></p> <p>顧客:<em id="peopleNumberCheckResponse"></em></p>
document.getElementById('peopleNumberVerify').onclick = function(){ var nowPeople = parseInt(document.getElementById('peopleNumber').value); console.log(typeof(nowPeople)); var reservedPeople = 5; console.log(typeof(reservedPeople)); var peopleCheck = nowPeople == reservedPeople; //就算兩個值,左邊是字串,右邊是數字,但使用==和!=的話,javascript會自動轉型 //但如果使用!==,就會不自動幫你轉型 document.getElementById('peopleNumberCheckResponse').textContent = peopleCheck; };

二、比較運算子:嚴謹模式 ===

1 == '1' //true 因為JS會自動轉型

1 === '1' //false 三個等於屬於嚴謹模式,不會自動轉型

'1' === '1' //true

true == 1 //true JS會自動將1轉型為true

true === 1 //false

三、邏輯運算子

&& and
|| or
! not

四、if、else if

if(判斷式){ 執行內容.... }else if(判斷式){ 執行內容 }else if(判斷式){ 執行內容 } . . . else{ 其他狀況,執行內容 }

五、switch

switch(變數){ case 判斷: 執行內容; break; case 判斷: 執行內容; break; case 判斷: 執行內容; break; . . . default: 其他狀況,執行內容; break; } //例子1 var status = 10; switch(true){ case status>=1&&status<=3: console.log('我很餓'); break; case status>3&&status<=7: console.log('我有點餓'); break; default: console.log('我不餓') break; } //例子2 var alert = 'red'; switch(alert){ case 'red': console.log('紅色警報'); break; case 'blue': console.log('藍色警報'); break; default: console.log('警報解除') break; }

柒、迴圈

一、for迴圈

//for(var宣告 初始狀態;條件;更新內容) for(var i=0;i<3;i++){ console.log(i); } //範例一:九九乘法 for(var i=1;i<10;i++){ for(var j=1;j<10;j++){ console.log(i+"*"+j+"="+j*i); } } //結果 //0 //1 //2

二、for-array 寫法

  • 犯的錯誤: 物件內的宣告是用:、分隔物件內的變數是用,
var farms = [ { farmer :'Tom', dog : 2 , }, { farmer :'John', dog : 2 , }, { farmer : 'Mary', dog : 2 , } ]; for(var i=0 ;i<farms.length ;i++){ console.log('第'+(i+1)+'個農場主人是'+farms[i].farmer) };

三、for if 寫法

var farms = [ { farmer :'Tom', dog : 13, }, { farmer :'John', dog : 2 , }, { farmer : 'Mary', dog : 12 , } ]; //篩選出有十隻狗狗以上的農場 for(var i=0 ;i<farms.length ;i++){ if(farms[i].dog>10){ console.log(farms[i].farmer+'的狗狗超過十隻') } };

四、for 加總+=

var farms = [ { farmer :'Tom', dog : 13, }, { farmer :'John', dog : 2 , }, { farmer : 'Mary', dog : 12 , } ]; var dogTotal = 0; for(var i=0 ;i<farms.length ;i++){ dogTotal += farms[i].dog; //等同於dogTotal = dogTotal+farms[i].dog }; console.log('全部的狗狗有' + dogTotal + '隻');

五、for 與 break 運用

  • break要放在if裡面,不然跑第一次的時候就會被中斷掉。只會跑一次。
var farms = [ { farmer :'Tom', dog : 13, chick:51, }, { farmer :'John', dog : 2 , chick:26, }, { farmer : 'Mary', dog : 12 , chick:100, } ]; //找到小雞有超過指定數量的農場 var buyChick = 60; for(var i=0 ;i<farms.length ;i++){ if(farms[i].chick>buyChick){ console.log(farms[i].farmer+'的農場小雞有超過'+buyChick+'隻,我買走'+buyChick+'隻'); farms[i].chick -= buyChick;//farms[i].chick-buyChick = farms[i].chick console.log(farms[i].farmer+'的農場剩下'+farms[i].chick+'隻小雞'); break; } };

六、return、break 和 break的差別

break : 當迴圈的值符合條件時候就立刻跳出迴圈,即使之後有其他的值也符合條件,範例

continue: 在迴圈內的意思是,看到它就直接跳到下一圈,無視剩下的程式碼,範例

return: 回傳指定 function 的值,只能放在function內範例

捌、DOM

一、什麼是 DOM ?

二、querySelector - 選擇單一元素

  • 選擇ID
document.getElementById('titleId').textContent = "1234"; //簡化document.getElementById('titleId'); var el = document.getElementById('titleId'); el.textContent = "12345";
  • ID和Class的方法:querySelector(單個class)
//選擇ID var el = document.querySelector("#title"); el.textContent = "123456"; //選擇Class var el = document.querySelector(".titleClass em"); el.textContent = "12345678";

二、querySelectorAll - 選擇多個元素

<h1 class="title"><em></em></h1>//顯示12345678 <h1 class="title"><em></em></h1>//顯示87654321
//選擇所有.titleClass下的em var el = document.querySelectorAll(".titleClass em"); el[0].textContent = "12345678"; el[1].textContent = "87654321";

三、增加與取出標籤屬性

<h1 class="titleClass"> <a href="#">yahoo</a> </h1>

1.setAttribute - 修改標籤屬性

//將href="#"的內容修改為google的首頁 var el = document.querySelector('.titleClass a'); el.setAttribute('href','http://www.google.com.tw/'); ////變更結果href="http://www.google.com.tw/"

2.getAttribute - 取出標籤內容

//取出href內容 var el1 = document.querySelector('.titleClass a').getAttribute('href'); console.log(el1); ////取出結果http://www.google.com.tw/

3.innerHTML - 取出整個Html標籤

//取出titleClass的html標籤 var el2 = document.querySelector('.titleClass').innerHTML; console.log(el2); ////取出結果<a href="http://www.google.com.tw/">yahoo</a>

四、插入 HTML 標籤的兩種方法

1. innerHTML

<h2 id="bodyId"></h2> <ul class="list"></ul>
  • 增加Html標籤
var el3 = document.getElementById('bodyId'); var str = '<p class="blue">hello<p>'; //class內要使用雙引號做出區分 el3.innerHTML = str; //這邊要使用 =
  • 在innerHTML加入變數
    • 訣竅:加入'++'
//在innerHTML加入變數 var el4 = document.querySelector('.list'); var booking = 'http://www.booking.com' var website = '訂房網站' el4.innerHTML = '<li><a href="' + booking + '"> ' + website + ' </a></li>';
  • innerHTML結合for迴圈
<ul class="js-zooClass"></ul>
var zoo = [ { zooName:'木柵動物園', lion:10, }, { zooName:'新竹動物園', lion:8, } ] var zooLength = zoo.length; var el5 = document.querySelector('.js-zooClass'); var com = ''; for(var i = 0 ; i < zooLength ; i++){ var zooNameTotal = '<li>第'+i+'間動物園的名字叫'+zoo[i].zooName+'</li>'; com += zooNameTotal; //必須把zooNameTotal的資料保留在com裡面,因為innerHTML的特性只要寫入一次就會把裡面的東西全洗掉 } el5.innerHTML=com;

2. createElement

  • 使用createElement增加子節點
    原本的內容
<ul class="js-cook"> <em>abcd</em> </ul>

js

var str = document.createElement('em'); str.textContent = 'ABCD'; //預先寫好em裡面的字串 str.setAttribute('class','blue'); //預先寫好em裡面的class名稱 //後來才宣告出來,增加的em會接續在原本的em後面,不會把原先的內容洗掉 var el6 = document.querySelector('.js-cook').appendChild(str);

經過js後

<ul class="js-cook"> <em>abcd</em> <em>ABCD</em> </ul>
  • createElement 與 for 運用
    原本的內容
<ul class="js-zoo2Class"> <li>tiger</li> </ul>

js

var zoo2 = [ { zooName:'木柵動物園', lion:10, }, { zooName:'新竹動物園', lion:8, } ] var zoo2Length = zoo2.length; var el7 = document.querySelector('.js-zoo2Class'); for(i = 0 ; i < zoo2Length ; i++){ var ptt = document.createElement('li'); ptt.textContent = '農場' + i + '獅子數量:'+zoo2[i].lion; el7.appendChild(ptt); }

js後的內容

<ul class="js-zoo2Class"> <li>tiger</li> <li>農場0獅子數量:10</li> <li>農場1獅子數量:8</li> </ul>

玖、event事件

一、什麼是event

二、event 物件 - 告知你當下元素資訊

<input type="button" class="apple" value="點擊"> <script> var el = document.querySelector('.apple'); el.onclick = function(e){ console.log(e) }; </script>
  • 使用chorme瀏覽器去看console,e裡面會呈現許多資訊。

三、addEventListener - 事件監聽

<input type="button" class="pineapple" value="點擊2"> <script> var el2 = document.querySelector('.pineapple'); ////事件,帶入匿名function,false el2.addEventListener('click',function(e){ alert('pineapple');},false) </script>

四、綁定事件的語法差異

<input type="button" class="on" value="onclick"> <input type="button" class="add" value="addclick">
var elOn = document.querySelector('.on'); var elAdd = document.querySelector('.add'); //使用onclick只會出現on2的事件 elOn.onclick = function(){ alert('on1') }; elOn.onclick = function(){ alert('on2') }; //使用監聽兩個事件都會出現 elAdd.addEventListener('click',function(e){alert('add1')},false); elAdd.addEventListener('click',function(e){alert('add2')},false);
  • 使用onclick只會出現on2的事件
  • 使用監聽兩個事件都會出現

五、Event Bubbling、Event Capturing 差異

<div class="outbox"> <div class="box"></div> </div>
var outelbox = document.querySelector('.outbox'); var elbox = document.querySelector('.box'); outelbox.addEventListener('click',function(){alert('out')},true); elbox.addEventListener('click',function(){alert('in')},true);
  • false冒泡事件:會從box->outbox由內向外監聽(預設)
  • true捕捉事件:會從outbox->box由外向內監聽

六、stopPropagation 終止氣泡

var outelbox = document.querySelector('.outbox'); var elbox = document.querySelector('.box'); outelbox.addEventListener('click',function(e){alert('out')},false); elbox.addEventListener('click', function(e){ e.stopPropagation();//告訴事件不要再往外找 alert('in'); } ,false);

七、preventDefault - 取消預設觸發行為

var elcancel = document.querySelector('.post'); elcancel.addEventListener ('click', function(e){ e.preventDefault(); },false )
  • 常用在
    • 取消a連結預設行為
    • 取消submit將資料傳到後端,先用js檢查表格內容,再使用post去傳送

八、e.target - 了解目前所在元素位置

<div class="header"> <ul> <li> <a href="#">HEKKO</a> </li> </ul> </div>
////要怎麼知道我現在點擊到的是ul、li還是a連結 var elPos = document.querySelector('.header'); elPos.addEventListener('click',function(e){ console.log(e.target); },false)
  • 使用e.target找出目前點擊的位置

九、change - 表單內容更動內容時觸發

  • 使用下拉式選單選取option,配合change觸發事件,讀取data增加li項目
<select name="" id="areaId"> <option value="大社區">大社區</option> <option value="岡山區">岡山區</option> <option value="路竹區">路竹區</option> </select> <ul class="show"></ul>
var data = [ { seq: 1, 行政區: "大社區", 臨時停車處所: "老人文康活動中心", 可提供小型車停車位: "10", 地址: "金龍路65號" }, { seq: 3, 行政區: "岡山區", 臨時停車處所: "嘉興國中", 可提供小型車停車位: "16", 地址: "嘉興里信中街486號" }, { seq: 9, 行政區: "岡山區", 臨時停車處所: "壽天國小", 可提供小型車停車位: "40", 地址: "公園東路55號" }, { seq: 10, 行政區: "路竹區", 臨時停車處所: "蔡文國小", 可提供小型車停車位: "60", 地址: "國昌路548號" }, { seq: 11, 行政區: "路竹區", 臨時停車處所: "一甲國中", 可提供小型車停車位: "50", 地址: "一甲路 111 號" }, { seq: 12, 行政區: "路竹區", 臨時停車處所: "路竹高中", 可提供小型車停車位: "30", 地址: "中華路292號" }]; var elArea = document.querySelector('#areaId'); var elShow = document.querySelector('.show'); var updatefunction = function(e){ var dataLen = data.length; var select = e.target.value; var listArea = ''; for(var i = 0 ; i<dataLen ; i++){ if(select == data[i].行政區){ listArea += '<li>編號:' + data[i].seq + '</li>'; } } elShow.innerHTML = listArea; //innerHTML是用等於= } elArea.addEventListener('change',updatefunction,false); ////可以把function另外獨立寫出來再帶進去

十、keyCode - 點擊鍵盤,射發火箭!

  • 使用keycode去指定鍵盤按鈕,觸發事件。
    • 鍵盤1的keycode按鈕是49,當按下1時就會觸發Rock-1發射

十一、blur - 離開焦點時進行事件觸發

狀態focus:

->移開滑鼠點擊其他地方->狀態blur:

  • 練習目標: input內不得為字串、空白或負數,按下計算按鈕時前確認兩欄都有填寫範例
<div class="wrap"> <div class="wrap-inner"> <h1>六角西餐廳 - 顧客點餐篇</h1> <p>服務生:Hello,請問您想要點什麼?</p> <p> 顧客:給我 <input type="text" id="hamNumId" > 個漢堡,再 <input type="text" id="cokeNumId"> 杯可樂吧!</p> <p>服務生:<input type="button" Id="countId" value="計算中">,好的,總計是<em id="totalId" class="tag"></em></p> </div> </div>
//方法一: 使用if function checkContent1(e){ var ta = e.target.value; var taInt = parseInt(ta); if(ta==''){ alert('此欄位不可為空'); //不得為空值 }; if(isNaN(taInt)&&ta != ''||taInt<0){ alert('此欄位必須為正值'); //不得為字串或負值 } }; //方法二: 使用break function checkContent2(e){ var ta = e.target.value; var taInt = parseInt(ta); switch(true){ case ta == '': alert('此欄位不可為空'); break; case isNaN(taInt)&&ta != ''||taInt<0: //一開始我使用case isNaN(parseInt(ta))無法運行 alert('此欄位必須為正值'); break; }; } function count(){ var ham = document.getElementById('hamNumId').value; var coke = document.getElementById('cokeNumId').value; var hamPrice = 30; var cokePrice = 20; var elTotal = document.getElementById('totalId'); if (ham == '' || coke == '') {//點擊計算前,確認兩欄都有填入 alert('你兩個都要買!!!'); return; //如果沒填入使用return停止 } totalPrice = parseInt(ham)*hamPrice+parseInt(coke)*cokePrice elTotal.textContent = totalPrice; }; document.querySelector('#hamNumId').addEventListener('blur',checkContent1,false); document.querySelector('#cokeNumId').addEventListener('blur',checkContent2,false); document.querySelector('#countId').addEventListener('click',count,false);

十二、 mouse - 當滑鼠滑入指定內容時觸發

老師範例

<div class="box box1"></div> <div class="box box2"></div> <div class="box box3"></div> <div class="box box4"></div> <div class="box box5"></div> <div class="box box6"></div>
var el = document.querySelectorAll('.box'); var Len = el.length; for(var i = 0;i<Len;i++){ el[i].addEventListener('mousemove',function(e){ alert('你輸了!'); }); }

十三、網頁座標 - 了解 screen、page、client 箇中差異

  • screen 是整個螢幕的解析度的座標點
  • PAGE 以整個網頁寬高為主,y軸拖曳軸多長都會算
  • CLIENT 是以瀏覽器窗口計算

十四、事件監聽優化篇 - 從父元素來監聽子元素內容

//只有點選到li時才會出現alert var al = document.querySelector('.list');//先選取整個父元素,在從這個範圍內篩選我要的 al.addEventListener('click',function(e){ if(e.target.nodeName != 'LI'){return}; alert(e.target.textContent); },false);

拾、localStorage - 瀏覽器資料儲存

一、setItem、getItem 基本操作

1.儲存當地資料:

localStorage.setItem('key',儲存的資料);

2.讀取當地資料:

localStorage.getItem('key');

<label for="name">請輸入你的名字</label> <input type="text" class="inputName"> <input type="button" class="enterBtn" value="點擊"> <input type="button" class="callBtn" value="呼叫">
//宣告變數 var inputValue = document.querySelector('.inputName'); var enter = document.querySelector('.enterBtn'); var call = document.querySelector('.callBtn'); //函式編寫 function save(e){ var str = inputValue.value; localStorage.setItem('Name',str); //儲存資料 } function callName(e){ var str = localStorage.getItem('Name'); //讀取資料 alert('儲存的名字是'+str); //監聽 enter.addEventListener('click',save,false); call.addEventListener('click',callName,false); }

3.刪除個別數據

localStorage.removeItem('key')

4.刪除所有數據

localStorage.clear()

二、透過 JSON.parse、JSON.stringify 來編譯資料

因為LocalStorage只能把資料存成String,所以收到Array資料時必須做編譯

1. JSON.stringify

  • 將Array轉成String
    JSON.stringify(陣列名稱)

2. JSON.parse

  • 將String轉成Array
    JSON.parse(陣列名稱)
var farms = [ { farmer: 'Toma', //文字記得要括號 }, { farmer: 'Mike', }, ]; var farmsString = JSON.stringify(farms);//將物件轉為字串 localStorage.setItem('farmer',farmsString);//字串才能儲存 var farmsArray = JSON.parse(farmsString);//將字串轉為物件 console.log(farmsArray[1].farmer);//物件及陣列才能讀取 //console: Mike

三、data-* - 透過 dataset 讀取自訂資料

HTML內的data-*

在html內可以自訂data-名稱="數字或字串"

JS讀取

var 變數名稱 = e.target.dataset.data名稱;

<ul class="list"> <li data-num="0" data-cat="3">吉米</li> <li data-num="0" data-cat="1">米zo</li> </ul>
var dataGet = document.querySelectorAll('.list li'); function add(e){ var num = e.target.dataset.num; var cat = e.target.dataset.cat; console.log('編號' + num + ',貓'+cat+'隻'); } var temp = document.querySelector('.list'); var len = temp.getElementsByTagName('li').length; for(var i=0 ; i<len ; i++){ dataGet[i].addEventListener('click',add,false); }

四、dataset、array 運用

選取大範圍的ul,不要單選小範圍的ul li,
使用e.target.nodeName去限定選取的標籤,如果不是li就使用return中斷。

<ul class="list"> </ul>
var data = [{ farmer : '卡斯柏', }, { farmer : '喬恩', }, ]; var el = document.querySelector('.list'); function dataCount(e){ var dataLen = data.length; var str =''; for(var i = 0 ; i<dataLen ; i++){ var count = data[i].farmer; str += '<li data-num="' + i + '">第' + i + '個農夫是' + count +'</li>'; } el.innerHTML = str; //使用innerHTML更新陣列資料 } dataCount(); el.addEventListener('click',function(e){ var ta = e.target.nodeName; //選取nodeName if(ta !== 'LI'){return;};//如果不是LI就return var num = e.target.dataset.num;//選取dataset資料 console.log(data[num].farmer); });

四、splice - 刪除 array 資料

splice

  • 陣列名稱.splice(位置,刪除數量);
var data = [{ farmer : '卡斯柏', }, { farmer : '喬恩', }, { farmer : '喬瑟夫', }, ]; var el = document.querySelector('.list'); function dataCount(e){ var dataLen = data.length;//dataLen要寫在方程式裡面,不然再次宣告時會找不到。 var str =''; for(var i = 0 ; i<dataLen ; i++){ var count = data[i].farmer; str += '<li data-num="' + i + '">第' + i + '個農夫是' + count +'</li>'; } el.innerHTML = str; } dataCount(); el.addEventListener('click',function(e){ var num = e.target.dataset.num; if(e.target.nodeName !== 'LI'){return;}; data.splice(num,1); dataCount(); });

拾壹、瀏覽器功能探索 (BOM)

一、瀏覽器功能簡介

  • window
    • history:歷史紀錄
    • frames:iframe插件
    • location: 目前位置href
    • DOM: document html、element
    • screen: 目前使用裝置寬高
    • navigator: 瀏覽器版本、是否連上網

二、回上頁功能實作

  • 第一次第一頁不能用JS的下一頁功能,因為還沒有history
  • 第二次紀錄完後就可以使用了
<h1>第一頁</h1> <a href="b.html">連到第二頁</a> <br> <a href="#" id="next">下一頁(JS版)</a> <script> document.getElementById('next').onclick = function () { window.history.forward(); } </script>

-這時因為有history就可以回到上一頁了。

<h1>第二頁</h1> <input type="button" id="back" value="回到上一頁"> <script> document.getElementById('back').onclick = function () { window.history.back(); } </script>

三、透過 JS 設計列印功能

document.getElementById('print').onclick = function () { window.print()//出現列印畫面 } document.getElementById('locat').onclick = function () { console.log(location)//顯示location資料 } document.getElementById('open').onclick = function () { window.open('http://www.google.com.tw')//新開視窗轉址到指定網址 }

四、動態擷取瀏覽器高度 - innerHeight

  • innerHeight:因為瀏覽器上面有工具欄,顯示屏又有工作列,所以會被擠掉。
  • outerHeight:整個瀏覽器的高度
  • 透過window.innerHeight來擷取網頁高度
document.querySelector('.hero').style.height = window.innerHeight+"px"; //當使用者一開始打開瀏覽器時,讀取到的瀏覽器高度 window.onresize = function(){ document.querySelector('.hero').style.height = window.innerHeight+"px" } //當使用者調整瀏覽器高度時(onresize),更新瀏覽器高度

拾貳、JS 開發邏輯思維養成

    1. 資料model:先處理好資料的新增、刪除、修改
    1. 事件event:使用者行為觸發程式
    1. 介面View

init為一開始要注入的初始資料。

拾叁、AJAX

一、透過 XMLHttpRequest 物件跨瀏覽器撈資料

1、readyState:0 (var xhr = new XMLHttpRequest())

產生出XMLHttpRequest,但還沒連接

2、readyState:1 (xhr.open())

  • 使用了open(),但還沒完送資料出去
  • open('格式','讀取的網址',同步與非同步)
    格式 : get(讀取資料)、post(傳送資料到伺服器)

3、readyState:2

使用send

4、readyState:3

loading

5、readyState:4

數據已經接收到

var xhr = new XMLHttpRequest(); xhr.open('get','https://hexschool.github.io/ajaxHomework/data.json',true); xhr.send(null);

二、 AJAX 非同步觀念

open('格式','讀取的網址',同步與非同步)

  • 非同步true: 不會等值撈回來,程式就會繼續往下跑,等到回傳時,才會自動回傳
  • 同步false: 會等值撈回來,程式才繼續往下跑

但因為同步如果資料量太龐大,網頁會等太久,通常會使用非同步。

1.如何使用非同步讀取資料

xhr.onload = function(){ //onload代表確認資料有回傳回來 console.log(xhr.responseText); var str = JSON.parse(xhr.responseText); document.querySelector('.message').textContent = str[0].name; }

三、HTTP狀態碼

xhr.onload = function(){ if(xhr.status == 200){ var str = JSON.parse(xhr.responseText); document.querySelector('.section2').textContent = str[0].name; }else{ alert('資料錯誤'); } }
  • 1xx - 參考資訊 (Informational)
    這些狀態碼代表主機先暫時回應用戶端一個狀態,所以在接收一般的回應之前,用戶端應準備接收一個或多個 1xx 的回應。我以前在寫 ASP 的時候比較有看到 IIS 使用到這些狀態碼回應,在 Apache 的環境我還未曾遇到過。
    • 100 - 繼續。
    • 101 - 切換通訊協定。
    • 2xx - 成功 (OK)
  • 2xx - 狀態碼表示伺服器成功接收到用戶端要求、理解用戶端要求、以及接受用戶端要求。
    • 200 - 確定。 用戶端要求成功。
    • 201 - 已建立。
    • 202 - 已接受。
    • 203 - 非授權資訊。
    • 204 - 無內容。
    • 205 - 重設內容。
    • 206 - 部分內容。
    • 207 - 多重狀態 (WebDAV) 這好像只有在 IIS 中才有,HTTP/1.1 並沒有定義這個狀態。這狀態會出現在可以包含多個不同回應代碼 (視子要求數量而定) 的 XML 訊息之前。
  • 3xx - 重新導向 (Redirection)
    用戶端瀏覽器必須採取更多動作才能完成要求。例如:瀏覽器可能必須重新發出 HTTP Request 要求伺服器上的不同頁面。
    • 301 - 要求的網頁已經永久改變網址。此狀態要求用戶端未來在連結此網址時應該導向至指定的 URI。
    • 302 - 物件已移動,並告知移動過去的網址。針對表單架構驗證,這通常表示為「物件已移動」。 要求的資源暫時存於不同的 URI 底下。 由於重新導向可能偶而改變,用戶端應繼續使用要求 URI 來執行未來的要求。 除非以 Cache-Control 或 Expires 標頭欄位表示,此回應才能夠快取。
      ASP.NET 預設的 Response.Redirect 方法,就是以 302 Found 做回應。
    • 303 - 通知 Client 連到另一個網址去查看上傳表單的結果(POST 變成 GET),當使用程式作網頁轉向時,會回應此訊息。
      ASP.NET 中要輸出 HTTP 303 轉向的程式碼如下:
      Response.StatusCode = 303;
      Response.RedirectLocation = "/PageB.aspx";
    • 304 - 未修改。用戶端要求該網頁時,其內容並沒有變更,應該回傳 304 告知網頁未修改。此時用戶端僅需要取得本地快取(Local Cache)的副本即可。
    • 305 - 要求的網頁必須透過 Server 指定的 proxy 才能觀看 ( 透過 Location 標頭 )
    • 306 - (未使用) 此代碼僅用來為了向前相容而已。
    • 307 - 暫時重新導向。要求的網頁只是「暫時」改變網址而已。
  • 4xx - 用戶端錯誤 (Client Error)
    這代表錯誤發生,且這錯誤的發生的原因跟「用戶端」有關。例如:用戶端可能連結到不存在的頁面、用戶端的權限不足、或可能未提供有效的驗證資訊(輸入的帳號、密碼錯誤)。下次看到 4xx 的回應千萬不要傻傻的一直查程式哪裡寫錯誤了(不過也有可能是程式造成的)。
    • 400 - 錯誤的要求。
    • 401 - 拒絕存取。 IIS 定義數個不同的 401 錯誤,以表示更詳細的錯誤原因。 這些特定的錯誤碼會顯示在瀏覽器中,但不會顯示在 IIS 記錄檔中:
    • 401.1 - 登入失敗。
    • 401.2 - 因為伺服器設定導致登入失敗。
    • 401.3 - 因為資源上的 ACL 而沒有授權。
    • 401.4 - 篩選授權失敗。
    • 401.5 - ISAPI/CGI 應用程式授權失敗。
    • 401.7 - Web 伺服器上的 URL 授權原則拒絕存取。 這是 IIS 6.0 專用的錯誤碼。
    • 403 - 禁止使用。 IIS 定義數個不同的 403 錯誤,以表示更詳細的錯誤原因:
    • 403.1 - 禁止執行存取。
    • 403.2 - 禁止讀取存取。
    • 403.3 - 禁止寫入存取。
    • 403.4 - 需要 SSL。
    • 403.5 - 需要 SSL 128。
    • 403.6 - IP 位址遭拒。
    • 403.7 - 需要用戶端憑證。
    • 403.8 - 網站存取遭拒。
    • 403.9 - 使用者過多。
    • 403.10 - 設定無效。
    • 403.11 - 密碼變更。
    • 403.12 - 對應程式拒絕存取。
    • 403.13 - 用戶端憑證已撤銷。
    • 403.14 - 目錄清單遭拒。
    • 403.15 - 超過用戶端存取授權數量。
    • 403.16 - 用戶端憑證不受信任或無效。
    • 403.17 - 用戶端憑證已經過期或尚未生效。
    • 403.18 - 無法在目前的應用程式集區中執行要求的 URL。 這是 IIS 6.0 專用的代碼。
    • 403.19 - 無法在這個應用程式集區中執行用戶端的 CGI。 這是 IIS 6.0 專用的代碼。
    • 403.20 - Passport 登入失敗。 這是 IIS 6.0 專用的錯誤碼。
    • 404 - 找不到。
    • 404.0 - (無) – 找不到檔案或目錄。
    • 404.1 - 無法在要求的連接埠上存取網站。
    • 404.2 - 網頁服務延伸鎖定原則阻止這個要求。
    • 404.3 - MIME 對應原則阻止這個要求。
    • 405 - 用來存取這個頁面的 HTTP 動詞不受允許 (方法不受允許)。
    • 406 - 用戶端瀏覽器不接受要求頁面的 MIME 類型。
    • 407 - 需要 Proxy 驗證。
    • 412 - 指定條件失敗。
    • 413 - 要求的實體太大。
    • 414 - 要求 URI 太長。
    • 415 - 不支援的媒體類型。
    • 416 - 無法滿足要求的範圍。
    • 417 - 執行失敗。
    • 423 - 鎖定錯誤。
  • 5xx - 伺服器錯誤 (Server Error)
    這代表錯誤發生,且這錯誤發生的原因跟「伺服器」有關。伺服器因為發生錯誤或例外狀況(Exception)而無法完成要求(Request)時,就會回應 5xx 的錯誤,且這肯定跟伺服器有關。
    • 500 - 內部伺服器錯誤。
    • 500.12 - 應用程式正忙於在 Web 伺服器上重新啟動。
    • 500.15 - 不允許直接要求 Global.asa。
    • 500.16 – UNC 授權認證不正確。 這是 IIS 6.0 專用的錯誤碼。
    • 500.18 – 無法開啟 URL 授權存放區。 這是 IIS 6.0 專用的錯誤碼。
    • 500.19 - 此檔案的資料在 Metabase 中設定不當。
    • 500.100 - 內部的 ASP 錯誤。
    • 501 – 標頭值指定未實作的設定。
    • 502 - Web 伺服器在作為閘道或 Proxy 時收到無效的回應。
    • 502.1 - CGI 應用程式逾時。
    • 502.2 - CGI 應用程式中發生錯誤。
    • 503 - 服務無法使用。 這是 IIS 6.0 專用的錯誤碼。
    • 504 - 閘道逾時。
    • 505 - 不支援的 HTTP 版本。

四、AJAX POST 寫法

var xhr = new XMLHttpRequest(); xhr.open('get','https://hexschool-tutorial.herokuapp.com/api/signin',true); xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');//post-api最常用的格式 xhr.send('email=asad@gmail.com&password=12345678');

五、AJAX 作業

var loginSend = document.querySelector('.js-loginSend'); var signupSend = document.querySelector('.js-signupSend'); var login = function(e){ var loginMail = document.querySelector('.js-loginMail').value; var loginPwd = document.querySelector('.js-loginPwd').value; var loginAlert = document.querySelector('.js-loginAlert'); var loginArr = {}; loginArr.email = loginMail; loginArr.password = loginPwd; var xhrLogin = new XMLHttpRequest(); xhrLogin.open('post','https://hexschool-tutorial.herokuapp.com/api/signin',true); xhrLogin.setRequestHeader('Content-type','application/json'); xhrLogin.send(JSON.stringify(loginArr)); xhrLogin.onload = function(){ console.log(xhrLogin); var callBackLogin = JSON.parse(xhrLogin.responseText); loginAlert.textContent = callBackLogin.message;//助教建議修改 } } var signup = function(e){ var signupMail = document.querySelector('.js-signupMail').value;; var signupPwd = document.querySelector('.js-signupPwd').value;; var signupAlert = document.querySelector('.js-signupAlert'); var signupArr = {}; signupArr.email = signupMail; signupArr.password = signupPwd; var xhrSignup = new XMLHttpRequest; xhrSignup.open('post','https://hexschool-tutorial.herokuapp.com/api/signup',true); xhrSignup.setRequestHeader('Content-type','application/json'); xhrSignup.send(JSON.stringify(signupArr)); xhrSignup.onload = function(){ console.log(xhrSignup); var callBackSignup = JSON.parse(xhrSignup.responseText); signupAlert.textContent = callBackSignup.message;//助教建議修改 } } loginSend.addEventListener('click',login,false); signupSend.addEventListener('click',signup,false);

拾參、ECMAScript 6 入門 - let、const

let和const是用來宣告區塊裡的變數。

一、let - if、function 用法

1.使用let避免汙染到全域變數

二、const 特性

1.特性:唯讀,不能去做修改

const a = 10; a = 11; //Uncaught TypeError

2.可以修改的特例

  • 陣列和物件
const obj = { url:'http://dd.com' } obj.url = 'http.xx.com'; console.log(obj); //"http.xx.com"
  • 如何不被修改Object.freeze()
const obj = { url:'http://dd.com' } Object.freeze(obj);//凍結 obj.url = 'http.xx.com'; console.log(obj); //'http://dd.com'

3.let、const 注意事項與使用時機

  • 不會向上提升
console.log(a); let a =1 console.log(a);
  • 不可重複命名
  • 不會被放到window全域變數裡面

參考網站

拾肆、ECMAScript 6 入門 - 字串篇

一、Template literals - 輕鬆進行字串相加

innerHTML

在原本字串相加的部分可以改由${img}

title.innerHTML = `<div>${img}</div>`