《JavaScript高級程式設計》筆記:新興的API

来源:https://www.cnblogs.com/moqiutao/archive/2019/05/07/10249181.html
-Advertisement-
Play Games

requestAnimationFrame() 大多數電腦顯示器的刷新頻率60HZ,大概相當於每秒鐘重繪60次。因此,最平滑動畫的最佳迴圈間隔是1000ms/60,約等於17ms。 mozRequestAnimationFrame() mozRequestAnimationFrame()方法接收一個 ...


requestAnimationFrame()

大多數電腦顯示器的刷新頻率60HZ,大概相當於每秒鐘重繪60次。因此,最平滑動畫的最佳迴圈間隔是1000ms/60,約等於17ms。

mozRequestAnimationFrame()

mozRequestAnimationFrame()方法接收一個參數,即在重繪屏幕前調用的一個函數。這個函數負責改變下一次重繪時的DOM樣式。為了創建動畫迴圈,可以像以前使用setTimeout()方法一樣,把多個對mozRequestAnimationFrame()的調用連綴起來,如下代碼:

function updateProgress(){
    var div = document.getElementById("status");
    div.style.width = (parseInt(div.style.width,10) + 5) + "%";
    if(div.style.width != "100%"){
        mozRequestAnimationFrame(updateProgress);
    }
}
mozRequestAnimationFrame(updateProgress);

我們傳遞的mozRequestAnimationFrame()函數也會接收一個參數,它是一個時間碼(從1970年1月1日起至今的毫秒數),表示下一次重繪的實際發生時間。

註意:mozRequestAnimationFrame()會根據這個時間碼設定將來的某個時刻進行重繪,而根據這個時間碼,你也能知道那個時刻是什麼時間。然後,在優化動畫效果就有了依據。

要知道距離上一次重繪已經過去了多長時間,可以查詢mozAnimationStartTime,其中包含上次重繪的時間碼。用傳入回調函數的時間碼減去這個時間碼,就能計算出在屏幕上重繪下一組變化之前要經過多長時間。使用這個值的典型方式:

function draw(timestamp){
    //計算兩次重繪的事件間隔
    var diff = timestamp - startTime;
    
    //使用diff確定下一步的繪製時間
    
    //把startTime重寫為這一次的繪製時間
    startTime = timestamp;
    
    //重繪UI
    mozRequestAnimationFrame(draw);
}

var startTime = mozAnimationStartTime;
mozRequestAnimationFrame(draw);

webkitRequestAnimationFrame與msRequestAnimationFrame

Chrome和IE10+也都給出了自己的實現,分別是webkitRequestAnimationFrame()msRequestAnimationFrame()。這兩個版本跟mozilla的版本有兩個方面的微小差異。

  • 首先,不會給回調函數傳遞時間碼,因此你無法知道下一次重繪將發生在什麼時間;
  • 其次,Chrome又增加了第二個可選的參數,即將要發生變化的DOM元素。知道了重繪將發生在頁面中哪個特定元素的區域內,就可以將重繪限定在該區域中。

既然沒有下一次重繪的時間碼,那麼就沒有提供像mozAnimationStartTime的實現,不過,Chrome提供了另一個方法webkitCancelAnimationFrame(),用於取消之前計劃執行的重繪操作。

假如你不需要知道精確的時間差,可以參考以下模式創建動畫迴圈:

(function(){
    function draw(timestamp){
        //計算兩次重繪的時間間隔
        var drawStart = timestamp || Date.now(),
            diff = drawStart - startTime;
            
        //使用diff確定下一步的繪製時間
    
        //把startTime重寫為這一次的繪製時間
        startTime = drawStart;
        
        //重繪UI
        requestAnimationFrame(draw);
    }
    var requestAnimationFrame = window.requestAnimationFrame ||
                                window.mozRequestAnimationFrame ||
                                window.webkitRequestAnimationFrame ||
                                window.msRequestAnimationFrame,
        startTime = window.mozAnimationStartTime || Date.now();
    requestAnimationFrame(draw);
})();

來看個實際的例子,如下代碼:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
    <style>
        *{margin:0;padding:0;}
    #status{width:20px;height:20px;background: red;}
    </style>
