vue中回調(diào)函數(shù)(callback)的用法舉例
一、介紹:
1、前提:在 js 中,函數(shù)也是對(duì)象,可以賦值給變量,可以作為參數(shù)放在函數(shù)的參數(shù)列表中,如:
var doSomething = function(a,b){
return a + b;
}
console.log(doSomething(2,3));2、概念:callback 是一種特殊的函數(shù),這個(gè)函數(shù)被作為參數(shù)傳給另一個(gè)函數(shù)去調(diào)用,這樣的函數(shù)就是回調(diào)函數(shù)。回調(diào),顧名思義,回頭再調(diào)。回調(diào)與同步、異步并沒有直接的聯(lián)系,回調(diào)只是一種實(shí)現(xiàn)方式,既可以有同步回調(diào),也可以有異步回調(diào),還可以有事件處理回調(diào)和延遲函數(shù)回調(diào)。
3、語法:在大多數(shù)編程語言中,函數(shù)的形參總是從外向內(nèi)傳遞參數(shù),但在JS中,如果形參碰到“關(guān)鍵字” callback 則完全相反,它表示從內(nèi)向外反向調(diào)用某個(gè)外部函數(shù)。
二、舉例
1、舉例介紹:
(1)第一步:
var fs = require("fs");
var c
function f(param) {
console.log(param)
}
function writeFile() {
fs.writeFile('input.txt', 'fs.writeFile 寫入文件的內(nèi)容', function (err) {
if (!err) {
console.log("文件寫入完成")
c = 1
}
});
}
c = 0
writeFile()
f(c)打印結(jié)果為0,因?yàn)槌绦蜻\(yùn)行到writeFile()這一行的時(shí)候,是一個(gè)比較耗時(shí)的IO操作,JS碰到這種操作并不會(huì)停在原地一直等待直到函數(shù)執(zhí)行完畢,而是直接運(yùn)行下一條代碼(即f©),而此時(shí) c = 1這一行代碼其實(shí)并沒有被執(zhí)行到,所以打印出來的結(jié)果還是0 !,如果希望打印1,可以使用第二步的代碼:
(2)第二步:
var fs = require("fs");
var c
function f(param) {
console.log(param)
}
function writeFile() {
fs.writeFile('input.txt', 'fs.writeFile 寫入文件的內(nèi)容', function (err) {
if (!err) {
console.log("文件寫入完成")
c = 1
f(c)
}
});
}
c = 0
writeFile() 這樣結(jié)果是對(duì)的,但是改成這樣并不完美,因?yàn)檫@么做就相當(dāng)于將f()寫死在writeFile()里了,如果此處我想根據(jù)不同的場(chǎng)景調(diào)用不同的函數(shù)還要寫幾個(gè)不同的writeFile(),而他們之間的區(qū)別僅僅是最后調(diào)用的那個(gè)函數(shù)不同,這里就體現(xiàn)callback的作用了(準(zhǔn)確地說callback并不真的是Javascript里的關(guān)鍵字,只是大家都約定成俗把callback這個(gè)單詞作為回調(diào)函數(shù)的默認(rèn)選擇)??聪率褂没卣{(diào)函數(shù)后的代碼:
(3)第三步:回調(diào)函數(shù)寫法
var fs = require("fs");
function f(param) {
console.log(param)
}
function writeFile(callback) { //callback,表示這個(gè)參數(shù)不是一個(gè)普通變量,而是一個(gè)函數(shù)
fs.writeFile('input.txt', 'fs.writeFile 寫入文件的內(nèi)容', function (err) {
if (!err) {
console.log("文件寫入完成")
c = 1
callback(c) // 因?yàn)槲覀儌鬟M(jìn)來的函數(shù)名是f(),所以此行相當(dāng)于調(diào)用一次f(c)
}
});
}
var c = 0
writeFile(f) // 函數(shù)f作為一個(gè)參數(shù)傳進(jìn)writeFile函數(shù)經(jīng)過改造后的代碼出現(xiàn)了兩次callback,第一個(gè)callback出現(xiàn)在writeFile的形參里,起定義的作用,表示這個(gè)參數(shù)并不是一個(gè)普通變量,而是一個(gè)函數(shù),即所謂的“以函數(shù)為參數(shù)”。 第二個(gè)callback出現(xiàn)在c = 1下面,表示此處“執(zhí)行”從形參傳遞進(jìn)來的那個(gè)函數(shù)。這樣一來,writeFile()函數(shù)在執(zhí)行完畢之后到底調(diào)用哪個(gè)函數(shù)就變“活”了,如果我們想writeFile()函數(shù)執(zhí)行完之后并不是像第二個(gè)例子那樣只能調(diào)用f(),而是還有別的函數(shù)比如說x() y() z(),那么只需要寫成 writeFile(x),writeFile(y)… 就行了。PS: 此處并不一定非要寫為“callback”,你可以任意寫成a,b,c…callback只是一種約定俗成的寫法,它明確地告訴代碼閱讀者:此處是一個(gè)回調(diào)函數(shù)。
但是這步寫法不夠簡(jiǎn)潔,一些函數(shù)的形參列表里直接嵌套一個(gè)函數(shù)的情況,其本質(zhì)上仍然是回調(diào)函數(shù),因?yàn)闆]有了函數(shù)名,所以也稱匿名函數(shù)。看下最終的簡(jiǎn)化寫法:
(4)第四步:匿名回調(diào)函數(shù)
var fs = require("fs");
function writeFile(callback) {
fs.writeFile('input.txt', '我是通過fs.writeFile 寫入文件的內(nèi)容', function (err) {
if (!err) {
console.log("文件寫入完畢!")
c = 1
callback(c)
}
});
}
var c = 0
writeFile(function (param) {
console.log(param)
})這是最簡(jiǎn)潔的寫法,再舉幾個(gè)例子:
var doit = function(callback)
{
var a = 1,
b = 2,
c = 3;
var t = callback(a,b,c);
return t + 10;
};
var d = doit(function(x,y,z){
return (x+y+z);
});
console.log(d);
export default {
created() {
this.testCallBack();
},
methods: {
testCallBack() {
let param = '測(cè)試'
this.myCallback(param, function (arg1, arg2) {
alert('這是回調(diào)' + arg1 + ' ' + arg2)
});
},
myCallback(param, callback) {
setTimeout(() => {
alert(param)
callback(param, '222');
}, 1000);
}
}
}
readImageFile(origin, quality, file) {
let that = this;
let fileName = file.name;
let reader = new FileReader();
reader.onload = function(evt) {
let base64File = evt.target.result;
that.imageCompress(
base64File,
origin,
{
quality
},
function(result) {
let blobFile = that.dataURLtoBlob(result);
let compressFile = new window.File([blobFile], fileName, { type: file.type });
that.uploadFile(compressFile);
}
);
};
reader.readAsDataURL(file);
},
// 壓縮圖片
imageCompress(path, Orientation, obj, callback) {
let img = new Image();
img.src = path;
img.onload = function() {
let that = this;
// 默認(rèn)按比例壓縮
let imgWidth = that.width;
let imgHeight = that.height;
let scale = imgWidth / imgHeight;
if (imgWidth > MAX_IMAGE_WIDTH) {
imgWidth = MAX_IMAGE_WIDTH;
imgHeight = imgWidth / scale;
}
let quality = obj.quality || 0.7; // 默認(rèn)圖片質(zhì)量為0.7
// 生成canvas
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
let anw = document.createAttribute('width');
let anh = document.createAttribute('height');
anw.nodeValue = imgWidth;
anh.nodeValue = imgHeight;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
ctx.drawImage(that, 0, 0, imgWidth, imgHeight);
// quality值越小,所繪制出的圖像越模糊
let base64 = canvas.toDataURL('image/jpeg', quality);
// 回調(diào)函數(shù)返回base64的值
callback(base64);
};
},
function doSomething(msg, callback){
alert(msg);
if(typeof callback == "function")
callback();
}
doSomething("回調(diào)函數(shù)", function(){
alert("匿名函數(shù)實(shí)現(xiàn)回調(diào)!");
}); 2、常見的回調(diào)函數(shù)例子:

