國慶七天收穫--

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];
			}
		}
	}
}
相關文章
相關標籤/搜索