JS高級程序設計2

面向對象 ,基本模式、對象字面量模式、工廠模式、構造函數模式、原型模式、組合構造函數和原型模式、其餘模式見電子書:動態原型模式、寄生構造函數模式(不推薦)、穩妥構造函數模式(要求安全的環境,不使用new 和 this)javascript

//面向對象
/* 【 數據屬性】
*  configurable  true 經過 delete刪除屬性來修改屬性
*  enumberable  true  經過 for-in 返回屬性
*  writable true 修改屬性值
*  value 數據值
*  es5 經過 Object.defineProperty(obj,屬性名,對象{} ) 可對以上修改
*  屬性名爲 configurable/enumerable/writable/value
*  把 configurable 設置爲 false後,就沒法再設置爲true 了,
*  調用 Object.defineProperty() 默認屬性名都爲 false
* */
var person = {}
Object.defineProperty(person,"name",{
  writable: false,  // 阻止修改屬性值
  value:'xiaoming'
})
console.log(person.name)
person.name = 'xxx';
console.log(person.name)
/* 【訪問器屬性】
* configurable  false
* enumerable
* get函數  默認 undefined
* set函數  默認 undefined
* 添加get set函數
* */
var book = {
  _year: 2014,  // 下劃線表示只能經過對象方法訪問的屬性,可直接訪問
  edition:1
}
Object.defineProperty(book,'year',{
  get:function () {
    return this._year
  },
  set:function (val) {
    if(val> 2014){
      this._year = val
      this.edition += val - 2004
    }
  }
})
book.year = 2015;
console.log(book.edition);
console.log(book._year);
/* 同時定義多個屬性用   Object.defineProperties() 複數 */
/* 經過 Object.getOwnPropertyDescriptor() 可查看 數據屬性和 訪問器屬性各個值
*  js中任何對象,包括DOM對象和BOM對象都有 Object.getOwnPropertyDescriptor() 方法
*
* */
var desc =Object.getOwnPropertyDescriptor(book,'_year')
console.log(desc.value);
console.log(desc.configurable);
var desc2 =Object.getOwnPropertyDescriptor(book,'year')
console.log(desc2.value);  // undefined
console.log(desc2.configurable); // false

/* 【1.通常模式 】*/
var obj = new Object()
obj.name='name'
console.log('name: '+obj.name);

/* 2.對象字面量 */
var obj2 = {
  name: 'mama'
}
console.log('mama: '+obj2.name);

/*【 3.工廠模式】 */
function cretePerson(name,age) {
  var o = new Object();
  o.name = name;
  o.age = age;
  o.sayName =function () {
    console.log('xx: ' + this.name);
  }
  return o;
}
var person1 = cretePerson('kang',22)
person1.sayName()
/* 【4.構造函數模式】*/
function Person(name, age) {
  this.name=name;
  this.age=age;
  this.sayName2=function () {
    console.log(this.name + 'abccde')  // 等同於  this.sayName2 = new Function('...') 每次實例化都會 new Function(),這是缺陷
  }
}
var per2 = new Person('xiao',33) // Person() 當成構造函數用,有 new
per2.sayName2()
console.log(per2 instanceof Person);

// Person('kangddd',44) //  Person() 當成普通函數用,
// window.sayName2();

var per3 = new Person('aa',33)
var per4 = new Person('bb',33)  // 實例化兩個對象,裏面有 sayName() 方法,ECMAScript中函數也是對象,每定義一個函數,就是實例化一個對象
console.log('ddd333' + (per3 == per4));  // + 號優先級比 == 高
console.log('eeefff' + false);

/* 【5.原型模式】
* 每一個函數都有 prototype(原型)屬性,是一個指針,指向一個對象
* 對象實例共享 prototype 定義的屬性和方法
* */
function PersonSix() {

}
PersonSix.prototype.name = 'li'
PersonSix.prototype.sayName3=function () {
  console.log(this.name);
}
var per10 = new PersonSix();
per10.sayName3() // 先查找 per10有沒有sayName3()方法,有則返回,沒有則查找 prototype是否有 sayname3()方法