</head>
<body>
<div id="status"></div>
<script type="text/javascript">
(function(){
    function draw(timestamp){
                //計算兩次重繪的時間間隔
        var drawStart = timestamp || Date.now(),
            diff = drawStart - startTime;
                
                //使用diff確定下一步的繪製時間
                console.log(diff)
                
        //把startTime重寫為這一次的繪製時間
        startTime = drawStart;
                
        var div = document.getElementById("status");
        var computedStyle = document.defaultView.getComputedStyle(div,null);
        div.style.width = (parseInt(computedStyle.width,10) + 5) + "px";
                
        //重繪UI
        if(parseInt(computedStyle.width,10) < 500){
            requestAnimationFrame(draw);
        }
    }
    var requestAnimationFrame = window.requestAnimationFrame ||
                                window.mozRequestAnimationFrame ||
                                window.webkitRequestAnimationFrame ||
                                window.msRequestAnimationFrame,
        startTime = window.mozAnimationStartTime || Date.now();
    requestAnimationFrame(draw);
})();
</script>
</body>
</html>

 requestAnimationFrame簡單相容方式:

window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();

更全面的相容方法:

(function() {
    var lastTime = 0;
    var vendors = ['webkit', 'moz'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||    // Webkit中此取消方法的名字變了
                                      window[vendors[x] + 'CancelRequestAnimationFrame'];
    }
 
    if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
            var id = window.setTimeout(function() {
                callback(currTime + timeToCall);
            }, timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
    }
    if (!window.cancelAnimationFrame) {
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
    }
}());

詳細參考地址:《requestAnimationFrame,Web中寫動畫的另一種選擇》。

 Page visibility API

如果頁面最小化了或者隱藏在了其他標簽頁後面,Page visibility API(頁面可見性API)就是為了讓開發人員知道頁面是否對用戶可見而推出的。

  • document.hidden:表示頁面是否隱藏的布爾值。
  • visibilitychange事件:當文檔從可見變為不可見或者從不可見變為可見時,觸發該事件。
document.addEventListener('visibilitychange',function(){
    if(document.hidden){
        console.log('頁面隱藏了')
    }else{
        console.log("頁面顯示了")
    }
},false);

IE10+以及其它高版本瀏覽器支持該API。

Geolocation API

Geolocation API在瀏覽器中實現是navigator.geolocation對象,這個對象包含3個方法,getCurrentPosition()watchPosition()、clearWatch()

getCurrentPosition():接受三個參數,成功回調函數、可選的失敗回調函數和可選的選項對象。

其中成功回調函數會接收一個position對象參數,該對象有兩個屬性:coordstimestamp。coords將包含與位置相關的信息,如下:

  • latitude:以十進位度數表示的緯度。
  • longitude:以十進位度數表示的經度。
  • accuracy:經、緯度坐標的精度,以米為單位。

失敗回調接收一個參數,這個參數是一個對象,包括兩個屬性:message和code。

getCurrentPosition()的第三個參數是一個選項對象,用於設定信息的類型。可以設置的選項有三個:

  • enableHighAccuracy:布爾值,表示必須儘可能使用最準確的位置信息;
  • timeout:是以毫秒數表示的等待位置信息的最長時間;
  • maximumAge:表示上一次取得的坐標信息的有效時間,以毫秒數表示,如果時間到重新取得新坐標信息。
navigator.geolocation.getCurrentPosition(function(position){
    console.log(position.coords.latitude,position.coords.longitude);
},function(error){
    console.log("Error code:" + error.code);
    console.log("Error message:" + error.message);
},{
    enableHighAccuracy:false,
    timeout:50000,
    maximumAge:25000
})

watchPosition():參數跟getCurrentPosition()一樣。實際上與定時調用getCurrentPosition()的效果相同。在第一次調用watchPostion()方法後,會取得當前位置,執行成功回調或者錯誤回調。然後,watchPosition()就地等待系統發出位置已改變的信號(它不會自己輪詢位置)。調用watchPosition()會返回一個數值標識符,用於跟蹤監控的操作。基於這個返回值可以取消監控操作,只要將其傳遞給clearWatch()方法即可。

var watchId = navigator.geolocation.watchPosition(function(position){
    console.log(position.coords.latitude,position.coords.longitude);
},function(error){
    console.log("Error code:" + error.code);
    console.log("Error message:" + error.message);
},{
    enableHighAccuracy:false,
    timeout:50000,
    maximumAge:25000
});

