1.遇到域要分兩步:第一預解析,第二逐行讀代碼 2.變量和屬性本質是一個東西,不過變量是自由的,而屬性是屬於某個對象的, 同理得出, 函數也是自由自在的不屬於誰, 而方法也是屬於某個對象的! 3. js中,this 誰發生事件就是誰! 全局的變量和函數,默認都是window的. object是空白對象. var obj = new Object(); 工廠方式構造對象: 1.原料: var obj = new Object() 2.加工: 添加屬性和方法 3.出廠: return 對象出去. 工廠方式構造對象缺點: 1. 沒有new 2.alert( p1.showName == p2.showName) //false,每一個對象都有本身一套資源,極其浪費資源 補充知識點 var a = function(){alert("abc")} //本質是 var a = new Function("alert('abc')"); var b = function(){alert("abc")} alert(a==b)//false; prototype 原型: 擴展系統或自定義類的通用的功能,全部對象公用一套! 能夠添加屬性或方法,通常是添加方法用 class 改變一類元素的樣式 Array.prototype.sum = function(){} 行間樣式: 改變一個元素的樣式 arr1.sum = function(){...} //蛋撻和蛋撻模子 類: 蛋撻模子,不具有實際功能,只能用來構造對象 對象(實例) : 蛋撻 ,具有實際功能 在js當中構造函數就是類,類就是構造函數! 通用規則: 不一樣的東西放在構造函數,相同的東西放在原型中! 構造函數:初始化屬性 prototype:方法作成通用的,全部對象都同樣 面向對象: 越是通用的東西,越是臃腫龐大 1.前提:全部代碼都必須在window.onload,window.onload做用是初始化整個程序(與構造函數同樣) 2.this面向對象中是極其噁心! 3.改錯: this this啥時候會出問題?? 1.定時器 2.事件 setInterval(this.show,1000)//但凡被定時器調用的函數,this指的都是window對象 解決的方法: 1.再套一層 2. var _this = this; 把對象換個名字,省的與定時器或事件中this重名 setInterval(function(){_this.show();},1000) 面向過程--->面向對象 1.函數拎到window.onload外面,把局部變量改爲全局變量(暫時) 2.幹掉window.onload,變成構造函數 3.把全局變量變成屬性,拎到外面的函數變成prototype(變成屬性或方法後不要忘了加this) 4.兩個地方的this要作手腳(定時器,事件),由於與window的this,矛盾. 5.解決方法: 存this, var _this = this; 事件上套一層, this.oDiv.onmousedown = fnDown;改爲 this.oDiv.onmousedown = function(){ _this.fnDown(); } 測試: window.onload = function(){ new Drag('div1') } drag限制範圍: 繼承 子集具有了父集的屬性和方法 Person : 屬性:name sex 方法:showName showSex Worker 屬性: *name *sex job(職位) 方法: *showName *showSex showJob Coder 程序員 屬性: *name *sex *job(職位) language(語言) 方法: *showName *showSex *showJob showLanguage php 中字符串鏈接用點. +號就是加號 美圓符號$ 等於js中的var -> 代替js或java中的點表明調用 obj.show() == obj->show() Class Person{ function _construct($name, $sex){ //構造函數 $this->name = $name; $this->sex = $sex; } function showName(){ echo $this->name; } function showSex(){ echo $this->sex; } } $p1 = new Person('blue','male'); $p1->showName(); class Worker extends Person{ function_construct($name, $sex, $job){ parent::_construct($name, $sex);//先執行父級構造函數 $this ->job = $job; } function showJob(){ echo $this->job; } } $w1 = new Worker('blue','female','打雜的'); $w1.showJob();// 構造函數中的this 實際上指的就是new出來的對象 function Worker(name, sex, job){Person.call(this, name, sex);} // this 就是 new 出來的worker對象ow1 構造函數假裝:Person.call(this, name, sex);//等於java中的super.name super.sex調用父級的屬性 經過原型來繼承父級的方法又叫原型鏈: Worker.prototype = Person.prototype; // 至關於java中的super(name,sex) //一個房子有兩把鑰匙,張三拿鑰匙1到房間拿走了沙發,那麼李四拿鑰匙2進去一看沙發是否是少了?!反之亦然 js中引用: 房子和鑰匙(引用),js中全部的對象都是引用 var arr1 = [1,2,3,4]; var arr2 = arr1; arr2.push(5) alert(arr1)//1 2 3 4 5 alert(arr2)// 1 2 3 4 5 // 若是隻想給arr2添加數據,arr1不變; 建立不一樣的引用 var arr1 = [1,2,3,4] var arr2 = [] for(var i in arr1){ arr2[i] = arr1[i]; } arr2.push(5) //------------- Worker.prototype = Person.prototype;//風險很大!由於是引用賦值,至關於多配了一把鑰匙 //一旦子類添加或刪除方法會把父級的方法添加或刪除!因此必須引用不一樣的變量for循環遍歷賦值 for(var i in Person.prototype){ Worker.prototype[i] = Person.prototype[i]; } //typeof 和 instanceof var arr = [1,2,3] alert(arr instanceof Object) //true // function LimitDrag(id){ Drag.call(this,id);//繼承父級的屬性 } for(var i in Drag.prototype){ LimitDrag.prototype[i] = Drag.prototype[i];//繼承父級的方法 } //限制拖動範圍就是重寫方法 LimitDrag.prototype.fnmove = function(ev){ var oEvent = ev || window.event; var l = oEvent.clientX - this.disX; var t = oEvent.clientY - this.disY; if(l < 0){ l = 0; }else if(l > document.documentElement.clientWidth - this.oDiv.offsetWidth){ l = document.documentElement.clientWidth - this.oDiv.offsetWidth; } if(t < 0){ t = 0; }else if(t > document.documentElement.clientHeight - this.oDiv.offsetHeight){ t = document.documentElement.clientHeight - this.oDiv.offsetHeight } 宿主對象:Dom === document ; BOM === window; 本地對象,非靜態對象,用的時候須要new 內置對象,靜態對象,用的時候不須要用直接用 Global MATH eval()能夠將任何形式的字符串轉換成js對象 parse() 只能解析json形式的字符串轉換成js對象 ;推薦 安全性高點,可是屬性必須加字符串 var str = '{"age":18, "name":"chenk"}';//在使用parse轉換時候age和name屬性必須加雙引號 var json = JSON.parse(str); alert(json.name); 焦點:三種方式 點擊 tab js 如何默認給焦點? focus方法給指定的元素設置焦點! obj.focus()//獲取焦點 obj.blur()//取消焦點 obj.select()//全選 點擊按鈕全選? btn.onclick = function(){oText.select()} 只能選中用戶輸入的內容,但p標籤div等中的文字就選中不了 event事件對象,當事件發生的時候,全部的信息都會保存到事件對象中 飛機上的黑匣子! 注意必須用事件調用才能拿到event對象! ie/chrome : event是內置全局的; var event; ff: window.event; 若是函數是被事件調用,那麼函數的第一個參數就是事件對象,參數名字無所謂 e,ev,event function fn1(ev){alert(event);} fn1(ev);// 不是事件調用因此event沒東西 document.onclick = fn1; //事件調用的函數,因此event有內容 事件流: 事件冒泡: 點擊等事件有內往外 應用:全部的事情讓父級去作,本身不作 div1包含div2包含div3 三個div同時綁定同一個函數!當點擊div3的時候,div2也被點擊了,div1也被點擊了,這就是冒泡! 阻止冒泡:event.canelBubble = true; 事件捕獲: ie下沒有,在綁定事件中,標準下是有的! 綁定事件的幾種方式: //第一種賦值形式,後面的函數會覆蓋前面的函數 document.onclick = fn1; document.onclick = fn2;//覆蓋fn11,只有fn2 //第二種方式, 事件名稱有on ie: obj.attachEvent(事件名稱,事件函數); obj.attachEvent('onclick',fn1); obj.attachEvent('onclick',fn2); this指向的是window,讓人極其不能容忍 標準: obj.addEventListener(事件名稱,事件函數,是否捕獲)//false不捕獲就是冒泡 this指向的是觸發該事件的對象 如何解決this指向的問題!!! 函數下的一個方法call()中的一個參數能夠改變函數執行過程當中的內部this指向的問題 若是第一個傳入的是null,那麼傳入的就是window! 封裝一個通用的方法 function bind(obj, evname,fn){ if(obj.addEventListener){ obj.addEventListener(evname, fn, false); }else{ obj.attachEvent('on'+evname,function(){ fn.call(obj); } } } //實現多個綁定 bind(document,'click',fn1); bind(document,'click',fn2); bind(document,'click',fn3); 如何取消事件綁定? 第一種: document.onclick = null;// 置空 第二種: ie: obj.detachEvent(事件名稱,事件函數) 標準: obj.removeEventListener(事件名稱,事件函數,是否捕獲) 三: 鍵盤事件 onkeydown默認是上一次的值而不是當前的值 onkeyup 當前值 event.keyCode: ctrlKey, shiftKey, altKey 布爾值 document.onkeydown = function(ev){ var ev = ev || window.event; alert(ev.keyCode) } 如何鍵盤控制div移動? 事件默認行爲阻止? return false; 右鍵菜單事件: oncontextmenu 又名環境菜單!不一樣的地方彈出的內容不一樣! 拖拽原理: 1.選中元素 oDiv. onmousedown 1.2.移動: document.onmousemove oDiv.style.left = 鼠標左邊-dealtaX便可 1.3.到達目的地 document.onmouseup document.onmousemove = onmouseup = null; 鼠標點到最左邊最上邊的距離 ev.clientX div到最左邊和最上邊的距離 oDiv.offsetLeft 問題: 如何解決拖動鼠標太快,div跟不上的問題? oDiv 的移動事件改爲它的父級document, disX = ev.clientX - this.offsetLeft; document.onmousemove = function(ev){ var ev = ev || window.event; oDiv.style.left = ev.clientX - disX + 'px'; oDiv.style.top = ev.clientY - disY +'px'; } 問題2:如何解決拖拽的時候若是有文字或圖片被選中會產生問題? 分析:當鼠標按下的時候,若是頁面中文字被選中,就會觸發瀏覽器默認拖拽文字的效果 標準下:return false;阻止默認事件的發生 非標準(ie):aInput[0].setCapture();//設置全局捕獲,把全部其餘元素的事件替換成本身事件 本身的事件會覆蓋其餘全部的事件 釋放: up中,if(oDiv.releaseCapture){oDiv.releaseCapture()} 最終: if(oDiv.setCapture){oDiv.setCapture()} 拖拽的封裝,限制範圍,磁性吸附 限制範圍:在移動中限制元素的(Left 和top值)範圍 L = ev.clientX - disX;//元素距離左邊的距離 左邊:L < 0 設置 L = 0 右邊: 可視區寬度- 元素自身的寬度 L > ll 設置成 L = ll; var ll = document.documentElement.clientWidth - obj.offsetWidth 上下同左右; var tt = document.documentElement.clientHeight - obj.offsetHeight 磁性吸附: 把L < 0 改爲L <100 ,當小於100時候一拉就過去了 拖拽改爲層大小 左右拖拽實現左右大小,上下拖動改變上下大小 碰撞檢測: 位置是否重合! 九宮格,假如當前image 在5號位,那麼在其餘8個位置不要緊 滾動條: 核心:滾動區域 和 滾動條 滾動條主要目的是控制其餘元素好比圖片文字的放大等 公式: T/MT = H/MH ; 求H var iScale = T / MT document.title = iScale; 控制內容的滾動!設置內容的top值,文字沒有top值因此要把文字放入div中 鼠標滾輪事件: onmousewheel 滾輪向上div變大,反之變小 ie/chrome: onmousewheel ; event.wheelDelta//下:-120 上:120 ff: addEventListener ; event.detail //上:-3 下3 oDiv.addEventListener('DOMMouseScroll',fn.false)//非標準下不行 改寫成:只在標準下才綁定事件 if(oDiv.addEventListener){ oDiv.addEventListener('DOMMouseScroll',fn.false) } //如何肯定滾輪的 上下判斷? var b = true; if(ev.wheelDelta > 0){ //ie或chrome下 b = ev.wheelDelta > 0 ? true : false; }else{ //ff下 b = ev.detail < 0 ? true : false; } //如何解決滾輪滾動,滾動條的事件 //return false阻止的 obj.on事件名稱 = fn; 所觸發的默認行爲(on事件) 也能阻止attachEvent的默認綁定事件 addEventListener綁定的事件須要經過event下面的preventDefault()來阻止 if(ev.preventDefault){ ev.preventDefault(); } return false; Cookie: 存儲數據用相似變量但能夠設置存儲時間! 變量是臨時存儲在內存中關閉瀏覽器就沒了! 1. 不一樣瀏覽器存放的cookie位置不能通用 2. cookie的存儲是以域名的形式保存在硬盤中,新浪的百度的,搜狐的... 3. 存儲格式 key-value document.cookie = 'zhangsan=26'; 4. 讀取都是經過 document.cookie document.cookie = 'age=26'; document.cookie = 'username=zhangsan'; 獲取的時候每一個cookie之間經過分號加空格串聯起來 "age=26; username=zhangsan" 5. 一個域名下存放的cookie的個數有限制,內容大小有限制 6.cookie默認是臨時存儲的,當關閉瀏覽器後自動銷燬 var oDate = new Date(); oDate.setDate(oDate.getDate() + 5);//五天後 document.cookie = 'username=zhangsan;expires='+oDate.toGMTString();//五天後失效,注意時間必須是字符串格式 //如何解決存儲特殊值 \n中文等? 內容最好編碼存放 encodeURI()和decodeURI() document.cookie = 'username=\n你好zhangsan;expires='+oDate.toGMTString(); //會出問題 document.cookie = 'username='+encodeURI('\n你好zhangsan')+';expires='+oDate.toGMTString(); //如何經過key 拿到value function getCookie(key){ var arr1 = document.cookie.split('; ');//以分號加空格切割字符串 for(var i = 0 ; i < arr1.length; i++){ var arr2 = arr1[i].split('='); if(arr2[0] == key){ return decodeURI(arr2[1]); } } } function setCookie(key, value, invalidTime){ var oDate = new Date(); oDate.setDate(oDate.getDate()+invalidTime); document.cookie = key + '=' + value + ';expires=' + oDate.toGMTString(); } function removeCookie(key){ setCookie(key,'',-1); } 事件高級應用1 1.但凡能帶括號的類型都是function,好比abc(),$.(); typeof($)//function 如何取到按鈕上的value值 obj.attr('value'); 選擇器僅僅用來選擇對象的 方法纔是真正改變! 運動: 1.div運動---定時器每隔50毫秒 offsetLeft 增長x(var iSpeed= 10) px 問題1: 如何到指定的地方停? if(oDiv.offsetLeft >= 500 ) clearInterval(timer) 問題2:到達目的地後繼續點擊按鈕仍是慢慢往前跑? 清除定時器僅僅是下次不執行,本次仍是要執行的? 因此當到達了目的地的時候,再點擊按鈕,div仍是會往前iSpeed個px!如何解決?? 把div的left值放到else中 if()else() 問題3: 不斷點擊按鈕,移動出問題!!!! 定時器惟一! 分析:每點擊一次按鈕就會開一個定時器. 解決: 每次執行定時器的時候,先把前面的定時器關了 var timer = null; clearInterval(timer);//防止屢次點擊建立多個定時器,每次建立前把前一個刪掉 timer = setInterval(function(){},30); 問題4:如何控制方向讓步長加或減 if(oDiv.offsetLeft < iTarget) iSpeed爲正數反之爲負數 2016/10/7 AJAX 一: 瀑布流: 固定列:統一寬度不統一高度,分批加載,浮動佈局 非固定列: 列數會隨着頁面大小改變, 定位實現 今天討論的是固定列,寬度相等高度不等 列的高度是0,經過ajax分批加載,動態填充到3個li,非按照順序上來,而是按照高度來 不能讓li相差太多 一個ul裏面包括四個li,每一個li中包含div包含img和p 1.引入自定義的ajax.js庫 2. getPics.php--接口,cpage=1--參數,請求第幾頁的數據,data是返回過來的數據 window.onload = function(){ ajax('get','getPics.php','cpage=1',function(data){ alert(data)//亂,能夠到瀏覽器中的network中的preview }); } window.onload = function(){ var oUl = document.getElementById('ul1'); var aLi = oUl.getElementById('li'); var iLen = aLi.length; var iPage = 1; var isOpen = true;//默認門是開的 getList(); //初始化數據 function getList(){ ajax('get','getPics.php','cpage='+iPage,function(data){//返回的data是字符串須要解析成對象 var data = JSON.parse(data); if(!data.length){ return; } for(var i = 0; i<data.length; i++){ //獲取高度最短的li的下標 var _minIndex = getShortLi(); var oDiv = document.createElement('div'); var oImg = document.createElement('img'); oImg.src = data[i].preview;//json對象直接點訪問 oImg.style.width = '225px'//隨意設置 oImg.style.height = data[i].height * (225 / data[i].width)+'px';//高度也要按照縮放比例 var oP = document.createElement('p'); oP.innerHTML = data[i].title; oDiv.appendChild(oImg); oDiv.appendChild(oP); aLi[_minIndex].appendChild(oDiv); } }); } window.onsrcoll = function(){ var _index = getShortLi(); var oLi = aLi[_index]; var scrollTop = document.documentElement.scrollTop || document.boby.scrollTop;//獲取滾動條的滾動距離 var visiualHeight = document.documentElement.clientHeight;//可視區高度 if(getTop(oLi) + oLi.offsetHeight < scrollTop + visiualHeight){ if(isOpen){ isOpen = false; iPage++; getList(); isOpen = true;//或者在getList()for循環結束後設置爲true } } } function getShortLi(){ var minIndex = 0; var ih = aLi[minIndex].offsetHeight; for(var i=1; i<iLen; i++){ if(aLi[i].offsetHeight < ih){ minIndex = i; ih = aLi[minIndex].offsetHeight; } } return minIndex; } function getTop(obj){ var iTop = 0; while(obj){ iTop += obj.offsetTop; obj = obj.offsetParent; } return iTop; } } //如何解決圖片加載速度小於for循環的速度,致使圖片的填充出現有的地方很長 //有的地方很短! 答案: 讓圖片加載完成後再去找最短的index,for循環改爲遞歸! 或者讓後端傳遞圖片高度和寬度能夠 oImg.style.width = '225px'//隨意設置 oImg.style.height = data[i].height * (225 / data[i].width)+'px';//高度也要按照縮放比例 問題3: 什麼時候去加載下一批數據? 最短一列li底部是否進入可視區!!! 若是: li的底部距離到頂部的距離大於可視區底部到頂部的距離,未進入可視區不用加載 反之:li的底部到頂部的距離小於可視區底部到頂部的距離,進入了加載 li的top值+li自身的高度 < 滾動條滾動高 + 可視區高度 須要加載 問題4:拉一下滾動條會加載不少頁面,需求是拉一次加載一頁 答案:標識位 設置一個flag var b = true; 到ATM的時候設置爲false,取完錢(事情作完了)改爲true if(b){//只有沒鎖門才能進去取錢 b = false;//一旦進去馬上鎖門讓別的人進不來 iPage ++; getList();//取錢,記得取完錢把b改爲true,把門打開讓別人也能取錢 } 問題5:若是數據加載完了,拖動滾動條也不能加載! 非空判斷很重要 在getList();要作判斷 if(!data.length){ return; } 四:留言本項目 用戶表 留言表 引入庫: ajax.js 和 guestbook.js 1 驗證用戶名信息 在php中有個方法叫作 verifyUserName() 光標離開後經過ajax發送用戶名到後端 window.onload = function(){ var oUsername = document.getElementById('username'); var oUsernameMsg = document.getElementById('msg');//驗證用戶名提示信息... var oUser = document.getElementById('user');//歡迎某某的欄 var oUserInfo = document.getElementById('userInfo')//歡迎某某的欄的span標籤 var oReg = document.getElementById('reg');//註冊模塊 var oLogin = document.getElementById('login');//登陸模塊 //0 初始化 updateUserStatus(); function updateUserStatus(){ var uid = getCookie('uid'); var user = getCookie('user'); if(uid){ //登陸狀態 oUser.style.dispay = 'block'; oUserInfo.innerHTML = user; oReg.style.display = 'none'; oLogin.style.display = 'none'; }else{ oUser.style.display = 'none'; oUserInfo.innerHTML = ''; oReg.style.display = 'block'; oLogin.style.display = 'block'; } } //1.驗證用戶名 oUsername.onblur = function(){ ajax('get','guestbook/index.php','m=index&a=verifyUserName='+this.value,function(data){ //alert(data);或者network中找到XHR點擊請求再找到preview 格式化數據 var data = JSON.parse(data);//返回的是json字符串解析成對象 oUsernameMsg.innerHTML = data.message;//message是json對象的key if(data.code){//若是是錯誤信息就把提示信息變成紅色 oUsernameMsg.style.color = 'red'; }else{ oUsernameMsg.style.color = 'green'; } }); } //2.註冊 var oPassword = document.getElementById('password'); var oRegBtn = document.getElementById('btnReg'); oRegBtn.onclick = function(){ ajax('post','guestbook/index.php','m=index&a=reg&username='+encodeURI(oUsername.value)+'&password='+oPassword.value,function(data){ var data = JSON.parse(data); //alert(data.message); }); } //3.登陸 var oUsername1 = document.getElementById('username1'); var oPassword1 = document.getElementById('password1'); var oLoginBtn = document.getElementById('btnLogin'); oLoginBtn.onclick = function(){ ajax('post','guestbook/index.php','m=index&a=reg&username='+encodeURI(oUsername1.value)+'&password='+oPassword1.value,function(data){ var data = JSON.parse(data); //alert(data.message); if(!data.code){//若是登陸成功 updateUserStatus(); } }); } //4.用戶退出 經過ajax var oLogoutBtn = document.getElementById('btnLogout'); oLoginBtn.onclick = function(){ ajax('post','guestbook/index.php','m=index&a=logout',function(data){ var data = JSON.parse(data); //alert(data.message); if(!data.code){//若是退出成功 updateUserStatus(); } }); } //5.獲取cookie值 function getCookie(key){ var arr1 = document.cookie.split("; "); for(var i=0; i<arr1.length; i++){ var arr2 = arr1[i].split('='); if(key == arr2[0]){ return arr2[1]; } } } }