/* 每建立一個函數,都有prototype */
function test() {
  return 1
}
console.log(test); // 輸入函數  function test(){}
console.log(test.prototype); // 返回一個對象  每建立一個函數,都有 prototype
console.log(test.prototype.constructor);  //  返回 函數  function test(){}

function Person100() {

}
Person100.prototype.name='100name'
Person100.prototype.age='100age'
var p100 = new Person100()
var p101 = new Person100()
p100.name = '110name'  // 實例中新增同名屬性覆蓋 原型中的 name
console.log(p100.name);  //  '110name'
console.log(p101.name); //   '100name'
delete p100.name;  // 經過  delete 能夠找回 原型中的 name
console.log(p100.name); //   '100name'

console.log(p100.hasOwnProperty('name'));  //  判斷實例是否有某屬性  hasOwnProperty
console.log('name' in p100);  // name存在於實例或者原型都會返回 true
console.log(Object.keys(Person100.prototype));  // ['name','age'] 拿到全部原型屬性的數組
console.log(Object.getOwnPropertyNames(Person100.prototype));  // ['constructor','name','age'] 拿到全部原型屬性的數組
console.log('ok ? ' + (p100.constructor == Person100));  // 簡化前 這裏是 true

/* 簡化原型語法*/
function Car() {

}
Car.prototype={
  constructor: Car, // 手動指定 constructor ,省略後, car.constructor 就再也不指向  Car
  name:'baoma',
  age:22
}
var car = new Car()
console.log(car.name);
console.log(Car.prototype.constructor);
console.log(car.constructor == Car);  // 簡化後,這裏返回 false

/* 在 String.prototype中能夠找到 substring() 方法 */

/* 原型模式的缺陷是 若是對象中的屬性是引用類型,如 數組 , 那麼某個實例修改了數組,另外一個實例也拿到了修改後的數據  */

function Dog() {

}
Dog.prototype={
  constructor:Dog,
  friends:['kang','jia']
}
var f1 = new Dog()
var f2 = new Dog()
f1.friends.push('hehe')
console.log(f1.friends);  // ['kang','jia','hehe']
console.log(f2.friends); // ['kang','jia','hehe']

/* 【組合使用構造函數械和原型原式 】*/
function Pig(name,age) {  // 屬性寫在構造函數中
  this.name = name;
  this.age= age;
  this.friends = ['dd','ee']
}
Pig.prototype={     // 方法寫在原型中
  constructor: Person,
  sayName:function () {
    console.log(this.name);
  }
}
var pig1 = new Pig('piga',11)
var pig2 = new Pig('pigb',12)
pig1.friends.push('ff')
console.log(pig1.friends);
console.log(pig2.friends);
console.log(pig1.friends === pig2.friends);  // false
console.log(pig1.sayName === pig2.sayName);  // true
View Code

 閉包css

/* 面向對象繼承方法 見 6.3.4原型式繼承,一個對象繼承另外一個不一樣的對象 更好的是 6.3.6寄生組合式繼承 */
var a = function () {
  return 5;
}
console.log(a());
/* 遞歸    嚴格模式下不能用  arguments.callee時的寫法,加多了一個括號,加多一個函數名 */
var factorial = (function f(num) {
  if (num <= 1) {
    return 1;
  } else {
    return num * f(num - 1)
  }
})
console.log(factorial(5));
/* 普通函數fn被調用時,會建立一個包含 this/arguments/參數val的活動對象, 全局執行環境的變量對象(包含this、res、fn)在執行環境的做用域鏈中則處於第二位*/
function fn(val) {
  return 5 + val
}
var res = fn(4)