navigator.geolocation.clearWatch(watchId);

File API

FIle API在表單中的文件輸入欄位的基礎上,又添加了一些直接訪問文件信息的介面。HTML5在DOM中為文件輸入元素添加了一個files集合。在通過文件輸入欄位選擇了一個或者多個文件時,files集合中包含一組File對象,每個file對象對應了一個文件。每個File對象都有下列只讀屬性。

  • name:本地文件系統中的文件名。
  • size:文件的位元組大小。
  • type:字元串,文件的MIME類型。
  • lastModifiedDate:字元串,文件上一次被修改的時間(只有Chrome實現了這個屬性)。

如下例子:

HTML代碼:

<input type="file" id="files-list" multiple/>

JS代碼:

var filesList = document.getElementById("files-list");
EventUtil.addHandler(filesList,"change",function(event){
    var files = EventUtil.getTarget(event).files,
        i = 0,
        len = files.length;
    while(i < len){
        console.log(files[i].name + "(" + files[i].type + "," + files[i].size + "bytes)");
        i++;
    }    
})

FileReader類型

FileReader類型實現的是一種非同步文件讀取機制。可以把FileReader想象成XMLHttpRequest,區別隻是它讀取的是文件系統,而不是遠程伺服器。為了讀取文件中的數據,FileReader提供瞭如下幾個方法。

  • readAsText(file,encoding):以純文本形式讀取文件,將讀取到的文本保存到result屬性中。第二個參數用於指定編碼類型,是可選的。
  • readAsDataURL(file):讀取文件並將文件以數據URI的形式保存在result屬性中。
  • readAsBinaryString(file):讀取文件並將一個字元串保存在result屬性中,字元串中的每個字元表示一個位元組。
  • readAsArrayBuffer(file):讀取文件並將一個包含文件內容的ArrayBuffer保存在result屬性中。

例如,可以讀取圖像文件並將其保存為數據URI,以便將其顯示給用戶,或者為瞭解析方便,可以將文件讀取為文本形式。

由於讀取是非同步的,因此FileReader提供了幾個事件。其中最有用的3個事件是progresserrorload,分別表示是否讀取了新數據、是否發生了錯誤以及是否讀完了整個文件。

每過50ms左右,就會觸發一次progress事件,通過事件對象可以獲得與XHR的progress事件相同的信息(屬性):lengthComputableloadedtotal。另外,儘管可能沒有包含全部數據,但每次progress事件中都可以通過FileReader的result屬性讀取到文件內容。

由於種種原因無法讀取到文件時,就會觸發error事件。觸發error事件時,相關的信息將保存到FileReader的error屬性中。這個屬性中將保存一個對象,該對象只有一個屬性code,即錯誤碼。這個錯誤碼如下:

  • 1:未找到文件。
  • 2:安全性錯誤。
  • 3:讀取中斷。
  • 4:文件不可讀。
  • 5:編碼錯誤。

文件成功載入後會觸發load事件;如果發生error事件,就不會觸發load事件。如下例子:

var filesList = document.getElementById("files-list");
EventUtil.addHandler(filesList,"change",function(event){
    var info = "",
        output = document.getElementById("output"),
        progress = document.getElementById("progress"),
        files = EventUtil.getTarget(event).files,
        type = "default",
        reader = new FileReader();
if(/image/.test(files[0].type)){
        reader.readAsDataURL(files[0]);
        type = "image";
    }else{
        reader.readAsText(files[0]);
        type = "text";
    };
    
    reader.onerror = function(){
        output.innerHTML = "Could not read file,error code is:" + reader.error.code;  
    };
    
    reader.onprogress = function(event){
        if(event.lengthComputable){
            output.innerHTML = event.loaded + "/" + event.total;
        }
    };
    
    reader.onload = function(){
        var html = "";
        
        switch(type){
            case "image":
                html = "<img src=\""+reader.result+"\"/>";
                break;
            case "text":
                html = reader.result;
                break;
        }
        output.innerHTML = html;
    };
});

讀取部分內容

