整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          六、循環(huán)表達(dá)式

          六、循環(huán)表達(dá)式

          .1、 循環(huán)表達(dá)式語法

          thymeleaf使用th:each屬性可以對數(shù)組,集合進(jìn)行循環(huán),此屬性用在容器元素上,循環(huán)生成子元素。

          語法

          th:each="循環(huán)出的元素 , 循環(huán)狀態(tài) : 集合或數(shù)組"

          6.2、數(shù)組的循環(huán)

          示例

          在TestServlet中定義一個(gè)數(shù)組

          String [] arr={"HTML","CSS","JavaScript"};
          request.setAttribute("arr",arr);

          在index.html中循環(huán)顯示數(shù)組中的元素

          <div th:text="'數(shù)組元素?cái)?shù)量:' + ${arr.length}"> </div><!--獲取數(shù)組元素的數(shù)量-->
          <ul th:each="s : ${arr}">
          	<li th:text="${s}"></li>
          </ul>

          運(yùn)行test.do,頁面顯示效果如下

          6.3、循環(huán)狀態(tài)的使用

          在th:each中循環(huán)狀態(tài)不是必須的,它是一個(gè)對象,具有以下屬性

          屬性名

          說明

          index

          整型屬性,當(dāng)前迭代索引,從0開始

          count

          整型屬性,當(dāng)前的迭代計(jì)數(shù),從1開始

          size

          整型屬性,迭代變量中元素的總量

          current

          對象屬性,每次迭代的 iter 變量,即當(dāng)前遍歷到的元素

          even/odd

          布爾屬性,當(dāng)前的迭代是偶數(shù)還是奇數(shù)

          first

          布爾屬性,當(dāng)前的迭代是否是第?個(gè)迭代

          last

          布爾屬性,當(dāng)前的迭代是否是最后?個(gè)迭代。

          修改上一個(gè)示例,顯示每次循環(huán)的各狀態(tài)的值

          <table border="1">	
          	<tr>			
                 <th>當(dāng)前迭代索引</th>	
                 <th>當(dāng)前迭代計(jì)數(shù)</th>	
          	<th>元素的總量</th>	
          	<th>當(dāng)前遍歷到的元素</th>		
          	<th>當(dāng)前遍歷的偶數(shù)</th>			
                  <th>是否是第一條</th>			
                  <th>是否是最后一條</th>	
          	</tr>		
          <tbody th:each="s,status : ${arr}">		
          	<tr><td th:text="${status.index}"></td>			
          	    <td th:text="${status.count}"></td>			
          	    <td th:text="${status.size}"></td>	
          	    <td th:text="${status.current}"></td>				
                      <td  th:text="${status.even}"></td>		
                      <td th:text="${status.first}"></td>			
          	    <td th:text="${status.last}"></td>	
          	</tr>	
          </tbody>
          	</table>

          運(yùn)行test.do,頁面顯示效果如下

          6.4、list的循環(huán)

          示例

          在TestServelt中添加一個(gè)List集合

          List list=new ArrayList<>();
           list.add("HTML"); 
          list.add("CSS");
          list.add("JavaScript");
          request.setAttribute("list", list);

          在index.html中循環(huán)顯示列表中的數(shù)據(jù)

          <div th:text="'list中元素?cái)?shù)量:' + ${list.size}"> </div>
          <ul th:each="s : ${list}">
          	<li th:text="${s}"></li>
          </ul>

          運(yùn)行test.do,頁面顯示效果如下

          6.5、map集合的訪問

          1) 直接訪問

          map集合可以通過key獲取值,也可以獲取集合中元素的數(shù)據(jù)

          示例

          在TestServelt中添加map集合

          Map<String,String> map=new HashMap<>();
          map.put("HTML", "超文本標(biāo)記語言");
          map.put("CSS", "層疊樣式表");
          request.setAttribute("map", map);

          在頁面中輸出map的信息

          <ul>		
          
          <li >集合:[[${map}]]</li>		
          <li>指定key的值:[[${map.HTML}]]</li>		
          <li>集合中元素的數(shù)量:[[${map.size}]]</li>		
          	</ul>

          運(yùn)行test.do,頁面顯示效果如下

          2)循環(huán)訪問

          Map循環(huán)的每個(gè)元素的類型是Entry,可以通過此Entry對象的key屬性獲取鍵,value屬性獲取值

          修改index.html,循環(huán)顯示map集合中的內(nèi)容

          <ul th:each="entry : ${map}">		
          <li >			
          <strong th:text="${entry.key}"></strong> 
          :
          <em th:text="${entry.value}"></em>		
          </li>	</ul>

          運(yùn)行test.do,頁面顯示效果如下

          6.6 th:block標(biāo)簽

          在使用th:if時(shí),如果是一當(dāng)條件成立需要加載一組標(biāo)簽,在循環(huán)時(shí),循環(huán)的元素外沒有容器時(shí),可以使用th:block標(biāo)簽做為外容器,th:block僅是一個(gè)屬性容器,允許開發(fā)人員指定他們想要的任何屬性

          示例

          <th:block th:each="s : ${list}">     
            <div th:text="${s}"></div></th:block>



          文章來源于嗶站《六、循環(huán)表達(dá)式 - 嗶哩嗶哩》

          更多學(xué)習(xí)視頻和專欄文章請到嗶站個(gè)人空間: 布道師學(xué)院的個(gè)人空間-布道師學(xué)院個(gè)人主頁-嗶哩嗶哩視頻

          更多資源和項(xiàng)目下載請到:”開源吧(找實(shí)戰(zhàn)項(xiàng)目和畢設(shè)項(xiàng)目的好網(wǎng)站)“ :開源吧

          javascript 是一門單線程的語言,在同一個(gè)時(shí)間只能做完成一件任務(wù),如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,再去執(zhí)行后面的任務(wù)。作為瀏覽器端的腳本語言,javascript 的主要功能是用來和用戶交互以及操作 dom。假設(shè) javascript 不是單線程語言,在一個(gè)線程里我們給某個(gè) dom 節(jié)點(diǎn)增加內(nèi)容的時(shí)候,另一個(gè)線程同時(shí)正在刪除這個(gè) dom 節(jié)點(diǎn)的內(nèi)容,則會造成混亂。

          由于 js 單線程的設(shè)計(jì),假設(shè) js 程序的執(zhí)行都是同步。如果執(zhí)行一些耗時(shí)較長的程序,例如 ajax 請求,在請求開始至請求響應(yīng)的這段時(shí)間內(nèi),當(dāng)前的工作線程一直是空閑狀態(tài), ajax 請求后面的 js 代碼只能等待請求結(jié)束后執(zhí)行,因此會導(dǎo)致 js 阻塞的問題。

          javascript 單線程指的是瀏覽器中負(fù)責(zé)解釋和執(zhí)行 javascript 代碼的只有一個(gè)線程,即為 js 引擎線程,但是瀏覽器的渲染進(jìn)程是提供多個(gè)線程的,如下:

          1. js 引擎線程
          2. 事件觸發(fā)線程
          3. 定時(shí)器觸發(fā)線程
          4. 異步 http 請求線程
          5. GUI 渲染線程

          一、異步 & 同步

          為解決上述類似上述 js 阻塞的問題,js 引入了同步和異步的概念。

          1、什么是同步?

          “同步”就是后一個(gè)任務(wù)等待前一個(gè)任務(wù)結(jié)束后再去執(zhí)行。

          2、什么是異步?

          “異步”與同步不同,每一個(gè)異步任務(wù)都有一個(gè)或多個(gè)回調(diào)函數(shù)。webapi 會在其相應(yīng)的時(shí)機(jī)里將回調(diào)函數(shù)添加進(jìn)入消息隊(duì)列中,不直接執(zhí)行,然后再去執(zhí)行后面的任務(wù)。直至當(dāng)前同步任務(wù)執(zhí)行完畢后,再把消息隊(duì)列中的消息添加進(jìn)入執(zhí)行棧進(jìn)行執(zhí)行。

          異步任務(wù)在瀏覽器中一般是以下:

          1. 網(wǎng)絡(luò)請求
          2. 計(jì)時(shí)器
          3. DOM 監(jiān)聽事件
          4. ...

          二、什么是執(zhí)行棧(stack)、堆(heap)、事件隊(duì)列(task queue)?

          1、執(zhí)行棧

          “棧”是一種數(shù)據(jù)結(jié)構(gòu),是一種線性表。特點(diǎn)為 LIFO,即先進(jìn)后出 (last in, first out)。

          利用數(shù)組的 push 和 shift 可以實(shí)現(xiàn)壓棧和出棧的操作。

          在代碼運(yùn)行的過程中,函數(shù)的調(diào)用會形成一個(gè)由若干幀組成的棧。

          function foo(b) {
            let a=10;
            return a + b + 11;
          }
          
          function bar(x) {
            let y=3;
            return foo(x * y);
          }
          
          console.log(bar(7))

          上面代碼最終會在控制臺打印42,下面梳理一下它的執(zhí)行順序。

          1. console.log 函數(shù)作為第一幀壓入棧中。
          2. 調(diào)用 bar,第二幀被壓入棧中。幀中包含著 bar 的變量對象。
          3. bar 調(diào)用 foo,foo 做一位第三幀被壓入棧中,幀中包含著 foo 的變量對象。
          4. foo 執(zhí)行完畢然后返回。被彈出棧。
          5. bar 執(zhí)行完畢然后返回,被彈出棧。
          6. log 函數(shù)接收到 bar 的返回值。執(zhí)行完畢后,出棧。此時(shí)棧已空。

          2、堆

          對象被分配在堆中,堆是一個(gè)用來表示一大塊(通常是非結(jié)構(gòu)化的)內(nèi)存區(qū)域的計(jì)算機(jī)術(shù)語。

          堆和棧的區(qū)別

          首先,stack 是有結(jié)構(gòu)的,每個(gè)區(qū)塊按照一定次序存放,可以明確知道每個(gè)區(qū)塊的大小;heap 是沒有結(jié)構(gòu)的,數(shù)據(jù)可以任意存放。因此,

          stack 的尋址速度要快于 heap。

          其次,每個(gè)線程分配一個(gè) stack,每個(gè)進(jìn)程分配一個(gè) heap,也就是說,stack 是線程獨(dú)占的,heap 是線程共用的。

          此外,stack 創(chuàng)建的時(shí)候,大小是確定的,數(shù)據(jù)從超過這個(gè)大小,就發(fā)生 stack overflow 錯誤,而 heap 的大小是不確定的,

          需要的話可以不斷增加。

          public void Method1()
          {
              int i=4;
          
              int y=2;
          
              class1 cls1=new class1();
          }

          上面代碼這三個(gè)變量和一個(gè)對象實(shí)例在內(nèi)存中的存放方式如下。

          從上圖可以看到,i、y和cls1都存放在stack,因?yàn)樗鼈冋加脙?nèi)存空間都是確定的,而且本身也屬于局部變量。但是,cls1指向的對象實(shí)例存放在heap,因?yàn)樗拇笮〔淮_定。作為一條規(guī)則可以記住,所有的對象都存放在heap。

          接下來的問題是,當(dāng)Method1方法運(yùn)行結(jié)束,會發(fā)生什么事?

          回答是整個(gè)stack被清空,i、y和cls1這三個(gè)變量消失,因?yàn)樗鼈兪蔷植孔兞浚瑓^(qū)塊一旦運(yùn)行結(jié)束,就沒必要再存在了。而heap之中的那個(gè)對象實(shí)例繼續(xù)存在,直到系統(tǒng)的垃圾清理機(jī)制(garbage collector)將這塊內(nèi)存回收。因此,一般來說,內(nèi)存泄漏都發(fā)生在heap,即某些內(nèi)存空間不再被使用了,卻因?yàn)榉N種原因,沒有被系統(tǒng)回收。

          3、事件隊(duì)列和事件循環(huán)

          隊(duì)列是一種數(shù)據(jù)結(jié)構(gòu),也是一種特殊的線性表。特點(diǎn)為 FIFO,即先進(jìn)先出(first in, first out)

          利用數(shù)組的 push 和 pop 可實(shí)現(xiàn)入隊(duì)和出隊(duì)的操作。

          事件循環(huán)和事件隊(duì)列的維護(hù)是由事件觸發(fā)線程控制的。

          事件觸發(fā)線程線程同樣是由瀏覽器渲染引擎提供的,它會維護(hù)一個(gè)事件隊(duì)列。

          js 引擎遇到上文所列的異步任務(wù)后,會交個(gè)相應(yīng)的線程去維護(hù)異步任務(wù),等待某個(gè)時(shí)機(jī),然后由事件觸發(fā)線程將異步任務(wù)對應(yīng)的回調(diào)函數(shù)加入到事件隊(duì)列中,事件隊(duì)列中的函數(shù)等待被執(zhí)行。

          js 引擎在執(zhí)行過程中,遇到同步任務(wù),會將任務(wù)直接壓入執(zhí)行棧中執(zhí)行,當(dāng)執(zhí)行棧為空(即 js 引擎線程空閑), 事件觸發(fā)線程 會從事件隊(duì)列中取出一個(gè)任務(wù)(即異步任務(wù)的回調(diào)函數(shù))放入執(zhí)行在棧中執(zhí)行。

          執(zhí)行完了之后,執(zhí)行棧再次為空,事件觸發(fā)線程會重復(fù)上一步的操作,再從事件隊(duì)列中取出一個(gè)消息,這種機(jī)制就被稱為 事件循環(huán) (Event Loop)機(jī)制。

          為了更好地理解Event Loop,請看下圖(轉(zhuǎn)引自Philip Roberts的演講《Help, I'm stuck in an event-loop》)。

          例子代碼:

          console.log('script start')
          
          setTimeout(()=> {
            console.log('timer 1 over')
          }, 1000)
          
          setTimeout(()=> {
            console.log('timer 2 over')
          }, 0)
          
          console.log('script end')
          
          // script start
          // script end
          // timer 2 over
          // timer 1 over

          模擬 js 引擎對其執(zhí)行過程:

          第一輪事件循環(huán):

          1. console.log 為同步任務(wù),入棧,打印“script start”。出棧。
          2. setTimeout 為異步任務(wù),入棧,交給定時(shí)器觸發(fā)線程處理(在1秒后加入將回調(diào)加入事件隊(duì)列)。出棧。
          3. setTimeout 為異步任務(wù),入棧,交給定時(shí)器觸發(fā)線程處理(在4ms之內(nèi)將回調(diào)加入事件隊(duì)列)。出棧。
          4. console.log 為同步任務(wù),入棧,打印"script end"。出棧。

          此時(shí),執(zhí)行棧為空,js 引擎線程空閑。便從事件隊(duì)列中讀取任務(wù),此時(shí)隊(duì)列如下:

          第二輪事件循環(huán)

          1. js 引擎線程從事件隊(duì)列中讀取 cb2 加入執(zhí)行棧并執(zhí)行,打印”time 2 over“。出棧。

          第三輪事件循環(huán)

          1. js 引擎從事件隊(duì)列中讀取 cb1 加入執(zhí)行棧中并執(zhí)行,打印”time 1 over“ 。出棧。

          注意點(diǎn):

          上面,timer 2 的延時(shí)為 0ms,HTML5標(biāo)準(zhǔn)規(guī)定 setTimeout 第二個(gè)參數(shù)不得小于4(不同瀏覽器最小值會不一樣),不足會自動增加,所以 "timer 2 over" 還是會在 "script end" 之后。

          就算延時(shí)為0ms,只是 time 2 的回調(diào)函數(shù)會立即加入事件隊(duì)列而已,回調(diào)的執(zhí)行還是得等到執(zhí)行棧為空時(shí)執(zhí)行。

          四、宏任務(wù) & 微任務(wù)

          在 ES6 新增 Promise 處理異步后,js 執(zhí)行引擎的處理過程又發(fā)生了新的變化。

          看代碼:

          console.log('script start')
          
          setTimeout(function() {
              console.log('timer over')
          }, 0)
          
          Promise.resolve().then(function() {
              console.log('promise1')
          }).then(function() {
              console.log('promise2')
          })
          
          console.log('script end')
          
          // script start
          // script end
          // promise1
          // promise2
          // timer over

          這里又新增了兩個(gè)新的概念, macrotask (宏任務(wù))和 microtask (微任務(wù))。

          所有的任務(wù)都劃分到宏任務(wù)和微任務(wù)下:

          • macrotask : script 主代碼塊、setTimeout、setInterval、requestAnimationFrame、node 中的setimmediate 等。
          • microtask : Promise.then catch finally、MutationObserver、node 中的process.nextTick 等。

          js 引擎首先執(zhí)行主代碼塊。

          執(zhí)行棧每次執(zhí)行的代碼就是一個(gè)宏任務(wù),包括任務(wù)隊(duì)列(宏任務(wù)隊(duì)列)中的。執(zhí)行棧中的任務(wù)執(zhí)行完畢后,js 引擎會從宏任務(wù)隊(duì)列中去添加任務(wù)到執(zhí)行棧中,即同樣是事件循環(huán)的機(jī)制。

          當(dāng)在執(zhí)行宏任務(wù)遇到微任務(wù) Promise.then 時(shí),會創(chuàng)建一個(gè)微任務(wù),并加入到微任務(wù)隊(duì)列中的隊(duì)尾。

          微任務(wù)是在宏任務(wù)執(zhí)行的時(shí)候創(chuàng)建的,而在下一個(gè)宏任務(wù)執(zhí)行之前,瀏覽器會對頁面重新渲染(task >> render >> task(任務(wù)隊(duì)列中讀取))。 同時(shí),在上一個(gè)宏任務(wù)執(zhí)行完成后,頁面渲染之前,會執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)。

          所以上述代碼的執(zhí)行過程就可以解釋了。

          js 引擎執(zhí)行 promise.then 時(shí),promise1、promise2 被認(rèn)為是兩個(gè)微任務(wù)按照代碼的先后順序被加入到微任務(wù)隊(duì)列中,script end執(zhí)行后,空。

          此時(shí)當(dāng)前宏任務(wù)(script 主代碼塊)執(zhí)行完畢,并不從當(dāng)前宏任務(wù)隊(duì)列中讀取任務(wù)。而是立馬清空當(dāng)前宏任務(wù)所產(chǎn)生的微任務(wù)隊(duì)列。將兩個(gè)微任務(wù)依次放入執(zhí)行棧中執(zhí)行。執(zhí)行完畢,打印 promise1、promise2。棧空。 此時(shí),第一輪事件循環(huán)結(jié)束。

          緊接著,再去讀取宏任務(wù)隊(duì)列中的任務(wù),time over 被打印。棧空。

          因此,宏任務(wù)和微任務(wù)的執(zhí)行機(jī)制如下:

          1. 執(zhí)行一個(gè)宏任務(wù)(棧中沒有就從宏任務(wù)隊(duì)列中獲取)
          2. 執(zhí)行過程中遇到微任務(wù),就將它添加到微任務(wù)的任務(wù)隊(duì)列中
          3. 宏任務(wù)執(zhí)行完畢,立即執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)(依次執(zhí)行)
          4. 當(dāng)前所有微任務(wù)執(zhí)行完畢后,開始檢查渲染,GUI 線程接管渲染
          5. 渲染完畢后,JS 引擎繼續(xù)開始下一個(gè)宏任務(wù),從宏任務(wù)隊(duì)列中獲取

          async & await

          因?yàn)?async 和 await 本質(zhì)上還是基于 Promise 的封裝,而 Promise 是屬于微任務(wù)的一種。所以使用 await 關(guān)鍵字與 Promise.then 效果類似:

          setTimeout(_=> console.log(4))
          
          async function main() {
            console.log(1)
            await Promise.resolve()
            console.log(3)
          }
          
          main()
          
          console.log(2)
          // 1
          // 2
          // 3
          // 4

          async 函數(shù)在 await 之前的代碼都是同步執(zhí)行的, 可以理解為 await 之前的代碼都屬于 new Promise 時(shí)傳入的代碼,await 之后的所有代碼都是 Promise.then 中的回調(diào),即在微任務(wù)隊(duì)列中。

          五、總結(jié)

          1. js 單線程實(shí)際上時(shí)解釋執(zhí)行 js 代碼的只有一個(gè)線程,但是瀏覽器的渲染是多線程的。
          2. 異步和同步的概念與區(qū)別,異步任務(wù)有哪些。
          3. 棧、堆、隊(duì)列的特點(diǎn)和使用場景。
          4. 事件隊(duì)列以及事件循環(huán)機(jī)制。
          5. es6 下,宏任務(wù)與微任務(wù)的執(zhí)行過程。

          參考:

          • JavaScript 異步與事件循環(huán)
          • 并發(fā)模型與事件循環(huán)
          • 微任務(wù)、宏任務(wù)與Event-Loop
          • JavaScript 運(yùn)行機(jī)制詳解:再談Event Loop
          • JS事件循環(huán)
          • [譯] 深入理解 JavaScript 事件循環(huán)(二)— task and microtask
          • Help, I'm stuck in an event-loop

          原文作者:大芒果哇

          原文地址:https://www.cnblogs.com/shenggao/p/13799566.html

          前端開發(fā)來說,通過動畫來提升交互效果是很常見的。在很早以前,做web動畫主要通過javascript或者jquery或者flash這樣的手段,非常麻煩,自打有了ccs3,做動畫就太方便了,只需幾行css代碼就可以搞定。

          這里我們就演示一個(gè)常見的循環(huán)滾動效果,任務(wù)是這樣:先準(zhǔn)備一個(gè)圖片,平鋪到頁面上充滿整個(gè)屏幕,然后就讓畫面一直向上循環(huán)滾動,形成無邊無際的感覺。

          雖然可以從網(wǎng)上搜到一些類似的代碼,但是魚龍混雜,無關(guān)緊要的代碼非常多,不夠純粹。如果要弄明白動畫的原理,只有自己動手做一遍才能真正消化吃透。所以我們來一步步原創(chuàng)這個(gè)代碼,排除所有不必要的基礎(chǔ)樣式,只說要點(diǎn),3個(gè)步驟你就可以完全掌握其精髓!

          第一步:布局

          首先,滾動的圖片需要放在一個(gè)容器里,一行html代碼即可完成:

          第二步:把圖片放進(jìn)容器

          css中body的邊界設(shè)為0,把容器設(shè)高度100%以充滿屏幕,再調(diào)用背景圖pic.png

          第三部:讓畫面動起來

          咱不做標(biāo)題黨,循環(huán)滾動靠的就是3行css動起來的。

          先是1行 -webkit-animation屬性:4個(gè)參數(shù)分別表示:動畫名稱scroll,1秒時(shí)長,移動速度為線性的,無限循環(huán)。

          然后是對應(yīng)的關(guān)鍵幀 @-webkit-keyframes 屬性,這是自己定義的動畫規(guī)則,只需寫2行規(guī)則即可:

          原理:動畫就是畫從一個(gè)地方動到另一個(gè)地方。對普通滾動效果來說,有起點(diǎn)和終點(diǎn)這兩個(gè)節(jié)點(diǎn)的位置就夠了。所以我們用0%和100%分別表示起點(diǎn)和終點(diǎn),指定2個(gè)背景圖的xy位置坐標(biāo)即可。圖片會在規(guī)定時(shí)間內(nèi)從起點(diǎn)移動到終點(diǎn),并循環(huán)下去,數(shù)值是負(fù)表示是向上移動。320px正好是圖片的高度,這樣循環(huán)的時(shí)候是無縫銜接的。

          好了,最終完整的代碼如下,是不是很精練呢?保存成 index.html 即可

          代碼寫完了,還要記得在當(dāng)前目錄要有pic.png這個(gè)圖片哦,我隨便畫了幾筆,絕無觀賞性,建議自己找個(gè)好看點(diǎn)的圖片來代替。

          現(xiàn)在用瀏覽器打開index.html即可看到效果,比較魔性的地方在于,如果你盯著看久了,關(guān)閉窗口以后會出現(xiàn)幻覺,仿佛整個(gè)顯示器都在向上飛,哈哈!

          最后我們來說說瀏覽器兼容性問題:

          大家可能注意到了,前面那2個(gè)古怪的 -webkit-animation, @-webkit-keyframes 這里的-webkit-其實(shí)是一個(gè)前綴,animation和@keyframes才是CSS的標(biāo)準(zhǔn)屬性。

          當(dāng)加上-webkit-后,就形成了一個(gè)針對特殊瀏覽器的專有屬性,表示用在谷歌的chrome和蘋果的safari瀏覽器上。此外還有-moz前綴代表針對firefox瀏覽器的私有屬性。

          所以我們在用到css3的一些特性的時(shí)候,經(jīng)常使用一大堆的重復(fù)性的代碼,比如我們今天的這個(gè)代碼,有人會寫成這個(gè)樣子:

          一個(gè)簡單的動畫就要寫這么多冗余的代碼,為的只是支持一些舊的瀏覽器,有必要嗎?為什么在這個(gè)例子中我們僅僅采用了-webkit-而沒有使用其它專有屬性呢?

          因?yàn)楝F(xiàn)在已經(jīng)是2019年了!谷歌蘋果的瀏覽器是主流,占據(jù)了絕大部分,而其它小眾瀏覽器也大多能夠兼容他們,在版本上,大部分人安裝瀏覽器是直接下載新版本安裝使用,而非找出家里陳年的老軟盤、老光盤去安裝,家中的老電腦也早已升級不知多少回了,所以也幾乎沒有機(jī)會使用低版本的瀏覽器了!

          至于微軟的IE,就更別提了,IE9以前不支持動畫的,只能用js或者jquery來寫動畫,直到IE10才支持css動畫,隨后IE被放棄,主推Edge,搞了幾天越來越頭大干脆也放棄,現(xiàn)在直接使用chrome內(nèi)核了,所以針對ie的兼容性除非有特殊要求已經(jīng)無需考慮。

          你在網(wǎng)上能看到的范例代碼,如果有寫成那么復(fù)雜臃腫的,估計(jì)也都是3-5年前發(fā)的老文,或者抄來抄去不做思考的搬磚工留下的“初學(xué)者”筆記。

          我們不仿測試一下幾款主流瀏覽器的情況看看,結(jié)論:

          測試結(jié)果表明,-webkit-的寫法在4款不同內(nèi)核的瀏覽器上都能正常使用,所以我們的代碼因此能得以簡化。

          當(dāng)然,這個(gè)例子也有局限性,比如你看,只有蘋果safari不支持標(biāo)準(zhǔn)寫法,萬一將來他改邪歸正了呢?畢竟標(biāo)準(zhǔn)寫法才是眾望所歸不是?使用針對個(gè)別瀏覽器的私有屬性寫法,雖可用但畢竟有些怪怪的,將來怎么樣還很難說呢。這樣看來,如果使用古老的處理辦法,重復(fù)N次為每個(gè)專屬瀏覽器各寫一份代碼,除了辣眼睛也真沒什么錯。

          瀏覽器的兼容問題涉及面實(shí)在是非常廣,三言兩語還真說不完,以后會專門來講。


          主站蜘蛛池模板: 国产av一区二区三区日韩 | 国产在线观看一区二区三区| 精品3d动漫视频一区在线观看| 亚洲午夜电影一区二区三区| 日本不卡免费新一区二区三区| 色综合视频一区中文字幕| 中文字幕av人妻少妇一区二区| 久久久久人妻一区二区三区| 蜜臀AV免费一区二区三区| 国产一区二区在线观看app | 亚洲国产一区明星换脸| 一本AV高清一区二区三区| 国产内射999视频一区| 亚洲AV无码一区二三区| 久久免费视频一区| 精品国产一区二区三区www| 亚洲综合一区无码精品| 国产精品资源一区二区| 亚洲一区二区三区在线视频 | 国产AV一区二区三区传媒| 一区二区三区日本视频| 日韩精品电影一区亚洲| 免费视频精品一区二区三区| 一区二区三区在线观看| 一区二区三区91| 日本免费一区二区在线观看| 亚洲乱码国产一区网址| 久久久久人妻一区二区三区| 国产拳头交一区二区| 久久一区二区三区免费播放| 无码视频一区二区三区| 久久伊人精品一区二区三区| 日本一区视频在线播放| 伊人久久精品一区二区三区| 无码囯产精品一区二区免费| 人妻少妇一区二区三区| 四虎一区二区成人免费影院网址| 中文乱码人妻系列一区二区| 久久免费国产精品一区二区| 亚洲一区二区三区自拍公司| 国产日韩精品一区二区三区在线|