/* 閉包:指有權訪問另外一個函數做用域中的變量的函數,建立閉包的常見方式,就是在一個函數內部建立另外一個函數*/
function createComparison() {
  return function (obj1, obj2) { // 內部函數會將外部函數  createComparison的活動對象 this等都添加到它的做用域鏈中,所以閉包比通常函數會佔用更多內存,少用
    // ...
  }
}
// 閉包做用域鏈使閉包只能取得包含函數中任何變量的最後一個值
function fn2() {
  var result = new Array();
  for (var i = 0; i < 10; i++) {
    result[i] = function () {
      return i;
    }
  }
  return result;
}
console.log(fn2()); // 不懂
// 閉包中的 this 指向 window, this通常狀況下,誰調用指代誰
var name = 'window'
var obj = {
  name: 'obj',
  getName: function () {
    return function () {
      return this.name
    }
  }
}
console.log(obj.getName());  // function(){ return this.name} 調用 getName() 返回一個函數 ,
console.log(obj.getName()()); // 'window'  調用 getName()() 就會當即調用它返回的函數,即返回一個字符串

function assign() {
  var element = document.getElementById('a');
  var id = element.id
  element.onclick = function () {
    console.log(id);
  }
  element = null; // 把 element 設置爲 null , 手動在閉包中釋放內存
}

function f2() {
  for (var i = 0; i < 10; i++) {
    console.log(i);
  }
  console.log(i); // undefined 還能夠訪問,i是定義在f2()函數的活動對象中的
  // console.log(j); // error  not defined
}
console.log(f2());

function f3() {
  (function () {
    for (var i = 0; i < 10; i++) {
      console.log(i);
    }
    console.log(i); // 10   (function(){ ... })() 塊級做用域,外部訪問不到,可使用本身定義的變量,不受其餘干擾
  })()
//  console.log(i);  // error not defined   i 在塊級做用域中,外部訪問不到,
}
f3()

function Test() {
 var num = 1078;
 return num;
}
console.log(Test()); // 函數名能夠大寫、中文,
/*
* 特權方法
* */
function f4() {
  var num4 = 4;
  function getNum() {
    return false
  }
  // 特權方法
  this.publicNum = function () {
    return num4
  }
  // 特權方法
  this.publicMothod = function () {
    return getNum()
  }
  //  return num4; 不想返回,能夠寫個方法返回 ,並用對象的構造函數模式返回
}
console.log(f4());
console.log(new f4().publicMothod());
console.log(new f4().publicNum());


var f6 = function () {
  console.log(666);
}()
View Code

 setTimeout()    少用setInterval()   history()  location.replace()  不能後退到當前頁面html

var age = 29; // 使用var 定義後,把 configurable 設置爲false 阻止 delete 【面向對象 數據屬性 configurable 】
window.color='red'
delete window.age;
delete window.color;
console.log(window.age); // 29
console.log(window.color); // undefined   使用window來定義變量color,能夠被 delete
// ECMAScript 是 js的核心,在web中使用js,則BOM是web(window location navigator )核心

// 使用 setTimeout() 超時調用, 少用間歇調用setInterval() ,須要 clearInterval
var num = 0;
var max = 60;
function minute() {
  max--;
  console.log(max);
  if (max > num) {
    setTimeout(minute, 1000)
  } else {
    console.log('ok');
  }
}
setTimeout(minute, 1000) // 倒計時效果
/* location.search  */
var url = 'http://www.baidu.com?name=kang&age=12'
console.log(location.search); // ?name=kang&age=12
/* 取消後退按鈕用 location.replace() */
setTimeout(function () {
  location.replace('http://www.baidu.com')  // 不能後退到以前的頁面
},1000)
location.reload() // 從新加載 (有可能從緩存中加載 )
location.reload(true) // 從新加載 (從服務器中加載 )
history.go(1)  // 前進一頁  history.forward()
history.go(-1) //後退一頁  history.back()
//
if(history.length == 0){
  // 這是用戶打開窗口後的第一個頁面 
}
View Code

 倒計時 setTimeout()   不用 setInterval() java

倒計時
<p id="num">60</p>
<script>
  var max = document.getElementById('num').innerHTML
  var num = 0;
  function minute() {
    max--;
    document.getElementById('num').innerHTML = max
    console.log(max);
    if (max > num) {
      setTimeout(minute, 1000)
    } else {
      console.log('ok');
    }
  }