有時候我們想讀取文件的一部分而不是全部內容。為此,File對象還支持一個slice()方法,這個方法在Firefox的實現為mozSlice(),在Chrome中的實現為webkitSlice()。slice()方法接收兩個參數:起始位元組及要讀取的位元組數。這個方法返回一個Blob實例,Blob是File類型的父類型。下麵一個通用的方法實現相容的slice():

function blobSlice(blob,startByte,length){
    if(blob.slice){
        return blob.slice(startByte,length);
    }else if(blob.webkitSlice){
        return blob.webkitSlice(startByte,length);
    }else if(blob.mozSlice){
        return blob.mozSlice(startByte,length);
    }else{
        return null;
    }
}

Blob類型有一個size屬性和一個type屬性,而且它也支持slice()方法,以便進一步切割數據。通過FileReader也可以從Blob中讀取數據。下麵這個例子只讀取文件的32B內容。

var filesList = document.getElementById("files-list");
EventUtil.addHandler(filesList,"change",function(event){
    var info = "",
        output = document.getElementById("output"),
        progress = document.getElementById("progress"),
        files = EventUtil.getTarget(event).files,
        reader = new FileReader(),
        blob = blobSlice(files[0],0,32);
    
    if(blob){
        reader.readAsText(blob);
        reader.onerror = function(){
            output.innerHTML = "Could not read file,error code is:" + reader.error.code;  
        };
        reader.onload = function(){
            output.innerHTML = reader.result;
        };
    }else{
        alert("Your browser doesn't support slice().");
    }
});

對象URL

對象URL也被成為blob URL,指的是引用保存在File或Blob中數據的URL。使用對象URL的好處是不用把文件內容讀取到JS中而直接使用文件內容。為此,只要在需要文件內容的地方提供對象URL即可。要創建對象URL,可以使用window.URL.createObjectURL()方法,並傳入File或者Blob對象。這個方法在Chrome中的實現為window.webkitURL.createObjectURL(),因此下麵相容寫法:

function createObjectURL(blob){
    if(window.URL){
        return window.URL.createObjectURL(blob);
    }else if(window.webkitURL){
        return window.webkitURL.createObjectURL(blob);
    }else{
        return null;
    }
}

這個函數返回值是一個字元串,指向一塊記憶體的地址。因為這個字元串是URL,所以在DOM中也能使用,例如,在頁面中顯示一個圖形文件:

var filesList = document.getElementById("files-list");
EventUtil.addHandler(filesList,"change",function(event){
    var info = "",
        output = document.getElementById("output"),
        progress = document.getElementById("progress"),
        files = EventUtil.getTarget(event).files,
        url = createObjectURL(files[0]);
    
    if(url){
        if(/image/.test(files[0].type)){
            output.innerHTML = "<img src=\"" + url +"\"/>";
        }else{
            output.innerHTML = "Not an image."
        }
    }else{
        alert("Your browser doesn't support URLs.");
    }
});

直接把對象URL放到<img>標簽中,就省去了把數據先讀到JS中的麻煩。另一方面,<img>標簽則會找到響應的記憶體地址,直接讀取數據並將圖像顯示在頁面中。

如果不再需要相應的數據,最好釋放它占用的記憶體。但只要有代碼在引用對象URL,記憶體就不會釋放。要手工釋放記憶體,可以把對象URL傳給window.URL.revokeObjectURL()(在Chrome中是window.webkitURL.revokeObjectURL()),相容寫法如下:

function revokeObjectURL(blob){
    if(window.URL){
        return window.URL.revokeObjectURL(blob);
    }else if(window.webkitURL){
        return window.webkitURL.revokeObjectURL(blob);
    }else{
        return null;
    }
}

支持對象URL的瀏覽器為IE10+、Firefox和Chrome。

讀取拖放的文件

從桌面上把文件拖放到瀏覽器中也會觸發drop事件。而且可以在event.dataTransfer.files中讀取到被放置的文件,當然此時它是一個File對象,與通過文件輸入欄位取得的File對象一樣。

下麵例子會將放置到頁面中自定義的放置目標中的文件信息顯示出來:

var droptarget = document.getElementById("droptarget");
function handleEvent(event){
    var info = "",
        output = document.getElementById("output"),
        files,
        i,
        len;
    EventUtil.preventDefault(event);
    if(event.type == "drop"){
        files = event.dataTransfer.files;
        i = 0;
        len = files.length;
        while(i < len){
            info += files[i].name + "(" + files[i].type + "," + files[i].size + "byte)<br/>";
            i ++;
        }
        output.innerHTML = info;
    }
}

