Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 中文一区二区,日韩中文字幕电影在线观看 ,亚洲依依成人综合网址首页

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JavaScript入門簡介

          JavaScript入門簡介

          么是 JavaScript

          JavaScript,我們一般簡稱為 JS,是一種具有函數優先的輕量級,解釋型或即時編譯型的編程語言。

          JavaScript 現在已經被用到了很多非瀏覽器環境中,JavaScript 基于原型編程、多范式的動態腳本語言,并支持面向對象、命令式和聲明式風格。

          HTML、CSS、JavaScript三者不同的功能:

          • HTML:定義網頁的內容。
          • CSS:描述頁面的布局。
          • JavaScript:指定網頁的行為。

          JavaScript 基本特點

          JavaScript 是一種屬于網絡的腳本語言,已經被廣泛用于 Web 應用開發,常用來為網頁添加各式各樣的動態功能,為用戶提供更流暢美觀的瀏覽效果。通常 JavaScript 腳本是通過嵌入在 HTML 中來實現自身的功能的(就是寫在 HTML 頁面中的 <script> 標簽中)。

          JavaScript 的基本特點如下所示:

          • Javascript 是一種解釋性腳本語言,代碼不進行預編譯。
          • Javascript 主要作用是用來向 HTML 頁面添加交互行為。
          • Javascript 代碼可以直接嵌入 HTML 頁面,但寫成單獨的 .js 文件有利于結構和行為分離。
          • 腳本語言,Javascript 腳本語言同其他語言一樣,有它自身的基本數據類型,表達式和算術運算符及程序的基礎程序框架。
          • 跨平臺特性,JavaScript 腳本語言不依賴于操作系統,僅需要瀏覽器的支持。在絕大多數瀏覽器的支持下,可以在 Windows、Android、Linux、Mac、IOS 等平臺下運行。

          JavaScript 可以做一些什么事情

          JavaScript 可以做一些什么事情呢,我們下面簡單的介紹一下,可能還沒學過 JavaScript 的同學看不懂,不要急,后面我們都會詳細的介紹。

          • 直接寫入 HTML 輸出流,如下所示,我們可以直接在 JavaScript 中寫入HTML 代碼:
          <script type="text/javascript">
            document.write("<h1>俠課島</h1>");
            document.write("<p>俠課島歡迎你!</p>");
          </script>
          
          • 對事件作出反應,可以使用 onclick 在HTML元素上綁定事件:
          <button type="button" onclick="alert('俠課島')"> 點擊彈出 </button>
          
          • 修改 HTML 中的內容,例如自定義一個 change() 方法,然后綁定到按鈕上:
          <body>
            <p id="content">原來的內容</p>
            <button type="button" onclick="change()">點擊修改</button>
          </body>
          <script type="text/javascript">
            function change(){
              document.getElementById('content').innerHTML='新的內容'
            }
          </script>
          
          • JavaScript 還可以實現改變 HTML 圖像,例如通過 <img> 標簽的 src 屬性來改變一張 HTML 圖像,如下所示:
          <body>
            <button onclick="changeImage()">修改圖片</button>
            <div>
              <img id="myImage" src="./img/part1-01.jpg">
            </div>
          </body>
          <script type="text/javascript">
            function changeImage(){
              element=document.getElementById('myImage');
              if(element.src.match("02")){
                element.src="./img/part1-01.jpg";
              }else{
                element.src="./img/part1-02.jpg";
              }
            }
          </script>
          
          • JavaScript 可以用來改變 HTML 樣式,例如:
          <p id="style">JavaScript改變HTML樣式</p>
          
          //點擊之后呈現的效果是:顏色變綠
          <button type="button" onclick="document.getElementById('style').style.color='green'">點擊</button>
          
          • 驗證輸入,例如:
          if isNaN(x) {alert("不是數字")};
          

          本節我們基本講了一下JavaScript是什么,它能做什么,下一節我們講JavaScript最基本的語法,學習一門語言,我們都要先弄清楚這門語言的基本語言,才好開始編寫代碼。

          .為何學習 JavaScript?

          ?JavaScript 是 web 開發者必學的三種語言之一:
          HTML 定義網頁的內容----[制作網頁]----簡單枯燥
          CSS 規定網頁的布局和樣式—[美化網頁]
          HTML+CSS—網頁—沒有動態的網頁【1.無動態效果 2.數據沒有動態化】
          JavaScript 對網頁行為進行編程【動態效果,數據動態加載】
          2. 什么是JavaScript?
          ?? 1.javascript和java是完全不同的語言,不論是概念還是設計。
          ?? 網景----瀏覽器【Netscape Navigator】----LiveScript-----JavaScript
          ?? 微軟----瀏覽器[IE]----JScript
          …等等
          ?? ECMA—歐洲計算機廠家協會–ECMA-262標準—ECMAScript
          ?? 2.JavaScript面向對象的腳本程序設計語言
          ?? 面向對象—編程思想
          ?? 腳本程序—依據一定的格式編寫的可執行文件【直接運行】
          ?? 3.JavaScript使用
          ??1.標記的事件中使用

          <!DOCTYPE html>
          <html>
          	<head>
          		<meta charset="utf-8">
          		<title></title>
          	</head>
          	<body>
          		<h1>1.標記的事件中使用</h1>
          		<input type="button" value="測試Javascript的使用" 
          		onclick="alert('歡迎使用Javascript')" />
          	</body>
          </html>
          
          


          2.script標記中的使用
          ?? script–<script>javascript程序</script>
          ?? 位置–<head>標記中/<body>標記中【最后】

          <!DOCTYPE html>
          <html>
          	<head>
          		<meta charset="utf-8">
          		<title></title>
          		<script type="text/javascript">
          			alert("歡迎使用JavaScript!");
          		</script>
          	</head>
          	<body>
          		<h1>script標記的中使用</h1>
          		<h1>script標記出現在head標記中</h1>
          		<input type="button"  value="測試javascript的使用" onclick="test1();" />
          	</body>
          </html>
          
          


          <!DOCTYPE html>
          <html>
          	<head>
          		<meta charset="utf-8">
          		<title></title>
          	</head>
          	<body>
          		<h1>script標記的使用</h1>
          		<h1>script標記出現在body標記中</h1>
          		<input type="button" value="測試JavaScript的使用" onclick="test1()" />
          		<script type="text/javascript">
          			function test1(){
          				alert("歡迎使用javascript!");
          			}
          		</script>
          	</body>
          </html>
          
          


          3.外部腳本—將JavaScript程序編寫到獨立的文件【.js】,通過<script>標記提供的src屬性將獨立的文件【.js】,導入到html文件中。
          ?? 您可以在<head>或<body>中放置外部腳本引用。
          ?? 格式:<script src=“js 文件路徑”></script>
          獨立的jsWENJIAN 【myscript1.js】
          function test1(){
          ?alert("歡迎使用javascript!”);
          }
          .js文件

          function test1(){
          	alert("歡迎使用JavaScript!")
          }
          

          html文件

          <!DOCTYPE html>
          <html>
          	<head>
          		<meta charset="utf-8">
          		<title></title>
          		<script src="javascript.js" type="text/javascript" charset="utf-8"></script>
          	</head>
          	<body>
          		<h1>script外部腳本使用</h1>
          		<input type="button"  value="測試JavaScript的使用" onclick="test1();" />
          	</body>
          </html>
          
          


          3.JavaScript 輸出
          JavaScript能夠以不同方式“顯示”數據:
          ?? 1.使用window.alert()寫入警告框
          ?? 2.使用document.write()寫入HTML輸出
          ?? 3.使用innerHTML寫入HTML元素
          ?? 4.使用console.log()寫入瀏覽器控制臺

          <!DOCTYPE html>
          <html>
          	<head>
          		<meta charset="utf-8">
          		<title></title>
          	</head>
          	<body>
          		<h1>1.使用window.alert()寫入警告框</h1>
          		<!--
          		<script type="text/javascript">
          			window.alert("測試window.alert()寫入警告框")
          		</script>
          		-->
          		<h1>2.使用document.write()寫入HTML輸出</h1>
          		<!--
          		<script type="text/javascript">
          			document.write("測試document.write()寫入HTML輸出")
          		</script>
          		-->
          		<h1>3.使用innerHTML寫入HTML元素</h1>
          		<p id="p1"></p>
          		<!--
          		<script type="text/javascript">
          			document.getElementById("p1").innerHTML="<font size='7'>測試innerHTML寫入HTML元素</font>"
          		</script>
          		-->
          		<h1>4.使用console.log()寫入瀏覽器控制臺</h1>
          		<script type="text/javascript">
          			console.log("console.log()寫入瀏覽器控制臺")
          		</script>
          	</body>
          </html>
          
          


          4.JavaScript 語句
          JavaScript 語句由以下構成:
          ?? 值、運算符、表達式、關鍵詞和注釋。
          ?? document.getElementById(“demo”).innerHTML=“Hello Kitty.”;
          “Hello Kitty.”----值
          ??=— 賦值運算符
          ?? 關鍵詞–常常通過某個關鍵詞來標識需要執行的 JavaScript 動作


          注釋–解釋說明代碼的含義/調試程序【注釋的內容不會被執行】
          // 單行注釋 【保證一行代碼被注釋掉不會被執行】
          /*
          多行注釋 【保證多行代碼被注釋掉不會被執行】
          // 可以包含單行注釋
          */

            <script>
          			/*
          			//console.log("console.log() 寫入瀏覽器控制臺");
          			console.log("console.log() 寫入瀏覽器控制臺");
          			console.log("console.log() 寫入瀏覽器控制臺");
          console.log("console.log() 寫入瀏覽器控制臺");
          			*/
          		</script>
          
          

          分號 ; 表示一條javascript語句的結束。
          ??可以將有分號的語句寫在同一行,通常我們都不這么寫,出錯以后查找不方便,所以一行一句。
          JavaScript代碼塊【{代碼塊}】
          function myFunction(){
          ??document.getElementById(“demo”).innerHTML=“Hello Kitty.”;
          ??document.getElementById(“myDIV”).innerHTML=“How are you?”;
          }
          5.JavaScript 語法
          JavaScript 值
          JavaScript 語句定義兩種類型的值:混合值和變量值。
          混合值被稱為字面量(literal)— 常量值
          寫數值有無小數點均可:12.5 1001
          寫字符串:”zhangsan”
          變量值被稱為變量[程序運行的最小單位]保存數據值。
          需要通過var 關鍵詞 來定義變量
          用法1 : var a; //定義變量
          ??a=1001; //變量賦值
          用法2: var b=”hello”;
          JavaScript 運算符
          JavaScript使用算是運算符(+ - * /)來計算值。
          JavaScript使用(=)賦值運算符。
          JavaScript使用(> <==>=<=!=)比較運算符。
          JavaScript使用(|| && !)邏輯運算符。

          JavaScript表達式
          表達式是值、變量和運算符的組合,計算結果是值。
          100+123【算數表達式】
          var b=“hello”; 【賦值表達式】
          12>23 【關系表達式】
          (12>23)&&(23<12) —【邏輯表達式】

          JavaScript 標識符
          標識符就是為JavaScript元素【函數,變量,對象…】起名字的字符串。
          1.可以由字母、下劃線(_)或美元符號($),數字組成,數字不能開頭。
          2.不能用關鍵詞
          3.區分大小寫
          駝峰式命名規則—首字母大寫【FirstName, LastName, MasterCard, InterCity.】
          JavaScript 程序員傾向于使用以小寫字母開頭的駝峰大小寫
          6. JavaScript 變量
          ??JavaScript 變量是存儲數據值的容器。
          ??JavaScript 數據類型
          ??在編程中,文本值被稱為字符串。
          ??JavaScript 可處理多種數據類型,但是現在,我們只關注數值和字符串值。
          ??字符串被包圍在雙引號或單引號中。數值不用引號。
          ??如果把數值放在引號中,會被視作文本字符串。
          ??true/false 布爾型
          ??null null型
          聲明(創建) JavaScript 變量
          在 JavaScript 中創建變量被稱為“聲明”變量。
          您可以通過 var 關鍵詞來聲明 JavaScript 變量:
          var carName;
          聲明之后,變量是沒有值的。(技術上,它的值是 undefined。)我們在使用的變量的時候需要賦予初始值,否則被視為未定義。
          通過”=”給變量賦值。
          var carName;
          carName=”BMW”;

          var carName=”BMW”;
          一條語句,多個變量
          var person=“Bill Gates”, carName=“porsche”, price=15000;

          7.JavaScript運算符

          JavaScript 使用(=)賦值運算符。
          JavaScript 使用算數運算符(+ - * / % ++ --)來計算值。

          <!DOCTYPE html>
          <html>
          	<head>
          		<meta charset="utf-8">
          		<title>變量-運算符-表達式</title>
          		<script>
          			function  suanshu(){
          				//聲明變量
          				var num1=10;
          				var num2=3;
          				document.getElementById("h1").innerHTML=num1+"+"+num2+"="+(num1+num2);
          				document.getElementById("h2").innerHTML=num1+"-"+num2+"="+(num1-num2);
          				document.getElementById("h3").innerHTML=num1+"*"+num2+"="+(num1*num2);
          				document.getElementById("h4").innerHTML=num1+"/"+num2+"="+(num1/num2);
          				document.getElementById("h5").innerHTML=num1+"%"+num2+"="+(num1%num2);
          				// ++ [自動加1]
          				// 變量++  [先用后加]
          				//num1++;  //10
          				//document.getElementById("h6").innerHTML=num1; //11
          				// ++變量  [先加后用]
          				//++num1;  //11
          				//document.getElementById("h6").innerHTML=num1; //11
          				// -- [自動減1]
          				// 變量-- [先用后減]
          				//num1-- ; //10
          				//document.getElementById("h6").innerHTML=num1; //9
          				//  -- 變量
          				--num1;  // 9
          				document.getElementById("h6").innerHTML=num1; //9
          			}
          		</script>
          	</head>
          	<body>
          		<input  type="button"  value="測試算數運算符" onclick="suanshu()"/><br>
          		<h1 id="h1"></h1>
          		<h1 id="h2"></h1>
          		<h1 id="h3"></h1>
          		<h1 id="h4"></h1>
          		<h1 id="h5"></h1>
          		<h1 id="h6"></h1>
          	</body>
          </html>
          
          


          JavaScript 使用(> <==>=<=!=)比較運算符運算符。

          JavaScript 使用(|| && ! )邏輯運算符運算符。

          為一名前端愛好者, 我利用空余時間研究了幾個國外網站的源碼,發現不管是庫,還是業務代碼,都會用到了一些比較有意思的API,雖然平時在工作中部分接觸過,但是經過這次的研究,覺得很有必要總結一下,畢竟已經2020年了,是時候更新一下技術儲備了,本文主要通過實際案例來帶大家快速了解以下幾個知識點:

          • Observer 原生觀察者
          • script標簽事件深入 - 移除script標簽后事件仍然能執行的原因
          • Proxy/Reflect 自定義事件
          • fileReader API Fullscreen 網頁全屏
          • URL API的使用
          • Geolocation 地理位置API的使用
          • Notifications 瀏覽器原生消息通知
          • Battery Status 設備電量情況

          我會對部分API做一些比較有意思的案例,那么開始我們的學習吧~

          1. Observer API

          Observer是瀏覽器自帶的觀察者,它主要提供了Intersection, Mutation, Resize, Performance這四類觀察者, 這里筆者重點介紹Intersection Observer.

          1.1 Intersection Observer

          IntersectionObserver提供了一種異步觀察目標元素與其祖先元素交叉狀態的方法。當一個IntersectionObserver對象被創建時,其被配置為監聽根中一段給定比例的可見區域,并且無法更改其配置,所以一個給定的觀察者對象只能用來監聽可見區域的特定變化值;然而,我們可以在同一個觀察者對象中配置監聽多個目標元素。

          說簡單點就是該api可以異步監聽目標元素在根元素里的位置變動,并觸發響應事件.我們可以利用它來實現更為高效的圖片懶加載, 無限滾動以及內容埋點上報等.接下來我們通過一個例子來說明一下它的使用步驟.

          // 1.定義觀察者及觀察回調
          const intersectionObserver=new IntersectionObserver((entries, observer)=> {
              entries.forEach(entry=> { 
                console.log(entry)
                // ...一些操作
              }); 
             },
             {
              root: document.querySelector('#root'),
              rootMargin: '0px',
              threshold: 0.5
             }
          )
          // 2. 定義要觀察的目標對象
          const target=document.querySelector(“.target”); 
          intersectionObserver.observe(target);
          

          以上代碼就實現了一個基本的Intersection Observer,雖然已有代碼中還體現不出什么實質性功能. 接下來介紹一下代碼中使用到的參數的含義: * callback IntersectionObserver實例的第一個參數, 當目標元素與根元素通過閾值 時就會觸發該回調.回調中第一個參數是被觀察對象列表,一旦被觀察對象發生突變就會被移入該列表, 列表中每一項都保留有觀察者的位置信息;第二個參數為observer,觀察者本身.如下圖控制臺打印:

          其中rootBounds表示根元素的位置信息, boundingClientRect表示目標元素的位置信息,intersectionRect表示叉部分的位置信息, intersectionRatio表示目標元素的可見比例.

          • 配置屬性 IntersectionObserver實例的第二個參數,用來配置監聽屬性,具體有以下三個屬性:
            • root 所監聽對象的具體祖先元素(element)。如果未傳入值或值為null,則默認使用頂級文檔的視窗。
            • rootMargin 計算交叉時添加到根(root)邊界盒bounding box的矩形偏移量, 可以有效的縮小或擴大根的判定范圍從而滿足計算需要
            • thresholds 一個包含閾值的列表, 按升序排列, 列表中的每個閾值都是監聽對象的交叉區域與邊界區域的比率。當監聽對象的任何閾值被越過時,都會生成一個通知(Notification)。如果構造器未傳入值, 則默認值為0。 以上屬性介紹字面上可能很難理解,筆者花幾個草圖來讓大家有個直觀的認知:

          當我們設置rootMargin為10px時,我們的root會增大影響范圍,但目標元素移動到淡紅色區域式就會被監聽到,當然我們還可以設置rootMargin為負值來減少影響區域.其支持的值為百分比和px,如下:

          rootMargin: '10px'
          rootMargin: '10%'
          rootMargin: '10px 0px 10px 10px'
          

          thresholds可以如下圖理解:

          由上圖所示,當我們設置閾值為[0.25, 0.5]時, 目標元素的25%和50%進入根元素的影響范圍時都會觸發回調.利用這個特性我們往往可以實現位差動畫,或者更根據目標元素的位置變化做不同的交互. 當然Intersection還提供了以下幾個方法來控制觀察對象: disconnect() 使IntersectionObserver對象停止監聽工作 takeRecords() 返回所有觀察目標的IntersectionObserverEntry對象數組 * unobserve() 使IntersectionObserver停止監聽特定目標元素

          了解了使用方法和api之后,我們來看看一個實際應用--實現圖片懶加載:

          <img src="loading.gif" data-src="absolute.jpg">
          <img src="loading.gif" data-src="relative.jpg">
          <img src="loading.gif" data-src="fixed.jpg">
          
          <script>
          let observerImg=new IntersectionObserver(
          (entries, observer)=> { 
              entries.forEach(entry=> {
                  // 替換為正式的圖片
                  entry.target.src=entry.target.dataset.src;
                  // 停止監聽
                  observer.unobserve(entry.target);
                });
              }, 
              {
                root: documennt.getElementById('scrollView'),
                threshold: 0.3
              }
          );
          
          document.querySelectorAll('img').forEach(img=> { observerImg.observe(img) });
          </script>

          以上代碼就實現了一個圖片懶加載功能, 當圖片的30%進入根元素時才加載真實的圖片,這又讓我想起了之前在某條做廣告埋點上報時使用react-lazyload的畫面.大家還可以利用它實現無限滾動, H5視差動畫等有意思的交互場景.

          1.2 Mutation Observer和Resize Observer

          Mutation Observer主要用來實現dom變動時的監聽,同樣也是異步觸發,對監聽性能非常友好. Resize Observer主要用來監聽元素大小的變化,相比于每次窗口變動都觸發的window.resize事件, Resize Observer有更好的性能和對dom有更細粒度的控制,它只會在繪制前或布局后觸發調用. 以上兩個api的使用和Intersection使用非常類似,官方資料也寫得很全,大家可以好好研究一下.

          2. 移除script標簽后事件仍然能執行的原因

          這個問題主要是之前有朋友問過我,當時的想法就是簡單的認為script內的代碼執行完之后以及與dom綁定了,存放在了瀏覽器內存中,最近查了很多資料發現有一個有點意思的解釋,放出來大家可以感受一下:

          JavaScript解釋器在執行腳本時,是按塊來執行的,也就是說瀏覽器在解析HTML文檔流時,如果遇到一個script標簽,javascript解釋器會等待這個代碼塊都加載完了,才進行預編譯,然后才執行。所以,當開始執行這個代碼塊的代碼時,這個代碼段已經被解析完了。這時再從DOM中刪去也就不影響代碼的執行了。

          3. Proxy/Reflect

          Proxy/Reflect雖然是es6的api,出現也已經有幾年了,但是在項目中用的還是比較少,如果是做底層架構方面的工作,還是建議大家多去使用,畢竟vue/react這種框架源碼把這些api玩的如火純青,還是很有必要掌握一下的。

          其實我們認真看mdn的介紹或者阮一峰老師的文章,還是很好理解這些api的用法的,接下來我們詳細介紹一下這兩個api以及應用場景.

          3.1 Proxy

          Proxy 可以理解成,在目標對象之前架設一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。Proxy在很多場景中都會和Reflect一起使用. 用法也很簡單,我們看看Proxy的基本用法:

          const obj={
             name: '徐小夕',
             age: '120'
           }
           const proxy=new Proxy(obj, {
             get(target, propKey, receiver) {
              console.log('get:' + propKey)
              return Reflect.get(target, propKey, receiver)
             },
             set(target, propKey, value, receiver) {
              console.log('set:' + propKey)
              return Reflect.set(target, propKey, value, receiver)
             }
           })
           console.log(proxy.name) // get:name 徐小夕
           proxy.work='frontend' // set:work frontend
          

          以上代碼攔截了obj對象,并重新定義了讀寫(get/set)方法,這樣我們就可以在訪問對象時進行額外的操作了.

          Proxy還有apply(攔截 Proxy 實例作為函數調用的操作)和construct(攔截 Proxy 實例作為構造函數調用的操作)等屬性可以使用,我們可以在對象操作的不同階段進行攔截,這里我就不一一樣舉例了.接下來看看Proxy的實際應用場景. * 實現數組讀取負數的索引

          我們一般操作數組大多數都是正向操作的,不能通過指定負數來逆向查找數組,如下圖:

          我們不能通過arr[-1]來拿到數組的尾部元素(字符串同理),這個時候我們就可以用Proxy來實現這一功能,這是我們的結構有點像環狀:

          這種實現的好處是如果我們想訪問數組的最后一個元素時,我們不需要先拿到長度,再通過索引訪問了:

          // 原始寫法
          arr[arr.length -1]
          // 通過proxy改造后寫法
          arr[-1]
          

          實現代碼如下:

          function createArray(...elements) {
            let handler={
              get(target, propKey, receiver) {
                let index=Number(propKey);
                if (index < 0) {
                  propKey=String(target.length + index);
                }
                return Reflect.get(target, propKey, receiver);
              }
            };
          
            let target=[];
            target.push(...elements);
            return new Proxy(target, handler);
          }
          

          我們可以發現以上代碼使用proxy來代理數組的讀取操作,在內部封裝了支持負值查找的功能,當然我們也可以不用proxy來實現同樣的功能,這里實現參考阮一峰老師的實現. * 利用proxy實現更優雅的校驗器

          一般我們在做表單校驗的時候會寫一些if else或者switch判斷來實現對不同屬性值的校驗,同樣我們也可以用proxy來優雅的實現它,代碼如下:

          const formData={
             name: 'xuxi',
             age: 120,
             label: ['react', 'vue', 'node', 'javascript']
           }
           // 校驗器
           const validators={
             name(v) {
               // 檢驗name是否為字符串并且長度是否大于3
               return typeof v==='string' && v.length > 3
             },
             age(v) {
               // 檢驗age是否為數值
               return typeof v==='number'
             },
             label(v) {
               // 檢驗label是否為數組并且長度是否大于0
               return Array.isArray(v) && v.length > 0
             }
           }
           // 代理校驗對象
           function proxyValidator(target, validator) {
            return new Proxy(target, {
              set(target, propKey, value, receiver) {
                if(target.hasOwnProperty(propKey)) {
                  let valid=validator[propKey]
                  if(!!valid(value)) {
                    return Reflect.set(target, propKey, value, receiver)
                  }else {
                    // 一些其他錯誤業務...
                    throw Error(`值驗證錯誤${propKey}:${value}`)
                  }
                }
              }
            })
           }
          

          有了以上實現模式,我們就可以實現對表單中某個值進行設置時進行校驗了,用法如下:

          let formObj=proxyValidator(formData, validators)
          formObj.name=333;   // Uncaught Error: 值驗證錯誤name:f
          formObj.age='ddd'   // Uncaught Error: 值驗證錯誤age:f
          

          以上代碼中當設置了不合法的值時,控制臺將會剖出錯誤,如果在實際業務中,我們可以給用戶做出適當的提醒. 實現請求攔截和錯誤上報 實現數據過濾

          以上幾點筆者在之前的文章中也寫過,所以這里不在詳細介紹了.大家也可以根據實際情況自己實現更加靈活的攔截操作.當然Proxy提供的API遠遠不止這幾個,我們可以在MDN或者其他渠道了解更多高級用法.

          3.2 Reflect

          Reflect對象與Proxy對象一樣,也是 ES6 為了操作對象而提供的新 API,更多的應用場景是配合proxy一起使用,在上文中已經用到了.可以將Object對象的一些明顯屬于語言內部的方法放到Reflect對象上,并修改某些Object方法的返回結果. Reflect對象的方法與Proxy對象的方法一一對應,只要是Proxy對象的方法,就能在Reflect對象上找到對應的方法。

          4. 自定義事件

          CustomEvent API是個非常有意思的api, 而且非常實用, 更重要的是學起來非常簡單,而且被大部分現代瀏覽器支持.我們可以讓任意dom元素監聽和觸發自定義事件,只需要如下操作:

          // 添加一個適當的事件監聽器
          dom1.addEventListener("boom", function(e) { something(e.detail.num) })
          
          // 創建并分發事件
          var event=new CustomEvent("boom", {"detail":{"num":10}})
          dom1.dispatchEvent(event)
          

          我們來看看CustomEvent的參數介紹: type 事件的類型名稱,如上面代碼中的'boom' CustomEventInit 提供了事件的配置信息,具體有以下幾個屬性 * bubbles 一個布爾值,表明該事件是否會冒泡 * cancelable 一個布爾值,表明該事件是否可以被取消 * detail 當事件初始化時傳遞的數據

          我們可以通過dispatchEvent來觸發自定義事件.其實他的用途有很多,比如創建觀察者模式, 實現數據雙向綁定, 亦或者在游戲開發中實現打怪掉血,比如下面的例子:


          筆者上面畫了一個打boss的草圖, 現在的場景是兩個玩家一起打boss, 我們可以在玩家發動攻擊的時候觸發dispatch掉血的自定義事件, boss監聽到事件后將血量自動扣除, 至于不同角色的傷害值,我們可以存放在detail中,然后通過策略模式去分發傷害.筆者曾今在學校開發的H5游戲時就大量采用類似的模式,還是非常有意思的.

          5. fileReader

          File API使得我們在瀏覽器端可以訪問文件的數據,比如預覽文件,獲取文件信息(比如文件名,文件內容,文件大小等), 并且可以在前端實現文件下載(可以借助canvas和 window.URL.revokeObjectURL的一些能力).當然我們還可以實現拖拽上傳文件這樣高用戶體驗的操作.接下來我們來看看幾個實際例子. * 顯示縮略圖

          function previewFiles(files, previewBox) {
              for (var i=0; i < files.length; i++) {
                var file=files[i];
                var imageType=/^image\//;
          
                if (!imageType.test(file.type)) {
                  continue;
                }
          
                var img=document.createElement("img");
                previewBox.appendChild(img); // 假設"preview"就是用來顯示內容的div
          
                var reader=new FileReader();
                reader.onload=(function(imgEl) { 
                  return function(e) { imgEl.src=e.target.result; }; 
                })(img);
                reader.readAsDataURL(file);
              }
            }
          

          以上代碼可以在reviewBox容器中顯示已上傳好的圖片,當然我們還可以基于此來擴展,利用canvas將圖片畫到canvas上,然后進行圖片壓縮,最后再把壓縮后的圖片上傳到服務器.這中方式其實目前很多工具型網站都在用,比如在線圖片處理網站,提供的批量壓縮圖片,批處理水印等功能,套路都差不多,感興趣的朋友可以嘗試研究一下. * 封裝文件上傳組件

          這塊筆者之前也寫過詳細的文章,這里就不一一舉例了.

          6. Fullscreen

          全屏API主要是讓網頁能在電腦屏幕中全屏顯示,它允許我們打開或者退出全屏模式,以便我們根據需要進行對應的操作,比如我們常用的網頁圖形編輯器或者富文本編輯器, 為了讓用戶專心于內容設計,我們往往提供切換全屏的功能供用戶使用.由于全屏API比較簡單,這里我們直接上代碼:

          // 開啟全屏
          document.documentElement.requestFullscreen();
          // 退出全屏
          document.exitFullscreen();
          

          以上代碼的document.documentElement也可以換成任何一個你想讓其全屏的元素.默認情況下我們還可以通過document.fullscreenElement來判斷當前頁面是否處于全屏狀態,來實現屏幕切換的效果.如果是react開發者,我們也可以將其封裝成一個自定義hooks來實現與業務相關的全屏切換功能.

          7. URL

          URL API是URL標準的組成部分,URL標準定義了構成有效統一資源定位符的內容以及訪問和操作URL的API。

          我們利用URL組件可以做很多有意思的事情.比如我們有個需求需要提取url的參數傳給后臺,傳統的做法是自己寫一個方法來解析url字符串,手動返回一個query對象.但是利用URL對象,我們可以很方便的拿到url參數,如下:

          let addr=new URL(window.location.href)
          let host=addr.host  // 獲取主機地址
          let path=addr.pathname  // 獲取路徑名
          let user=addr.searchParams.get("user")  // 獲取參數為user對應的值
          

          以上代碼可知,我們如果將url轉化為URL對象,那么我們就可以很方便的通過searchParams提供的api來拿到url參數而無需自己再寫一個方法了.

          另一方面,如果網站安全性比較高,我們還可以對參數進行自然數排序然后再加密上傳給后端.具體代碼如下:

          function sortMD5WithParameters() {
              let url=new URL(document.location.href);
              url.searchParams.sort();
              let keys=url.searchParams.keys();
              let params={}
          
              for (let key of keys) {
                let val=url.searchParams.get(key);
                params[key]=val
              };
              // ...md5加密
              return MD5(params)
           }
          

          8. Geolocation

          地理位置 API 通過 navigator.geolocation 提供, 這個瀏覽器API也比較實用, 我們在網站中可以用此方式確定用戶的位置信息,從而讓網站有不同的展現,增強用戶體驗.

          舉幾個有意思的例子可以讓大家感受一下: 根據不同地區,網站展示不同的主題:

          根據用戶所在地區,展示不同推薦內容 這一點電商網站或者內容網站用的比較多, 比如用戶在新疆,則給他推薦瓜果類廣告, 在北京,則給他推薦旅游景點類廣告等,雖然實際應用中往往會更復雜,但是也是一種思路.

          其實應用遠遠不止如此,程序員可以發揮想象來實現更有意思的事情,讓自己的網站更智能.接下來筆者就基于promise寫一段獲取用戶位置的代碼:

          function getUserLocation() {
              return new Promise((resolve, reject)=> {
                if (!navigator.geolocation) {
                  reject()
                } else {
                  navigator.geolocation.getCurrentPosition(success, error);
                }
          
                function success(position) {
                  const latitude=position.coords.latitude;
                  const longitude=position.coords.longitude;
                  resolve({latitude, longitude})
                }
          
                function error() {
                  reject()
                }
              })
            }
          

          使用方式和結果如下圖所示:

          我們基于獲取到的經緯度調用第三方api(比如百度,高德)就可以獲取用戶所在為精確位置信息了.

          9. Notifications

          Notifications API 允許網頁或應用程序在系統級別發送在頁面外部顯示的通知;這樣即使應用程序空閑或在后臺,Web應用程序也會向用戶發送信息。

          我們舉個實際的例子,比如我們網站內容有更新,通知用戶,效果如下:

          相關代碼如下:

          Notification.requestPermission( function(status) {
            console.log(status); // 僅當值為 "granted" 時顯示通知
            var n=new Notification("趣談前端", {body: "從零搭建一個CMS全棧項目"}); // 顯示通知
          });
          

          當然瀏覽器的Notification還給我們提供了4個事件觸發api方便我們做更全面的控制: onshow 當通知被顯示給用戶時觸發 (已廢棄, 但部分瀏覽器仍然能用) onclick 當用戶點擊通知時觸發 onclose 當通知被關閉時觸發(已廢棄, 但部分瀏覽器仍然能用) onerror 當通知發生錯誤的時候觸發

          有了這樣的事件監聽,我們就可以控制當用戶點擊通知時, 跳轉到對應的頁面或者執行相關的業務邏輯.如下代碼所示:

          Notification.requestPermission( function(status) {
            console.log(status); // 僅當值為 "granted" 時顯示通知
            var n=new Notification("趣談前端", {body: "從零搭建一個CMS全棧項目"}); // 顯示通知
                n.onshow=function () { 
                  // 消息顯示時執行的邏輯
                  console.log('show') 
                }
                n.onclick=function () { 
                  // 消息被點擊時執行的邏輯
                  history.push('/detail/1232432')
                }
                n.onclose=function () { 
                  // 消息關閉時執行的邏輯
                  console.log('close')
                }
          });
          

          當然我們在使用前需要獲取權限,方式也很簡單,大家可以在mdn上學習了解.

          10. Battery Status

          Battery Status API提供了有關系統充電級別的信息并提供了通過電池等級或者充電狀態的改變提醒用戶的事件。 這個可以在設備電量低的時候調整應用的資源使用狀態,或者在電池用盡前保存應用中的修改以防數據丟失。

          之前的版本中Battery Status API提供了幾個事件監聽函數來監聽電量的變化以及監聽設備是否充電,但是筆者看文檔時這些api都已經廢棄,如下: chargingchange 監聽設別是否充電 levelchange 監聽電量充電等級 chargingtimechange 充電時間變化 dischargingtimechange 放電時間變化

          雖然以上幾個看似有用的api已經被棄用,但是筆者親測谷歌還是可以正常使用的,但是為了讓自己代碼更可靠,我們可以用其他方式代替,比如用定時器定期去檢測電量情況,進而對用戶做出不同的提醒.

          接下來我們看看基本的用法:

          navigator.getBattery().then(function(battery) {
            console.log("是否在充電? " + (battery.charging ? "是" : "否"));
            console.log("電量等級: " + battery.level * 100 + "%");
            console.log("充電時間: " + battery.chargingTime + " s");
            console.log("放電時間: " + battery.dischargingTime + "s");
          });
          

          我們可以通過getBattery拿到設備電池信息,這個api非常有用,比如我們可以在用戶電量不足時禁用網站動畫或者停用一些耗時任務,亦或者是對用戶做適當的提醒,改變網站顏色等,對于webapp中播放視頻或者直播時,我們也可以用css畫一個電量條,當電量告急時提醒用戶.作為一個優秀的網站體驗師,這一塊還是不容忽視的.

          參考文獻

          • ECMAScript 6 入門 - 阮一峰
          • MDN web English docs

          主站蜘蛛池模板: 亚拍精品一区二区三区| 无码人妻精品一区二区三区蜜桃| 亚洲欧美成人一区二区三区 | 国产在线视频一区二区三区98| 色综合视频一区二区三区| 久久久精品一区二区三区| 极品尤物一区二区三区| 日韩精品中文字幕视频一区| 东京热人妻无码一区二区av| 麻豆文化传媒精品一区二区| 一区二区三区免费视频播放器| 国产在线视频一区二区三区98| 久久无码AV一区二区三区| 三级韩国一区久久二区综合| 国产精品高清视亚洲一区二区| 波多野结衣精品一区二区三区| 另类一区二区三区| 国产在线不卡一区二区三区| 国产一区二区三区日韩精品 | 无码精品人妻一区二区三区免费| 亚洲av无码一区二区三区不卡 | 亚洲国产成人一区二区精品区| 国产伦精品一区二区| 2021国产精品一区二区在线| 色欲AV蜜臀一区二区三区| 久久国产精品免费一区二区三区| 精品深夜AV无码一区二区老年| 性色av一区二区三区夜夜嗨 | 精品国产鲁一鲁一区二区| 国产精品一区二区久久国产| 中文字幕一区二区视频| 国产成人精品久久一区二区三区av | 国产成人精品a视频一区| 在线观看精品视频一区二区三区| 国产亚洲一区二区三区在线不卡| 国产精品一区12p| 日韩精品无码一区二区三区| 亚拍精品一区二区三区| 亚洲av永久无码一区二区三区| 人妻AV一区二区三区精品| 中文字幕乱码一区久久麻豆樱花 |