//  setTimeout(minute, 1000)
</script>
View Code

 document  getElementByClassName classList  readyState  compatMode  outerHTMLnode

console.log(document.title);  // 標題
console.log(window.location.href);
console.log(document.URL); // 網址
console.log(document.domain); // 域名
/*
*  document.forms  全部<form>元素
*  document.images 全部 <img>元素
*  document.links 全部帶 href的<a>元素
*  document.anchors 全部帶 name的<a>元素 描點
* */
document.write('<script src = "1.js"></script>')
/* 文本 節點分割 */
var element = document.createElement("div")
var textNode  = document.createTextNode('hello world')
element.appendChild(textNode)
document.body.appendChild(element)
var newNode = element.firstChild.splitText(5)  // 文本節點分割
console.log(element.firstChild.nodeValue);
console.log(newNode.nodeValue);

/*
*   <div class="a"></div>
* */
document.getElementsByTagName('div')[0].innerHTML = 444
document.querySelector('.a').innerHTML = 123
document.getElementsByClassName('a')[0].innerHTML = 888  // h5 新增  getElementsByClassName

/*
*   h5 增長  classList 方法     for(var i = 0;i<div.classList.length; i++){...}
*  <div class = 'a b c'>ddd</div>
*  div.classList.remove('a') // 刪除a 樣式    add() 添加     toggle('c') 切換樣式   contains('d') 包含樣式
* */

/*
*  h5  DOM焦點功能
*  document.activeElement  判斷得到焦點是哪一個元素
*  document.hasFocus() 是否得到焦點了
* */
var button = document.getElementById('mybtn')
button.focus();
console.log(document.activeElement === button); //  true
console.log(document.hasFocus()); // true

/*
*  h5 文檔加載屬性   readyState    loading 加載中    complete 加載完成
*  if(document.readyState == 'complete'){ ... // 文檔加載完成 }
* */

/*
*   渲染模式
 *
* */
if(document.compatMode == 'CSS1Compat'){
  console.log('standards mode');  // 標準模式
}else {
  console.log('quirks mode'); // 混雜模式
}
console.log(document.charset); // utf-8
// h5 新增 document.head (chrome和 safari5 實現了)
var head = document.head || document.getElementsByTagName('head')[0];
/*
*  outerHTML
* <div id="mydiv" data-apptest = '12345' data-appName="hehe">div</div>
* */
document.getElementById('mydiv').outerHTML="<p>this is p</p>"
/* 把 mydiv整個html片段 替換爲 新的內容 */
/*
* <div id="mydiv" data-apptest = '12345' data-appName="hehe">div</div>
* 在 div同級以前、以後插入元素,在div裏面內容以前、以後插入元素   beforebegin   afterbegin  beforeend  afterend
* 使用 innerHTML outerHTML insertAdjacentHTML  要先把原來的元素相關的事件給刪除,減小內存佔用
* */
document.getElementById('mydiv').insertAdjacentHTML('beforebegin','<p>pppp</p>')
View Code

 js刪除元素的行內樣式 removeProperty()    cssText 添加多個樣式android

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>abc</title>
</head>
<style>
  .p3{
    position: absolute;top:22px;left:33px;
    color: red;
  }
</style>
<body>
<div id="test">d</div>
<div style="border: 1px solid green;width:200px;height: 300px;position: relative;" >
  <p style="position: absolute;top:22px;left:33px;color:blue;" id="test2">dddddd</p>
  <p style="" class="p3" id="test3">dddddd</p>