EventUtil.addHandler(droptarget,"dragenter",handleEvent);
EventUtil.addHandler(droptarget,"dragover",handleEvent);
EventUtil.addHandler(droptarget,"drop",handleEvent);

使用XHR上傳文件

var droptarget = document.getElementById("droptarget");
function handleEvent(event){
    var info = "",
        output = document.getElementById("output"),
        data,xhr,
        files,i,len;
    EventUtil.preventDefault(event);
    if(event.type == "drop"){
        data = new FormData();
        files = event.dataTransfer.files;
        i = 0;
        len = files.length;
        while(i < len){
            data.append("file" + i,files[i]);
            i++;
        }
        xhr = new XMLHttpRequest();
        xhr.open("post","FileAPIUpload.php",true);
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                alert(xhr.responseText);
            }
        }
        xhr.send(data);
    }
}

EventUtil.addHandler(droptarget,"dragenter",handleEvent);
EventUtil.addHandler(droptarget,"dragover",handleEvent);
EventUtil.addHandler(droptarget,"drop",handleEvent);

Web計時

Web計時機制的核心是window.performance對象。window.performance對象有兩個屬性performance.navigationperformance.timing

Web Workers

隨著Web應用複雜性的與日俱進,越來越複雜的計算在所難免。長時間運行的Javascript進程會導致瀏覽器凍結用戶界面,讓人感覺屏幕“凍結”了。Web Workers規範通過讓JS在後臺運行解決了這個問題。瀏覽器實現Web Workers規範的方式有很多種,可以使用線程、後臺進程或者運行在其他處理器核心上的進程,等等。

目前支持Web Workers的瀏覽器IE10+以及其它高版本瀏覽器。

使用Worker

實例化Worker對象並傳入要執行的JS文件名就可以創建一個新的Worker,如下:

var worker = new Worker("js/index.js");

這行代碼會導致瀏覽器下載index.js,但只有接收到消息才會實際執行文件中的代碼。要給Worker傳遞消息,可以使用postMessage()方法(與XDM中的postMessage()方法類似):

worker.postMessage("start!");

消息內容可以是任何能被序列化的值,不過與XDM不同的是,在所有支持的瀏覽器中,postMessage()都能接收對象參數。因此,可以隨便傳遞任何形式的對象數據,如下例子:

worker.postMessage({
    type:"Command",
    message:"start!"
});

Worker是通過messageerror事件與頁面通信的。來自Worker的數據保存在event.data中。Worker返回的數據也可以是任何能被序列化的值:

worker.onmessage = function(event){
    var data = event.data;
    
    //對數據執行處理
}

Worker不能完成給定的任務時會觸發error事件。具體來說,Worker內部的JS在執行過程中只要遇到錯誤,就會觸發error事件。發生error事件時,事件對象包含三個屬性:filenamelinenomessage,分別表示發生錯誤的文件名、代碼行號和完整的錯誤信息。

worker.onerror = function(event){
    console.log("ERROR:" + event.filename + "(" + event.lineno + "):" + event.message);
}

只要調用terminate()方法就可以停止Worker的工作。

worker.terminate(); //立即停止Worker的工作

Worker全局作用域

Web Worker中的全局對象是worker對象本身。也就是說,在這個特殊的全局作用域中this和self引用的都是worker對象。為便於處理數據,Web Worker本身也是一個最小化的運行環境。

  • 最小化的navigator對象,包括onLine、appName、appVersion、userAgent和platform屬性。
  • 只讀的location對象。
  • setTimeout()、setInterval()、clearTimeout()和clearInterVal()方法。
  • XMLHttpRequest構造函數。

顯然,Web Worker的運行環境與頁面環境相比,功能是相當有限的。

當頁面在worker對象上調用postMessage()時,數據會以非同步方式被傳遞給worker,進而觸發worker中的message事件。為了處理來自頁面的數據,同樣也需要創建一個onmessage事件處理程式。

//Web Worker內部代碼
self.onmessage = function(event){
    var data = event.data;
    
    //處理數據
}