三、回調(diào)函數(shù)中this的指向:
callback中的this指向window。可以使用Call和Apply函數(shù)來改變this指向,每個(gè)Javascript中的函數(shù)都有兩個(gè)方法:Call 和 Apply。這些方法被用來設(shè)置函數(shù)內(nèi)部的this對(duì)象以及給此函數(shù)傳遞變量。
舉例:
var clientData = {
id: 096545,
fullName: "Not Set",
//setUsrName是一個(gè)在clientData對(duì)象中的方法
setUserName: function (firstName, lastName){
this.fullName = firstName + " " + lastName;
}
}
function getUserInput(firstName, lastName, callback){
//code .....
//調(diào)用回調(diào)函數(shù)存儲(chǔ)
callback(firstName, lastName);
}
getUserInput("Barack","Obama",clientData.setUserName);
console.log(clientData.fullName); //Not Set
console.log(window.fullName); //Barack Obama在上面的代碼中,當(dāng)clientData.setUsername被執(zhí)行時(shí),this.fullName并沒有設(shè)置clientData對(duì)象中的fullName屬性,它將設(shè)置window對(duì)象中的fullName屬性。
下面我們看下Apply函數(shù)實(shí)現(xiàn),Call函數(shù)類似。(call接收的第一個(gè)參數(shù)為被用來在函數(shù)內(nèi)部當(dāng)做this的對(duì)象,傳遞給函數(shù)的參數(shù)被挨個(gè)傳遞。Apply函數(shù)的第一個(gè)參數(shù)也是在函數(shù)內(nèi)部作為this的對(duì)象,然而最后一個(gè)參數(shù)確是傳遞給函數(shù)的值的數(shù)組。)
//注意到我們?cè)黾恿诵碌膮?shù)作為回調(diào)對(duì)象,叫做“callbackObj”
function getUserInput(firstName, lastName, callback ,callbackObj){
//code .....
callback.apply(callbackObj, [firstName, lastName]);
}
getUserInput("Barack", "Obama", clientData.setUserName, clientData);
console.log(clientData.fullName); //Barack Obama四、回調(diào)函數(shù)的使用場(chǎng)景:
1、回調(diào)函數(shù)經(jīng)常使用于以下場(chǎng)景:
異步調(diào)用(例如讀取文件,進(jìn)行HTTP請(qǐng)求,動(dòng)態(tài)加載js文件,加載iframe資源后,圖片加載完成執(zhí)行回調(diào)等等)事件監(jiān)聽器/處理器setTimeout和setInterval方法一般情況:精簡(jiǎn)代碼
2、以異步調(diào)用為例,回調(diào)函數(shù)與異步編程:回調(diào)函數(shù)是實(shí)現(xiàn)異步編程的利器,在程序運(yùn)行中,當(dāng)某些請(qǐng)求過程漫長,我們有時(shí)沒必要選擇等待請(qǐng)求完成繼續(xù)處理下一個(gè)任務(wù),這時(shí)使用回調(diào)函數(shù)進(jìn)行異步處理可以大大提高程序執(zhí)行效率。例如:AJAX請(qǐng)求。若是使用回調(diào)函數(shù)進(jìn)行處理,代碼就可以繼續(xù)進(jìn)行其他任務(wù),而無需空等。實(shí)際開發(fā)中,經(jīng)常在javascript中使用異步調(diào)用!下面有個(gè)使用AJAX加載XML文件的示例,并且使用了call()函數(shù),在請(qǐng)求對(duì)象(requested object)上下文中調(diào)用回調(diào)函數(shù)。
function fn(url, callback){
var httpRequest; //創(chuàng)建XHR
httpRequest = window.XMLHttpRequest ? new XMLHttpRequest() : //針對(duì)IE進(jìn)行功能性檢測(cè)
window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : undefined;
httpRequest.onreadystatechange = function(){
if(httpRequest.readystate === 4 && httpRequest.status === 200){ //狀態(tài)判斷
callback.call(httpRequest.responseXML);
}
};
httpRequest.open("GET", url);
httpRequest.send();
}
fn("text.xml", function(){ //調(diào)用函數(shù)
console.log(this); / /此語句后輸出
});
console.log("this will run before the above callback."); //此語句先輸出總結(jié)
到此這篇關(guān)于vue中回調(diào)函數(shù)(callback)的用法舉例的文章就介紹到這了,更多相關(guān)vue回調(diào)函數(shù)callback用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3中通過ref獲取元素節(jié)點(diǎn)的實(shí)現(xiàn)
這篇文章主要介紹了vue3中通過ref獲取元素節(jié)點(diǎn)的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
vue大文件分片上傳之simple-uploader.js的使用
本文主要介紹了vue大文件分片上傳之simple-uploader.js的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
Fragment 占位組件不生成標(biāo)簽與路由組件lazyLoad案例
這篇文章主要為大家介紹了Fragment 占位組件不生成標(biāo)簽與路由組件lazyLoad案例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
Vue循環(huán)遍歷選項(xiàng)賦值到對(duì)應(yīng)控件的實(shí)現(xiàn)方法
這篇文章主要介紹了Vue-循環(huán)遍歷選項(xiàng)賦值到對(duì)應(yīng)控件的實(shí)現(xiàn)方法啊,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
解決vue創(chuàng)建項(xiàng)目使用vue-router和vuex報(bào)錯(cuò)Object(...)is not a&nb
這篇文章主要介紹了解決vue創(chuàng)建項(xiàng)目使用vue-router和vuex報(bào)錯(cuò)Object(...)is not a function問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02