</div>
<script src="0.js"></script>
原型對象 p167
<script>
  /*  刪除樣式,取得默認屬性
  *  cssText 批量添加樣式、 removeProperty() 刪除樣式  h5的classList 也能夠刪除樣式
  *   removeProperty() 在不肯定某個給定的CSS屬性擁有什麼默認值的狀況下,能夠移除相應的屬性,就能夠爲元素應用默認值
  * */
  var test = document.getElementById('test')
  test.style.color='red'
  test.style.cssText='font-size:50px;color:blue;'  //添加多個樣式
  var prop,val
  for(var i =0;i<test.style.length;i++){
//    console.log(test.style[i]);
    prop = test.style[i]
    val = test.style.getPropertyValue(prop)
    console.log(prop + " : " + val);
  }
  test.style.removeProperty('color')

  document.getElementById('test2').style.removeProperty('position')
  document.getElementById('test2').style.removeProperty('color')
  document.getElementById('test3').style.removeProperty('color') // 只能刪除行內式,樣式選擇器的刪除不了

  /* getComputedStyle(a,b) a:元素, b:僞元素字符串,如 :after ,沒有傳 null   ie不支持,用currentStyle   其餘瀏覽器返回值,如border值不一致*/
  var computedStyle = document.defaultView.getComputedStyle(test,null)
</script>
</body>
</html>
View Code

 js 讀取樣式表的屬性  能夠動態添加 樣式 insertRule ie用addRule    刪除樣式 deleteRule() ie用 removeRule() 不經常使用ios

<style>
  .test{
    background: blue;
    width:110px;
    height:220px;
  }
  .box{
    background: red;
    width:100px;
    height:200px;
  }
</style>
<body>
<script>
  var sheet = document.styleSheets[0];
  var rules = sheet.cssRules || sheet.rules;
  console.log(rules[0].selectorText);  // 讀取樣式表的屬性值
  console.log(rules[1].style.cssText);
  console.log(rules[0].style.background);
  console.log(rules[0].style.width);
  console.log(rules[0].style.height);
</script>
View Code

偏移量 offset  客戶區大小  client 滾動大小 scrollTop web

偏移量
offset  內容+padding+border
offsetHeight offsetWidth offsetLeft offsetTop  p12.2.3 元素大小

客戶區大小
client  內容+padding
clientHeight  clientWidth     document.documentElement.clientWidth  低版本用  document.body.clientWidth

滾動大小
 scrollHeight 元素內容高度
 scrollWidth 元素內容寬度   document.documentElement.scrollWidth
 scrollLeft
 scrollTop

getBoundingClientRect()  DOM遍歷、DOM範圍chrome

每一個元素都有 getBoundingClientRect() , 返回一個矩形對象 left top right bottom   ie8不一致
  DOM遍歷 p12.3 NodeIterator、TreeWalker   ie不支持
   DOM範圍 p12.4
View Code

 事件 event對象  currentTarget target thiswindows

<script>
  /*  事件都會傳 event對象 , ie8之前由 window.event 得到,若是ie使用 <input type='text' onclick="alert(event.type)"> 這裏的event就能夠直接獲取 ,跟DOM同樣
  currentTarget target this
   通常狀況下,currentTarget === this === target , 當點擊區域變大了後, target會變成點擊目標,如body,如button等,而 this和currentTarget永遠表示調用的對象,這裏是body*/
  document.body.onclick=function (e) {
    console.log(e.type); // 'click'   'mouseover'等
    console.log(e.currentTarget === this);
    console.log(e.target === this);
    console.log(e.target);  // 點哪一個是哪一個  button  或  body
    console.log(this);   // 誰調用是誰 body
  }

</script>

js訪問form元素簡寫 、 addEventListener()   事件冒泡 stopPropagation()

<body>
<form action="" name="form1">
  <input type="text" name="username">
  <input type="button" onclick="console.log(username.value)" value="click"> <!-- 輸入的值  表單簡寫  -->
  <input type="button" onclick="console.log(this.value)" value="btn">   <!--  btn -->
  <input type="button" onclick="console.log(value)" value="btn22">   <!--  btn22  表單簡寫 -->
</form>
<!-- addEventListener('click',function(){},false)
false 表示在冒泡階段調用事件處理程序,即從當前元素,如div 往上一級,body 等促發
 true 表示在捕獲階段調用事件處理程序,即從body-> div 再到 body的促發,先由外到內的捕獲,再由內到外的冒泡