大家看清楚,這裡的self引用的是Worker全局作用域中的worker對象(與頁面中的Worker對象不同一個對象)。Worker完成工作後,通過調用postMessage()可以把數據再發回頁面。例如下麵的例子假如需要Worker對傳入的數組進行排序,而Worker在排序之後又將數組發回了頁面:

//Web Worker內部代碼
self.onmessage = function(event){
    var data = event.data;
    
    //別忘了,預設的sort方法只比較字元串
    data.sort(function(a,b){
        return a - b;
    })
    self.postMessage(data);
}

 傳遞消息就是頁面與Worker相互之間通信的方式。在Worker中調用postMessage()會以非同步的方式觸發頁面中Worker實例的message事件。如果頁面想要使用這個Worker,可以這樣:

//在頁面中
var data = [23,4,7,59,11,24,222,10,3],
    worker = new Worker("index.js");

worker.onmessage = function(event){
    var data = event.data;
    
    //對排序後的數組進行操作
    console.log(data);  //[3, 4, 7, 10, 11, 23, 24, 59, 222]
}

//將數組發送給worker排序
worker.postMessage(data);

在上面建立的index.js中,也就是在Worker作用域下代碼如下:

self.onmessage = function(event){
    var data = event.data;
    data.sort(function(a,b){
        return a - b;
    })
    self.postMessage(data);
}

排序的確是比較消耗時間的操作,因此轉交給Worker做就不會阻塞用戶界面了。另外把彩色圖像轉換成灰階圖像以及加密解密之類的操作也是相當費時的。

在Worker內部,調用close()方法也可以停止工作,Worker停止工作後就不會再有事件發生了。

//web worker內部的代碼
    self.close();

包含其它腳本

雖然無法在Worker中動態創建<script>元素,Worker的全局作用域提供了一個方法是importScripts(),這個方法接收一個或者多個指向JS文件的URL。每個載入過程都是非同步的,因此所有腳本載入並執行之後,importScripts()才會執行,如下代碼:

//web worker內部的代碼
importScripts("file1.js","file2.js");

即使file2.js優先於file1.js下載完,執行的時候仍然會按照先後順序執行。

Web Worker詳細可參考:《Web Worker 使用教程 - 阮一峰的網路日誌_阮一峰的個人網站


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ---游標更新刪除當前數據 ---1.聲明游標 declare orderNum_03_cursor cursor scroll for select OrderId ,userId from bigorder where orderNum='ZEORD003402' --2.打開游標 open o... ...
  • select row_number() over(order by a.column_id) rownumber, a.name, case when t.name in (N'decimal', N'numeric') then t.name + '('+ Convert(varchar(10),... ...
  • DB-Engines 資料庫流行度排行榜發佈了 5 月份的數據,排名前二十如下: 前六名千年不變,分別是:Oracle、MySQL、Microsoft SQL Server、PostgreSQL、MongoDB 和 IBM Db2。其中 PostgreSQL 雖然仍保持增長的趨勢,不過增加的分數和以 ...
  • select table_name from DBA_TAB_COLUMNS where COLUMN_NAME='欄位名';欄位名需要大寫 ...
  • 分享一個免費的ip地址庫查詢,同時支持ipv4和ipv6查詢,提供api介面。官網地址:https://www.calpha.club/ 希望可以幫助運維朋友們。 python 2.7實例# -*- coding: utf-8 -*- import urllib import urllib2 imp ...
  • 五一佳節匆匆而過,有人選擇在外面看人山人海,有人選擇宅在家中度過五一,也有人依然堅守在第一線,致敬! 這是堅持學習 的第二篇文章,可能會遲到,但是絕不會缺席,這篇要涉及到的是 " " ,也是rn社區主推的一個導航庫。 網上關於 的基本使用也是一抓一大把,這裡對於它的使用不做過多介紹,主要記錄使用過程 ...
  • 1. GCD 簡介 什麼是 GCD 呢?我們先來看看百度百科的解釋簡單瞭解下概念 引自百度百科 Grand Central Dispatch(GCD) 是 Apple 開發的一個多核編程的較新的解決方法。它主要用於優化應用程式以支持多核處理器以及其他對稱多處理系統。它是一個線上程池模式的基礎上執行的 ...
  • vue接入騰訊防水牆代碼 開始創建代碼: 登陸調用方法代碼 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...