-->
<!--
/* 取消連接的默認行爲,如連接跳轉,使用  e.preventDefault()
   * 取消事件冒泡,使用 stopPropagation()
   * */
-->
<div id="mydiv" style="border: 1px solid green;width: 200px;height: 200px;">
  <button id="btn">btn</button>
</div>
<script>
  // 只有在事件處理期間,event對象纔會存在,一旦事件處理完成,event對象就會被銷燬
  document.getElementById('btn').onclick=function (e) {
    e.stopPropagation()  // 阻止後,就不影響
    console.log('btn'); // 點擊btn時,也會點到外面的mydiv,會輸入兩行
  }
  document.getElementById('mydiv').onclick=function () {
    console.log('mydiv');
  }
</script>
</body>

 事件   event

/* 【電子書 13.4】
*  load  頁面加載後 window.onload , 全部框架加載完,在框架上觸發, 圖片加載完,在img上觸發, object嵌入內容加載完在 object上觸發
*  unload 頁面卸載 window.unload ,全部框架卸載完,在框架上觸發, object嵌入內容卸載完在 object上觸發 ,從一個頁面切換到另外一個頁面就會發生 unload事件,多用於清除引用,避免內存泄漏
*  abort 用戶中止下載過程時,若是嵌入的內容沒有加載完,在<object>上觸發
* error 當發生javascript錯誤時在window上面觸發,當沒法加載圖像在img觸發,當沒法加載嵌入內容在<object>觸發
* select 當選擇文本框input 或 textarea 中一或多個字符時觸發
* resize 當窗口或框架大小變化在 window 觸發, 最大化、最小化也會觸發
* scroll 當滾動帶滾動條的元素中的內容時,在該元素上面觸發 body元素包含所加載頁面的滾動條
*
* <script> 在ie9+ 中,只有設置了script的src屬性,並添加該元素到文檔後,纔會開始加載js文件
*  事件中的 shift ctrl alt meta(指windows鍵盤中的windows鍵,在蘋果機 Cmd鍵 )
*  e.shiftKey   e.ctrlKey  e.altKey e.metaKey
*  鼠標左中右鍵  e.button  0 表示左鍵 1 表示鼠標滾輪 2表示鼠標右鍵
*  mousewheel 鼠標滾輪事件 有一個 e.wheelDelta 屬性,當用戶向前滾動鼠標時  wheelDelta是120的倍數,向後滾動鼠標,wheelDelta是-120的倍數
*  火狐用 e.DOMMouseScroll 保存在 e.detail 當用戶向前滾動鼠標時  wheelDelta是 -3 的倍數,向後滾動鼠標,wheelDelta是3的倍數
*
*  觸摸設備  ios 和 android 沒有鼠標, 沒有 dbclick
*  輕擊可觸發  mousemove事件,若是該操做會致使內容變化,將再也不有其餘事件發生,若是屏幕沒有所以變化,那麼會依次發生 mousedown mouseup 和 click 事件
*  mousemove事件也觸發 mouseover mouseout事件
*  兩個手指在屏幕上且頁面隨手指移動而滾動時會觸發mousewheel和scroll事件 (好像沒啥用)
*
*  keydown 用戶按下鍵盤任意鍵觸發,按住不放,會重複觸發
*  keypress 鍵盤字符鍵、esc鍵觸發,按住不放,會重複觸發
*  textInput 文本事件,對keypress的補充,在文本插入文本框以前觸發textInput 事件
*  用戶按下鍵盤的字符鍵後,先觸發 keydown事件、再觸發 keypress事件,再觸發 keyup事件, keydown和keypress是在文本框發生變化以前觸發的。 keyup是文本框發生變化以後觸發的。
*  【電子書 13.4.4】
* */

pageX  offsetX  screenX clientX  鼠標左中右鍵,滾輪事件 頁面切換事件 unload

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>abc</title>
</head>
<body>
this is 0.html
<script>
  window.onunload=function () {
    console.log('unload'); // 頁面跳轉,離開當前頁面會執行,頁面刷新也會執行
  }
</script>
<div id="a" style="border: 6px solid green;width:200px;height: 200px;padding:10px;">div</div>
<div id="b" style="border: 6px solid green;width:200px;height: 200px;padding:10px;">div</div>
<div id="c" style="border: 6px solid green;width:200px;height: 200px;padding:10px;">div</div>
<script>
  document.getElementById('a').onclick=function (e) {
    console.log(e.clientX);
    console.log(e.pageX);  // 以瀏覽器爲起點,頁面不滾動,二者一致, 頁面滾動,pageX包括滾動條的值
    console.log(e.screenX); // 相對當前屏幕,以PC桌面左上角爲起點
    console.log(e.offsetX);  // 限制在點擊區域內的位置,除去邊框和外邊距
  }
  document.getElementById('b').addEventListener('mousedown',function (e) {
    console.log(e.button);  // 判斷鼠標左中右鍵     e.button的值  0 是左鍵 1 是鼠標滾輪  2是右鍵
  },false)
  document.getElementById('c').addEventListener('mousewheel',function (e) {
    console.log(e.wheelDelta);
  },false)
  document.getElementById('c').addEventListener('DOMMouseScroll',function (e) {
    console.log(e.detail);  // 火狐用  DOMMouseScroll
  },false)
</script>
</body>
</html>

 contextmenu冒泡事件 右鍵菜單

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>abc</title>
</head>
<body>
contextmenu冒泡事件 上下文菜單(右鍵菜單)

<div id="mydiv" style="border: 1px solid green;width:800px;height: 1000px;">右鍵菜單</div>
<div id="mymenu" style="border: 1px solid green;width:200px;height:200px;display:none;position: absolute;top:80px;left:20px;">右鍵菜單
</div>

<script>
  // 右鍵菜單
  var mydiv = document.getElementById('mydiv')
  var mymenu = document.getElementById('mymenu')
  mymenu.addEventListener('contextmenu', function (e) {
    e.preventDefault() // 阻止默認的瀏覽器右鍵菜單
  })
  mydiv.addEventListener('contextmenu', function (e) {
    e.preventDefault()  // 阻止默認的瀏覽器右鍵菜單
    mymenu.style.left = e.clientX + 'px'
    mymenu.style.top = e.clientY + 'px'
    mymenu.style.display = 'block'
  })
  document.addEventListener('click', function () {
    mymenu.style.display = 'none'
  })
</script>
<script>
  window.addEventListener('beforeunload',function (e) {  // 窗口關閉時,彈窗是否關閉
    var res = 'abc'
    e.returnValue=res  // ie能夠
    return res  // chrome 返回不了'abc'
  })
</script>
load事件會在頁面中一切都加載完畢時觸發,包括一堆外部資源
DOMContentLoaded事件則在造成完整的DOM樹以後就會觸發,不理會圖像、JS文件、css文件是否已經下載完畢,用戶能夠早點與頁面進行交互 ie9+支持
不支持的瀏覽器,處理以下  setTimeout(function(){ ... },0); // 不必定有效
readystatechange事件 chrome不支持! ie、firefox支持
pageshow和pagehide事件  在瀏覽器後退和前進按鈕時緩存數據,不會用 ,ie9不兼容
hashchange事件 url中'#'號後面的字符串發生變化時,監聽事件
window.addEventListener('hashchange',function(e){console.log(location.hash);})  ie8+ 支持
手機設備旋轉事件 deviceorientation devicemotion    android版 webkit ?
觸摸事件 touchstart touchmove(調用 preventDefault()能夠阻止滾動 ) touchend
觸摸事件(包括鼠標事件的順序,會冒泡)
touchstart / moseover / mousemove(一次) / mousedown / mouseup /click/ touchend
手勢事件(要兩個手指在元素範圍內才觸發,會冒泡,只放一個手指會觸發 touchstart事件) ios才支持
gesturestart
gesturechange
gestureend
</body>
</html>
相關文章
相關標籤/搜索