Vue箭頭函數(shù)與普通函數(shù)的正確使用及說明
在 Vue 項目中,你是否遇到過這樣的場景:
明明寫了正確的邏輯,卻因為用錯函數(shù)類型,導(dǎo)致this.msg拿不到值、點擊事件不生效?其實,這大多是箭頭函數(shù)與普通函數(shù)的this指向差異在 “搞鬼”。
本文不堆砌理論,而是從實際開發(fā)痛點出發(fā),結(jié)合 Vue 2/3 的不同場景,帶你搞懂兩種函數(shù)的用法邊界,徹底避免這類低級錯誤。
一、先解決核心困惑:為什么用錯函數(shù)會出問題?
Vue 中函數(shù)報錯的根源,90% 都和this指向有關(guān)。
箭頭函數(shù)與普通函數(shù)的本質(zhì)差異,就體現(xiàn)在this的綁定規(guī)則上 —— 這是我們判斷 “該用哪種函數(shù)” 的唯一核心標(biāo)準(zhǔn)。
1. 一張表分清兩種函數(shù)的關(guān)鍵差異
| 對比維度 | 普通函數(shù)(function) | 箭頭函數(shù)(() => {}) |
|---|---|---|
| this綁定 | 動態(tài):誰調(diào)用,this就指向誰 | 靜態(tài):定義時繼承外層非箭頭函數(shù)的this |
| 適用場景 | 需要訪問 Vue 實例(data/props)時 | 無需綁定實例,需固定this時 |
| 能否當(dāng)構(gòu)造函數(shù) | 能(new Function()) | 不能(報錯) |
| 能否用arguments | 能(獲取所有實參) | 不能(需用...rest參數(shù)) |
| 語法復(fù)雜度 | 需寫function,代碼稍長 | 省略function,簡潔(僅匿名) |
2. 最關(guān)鍵的this指向?qū)Ρ龋ǜ?Vue 場景示例)
- 普通函數(shù):
this是 “跟著調(diào)用者走” 的。比如 Vue 組件的methods里,函數(shù)由組件實例(vm)調(diào)用,所以this自然指向vm,能拿到this.data里的內(nèi)容。 - 箭頭函數(shù):
this是 “跟著定義環(huán)境走” 的。它不會自己綁定this,而是 “抄” 外層非箭頭函數(shù)的this。如果外層沒有非箭頭函數(shù),this就會變成window(瀏覽器)或undefined(嚴(yán)格模式)。 - 舉個直觀的例子:
<script>
export default {
data() {
return { name: "Vue" };
},
created() {
// 普通函數(shù):由this(組件實例)調(diào)用,this指向?qū)嵗?
const normalFunc = function() {
console.log(this.name); // 輸出"Vue"
};
normalFunc.call(this); // 主動綁定this為組件實例
// 箭頭函數(shù):繼承外層created的this(組件實例)
const arrowFunc = () => {
console.log(this.name); // 輸出"Vue"
};
arrowFunc(); // 無需綁定,this已固定
// 注意:如果箭頭函數(shù)外層是普通函數(shù),this會變
const outerFunc = function() {
const innerArrow = () => {
console.log(this.name); // 這里的this是outerFunc的this(若未綁定則為window)
};
innerArrow();
};
outerFunc(); // 輸出undefined(因為outerFunc的this是window)
}
};
</script>
二、Vue 2/3 通用場景:哪些地方必須用普通函數(shù)?
這些場景的核心需求是 “訪問 Vue 實例”,箭頭函數(shù)會直接導(dǎo)致this失效,哪怕代碼能運行,也會埋下隱患。
1.methods中的事件處理函數(shù)(絕對不能用箭頭函數(shù))
methods里的函數(shù)要綁定到模板事件(如@click、@input),Vue 會自動把函數(shù)的this綁定到組件實例。
如果用箭頭函數(shù),this會繼承methods定義時的外層環(huán)境(通常是window),導(dǎo)致無法訪問實例數(shù)據(jù)。
- 錯誤示范(點擊按鈕無反應(yīng),控制臺報錯):
<template>
<button @click="changeName">修改名稱</button>
<p>{{ name }}</p>
</template>
<script>
export default {
data() {
return { name: "初始名稱" };
},
methods: {
// 錯誤:箭頭函數(shù)的this不是組件實例
changeName: () => {
this.name = "修改后名稱"; // 報錯:Cannot set property 'name' of undefined
}
}
};
</script>
- 正確示范(點擊按鈕正常修改):
methods: {
// 普通函數(shù):this指向組件實例
changeName() {
this.name = "修改后名稱"; // 正常生效
}
}
2.computed計算屬性(必須用普通函數(shù))
computed需要依賴data或props計算值,普通函數(shù)能確保this指向?qū)嵗^函數(shù)會導(dǎo)致依賴無法讀取。
- 正確寫法:
computed: {
fullName() {
// 普通函數(shù):this能拿到firstName和lastName
return `${this.firstName} ${this.lastName}`;
}
}
3.watch監(jiān)聽器(推薦用普通函數(shù))
watch需要在數(shù)據(jù)變化時執(zhí)行邏輯(如修改其他數(shù)據(jù)、調(diào)用接口),普通函數(shù)的this能直接操作實例,箭頭函數(shù)會導(dǎo)致邏輯失效。
- 正確寫法:
watch: {
// 監(jiān)聽name變化,更新日志
name(newVal, oldVal) {
this.log = `名稱從${oldVal}變成${newVal}`; // this指向?qū)嵗?,正常更?
}
}
4. 生命周期鉤子(Vue 2 推薦普通函數(shù),Vue 3setup外同)
Vue 2 的created、mounted等鉤子,雖然用箭頭函數(shù) “看似能運行”(因為鉤子的this是實例,箭頭函數(shù)會繼承),但不符合 Vue 設(shè)計規(guī)范,且后續(xù)維護(hù)者容易誤解this來源。Vue 3 的Options API(非setup)場景同理。
- 推薦寫法:
// Vue 2 / Vue 3 Options API
export default {
mounted() {
this.initData(); // 普通函數(shù):this指向?qū)嵗?,調(diào)用methods方法
},
methods: {
initData() {
// 初始化邏輯
}
}
};
三、Vue 2/3 通用場景:哪些地方推薦用箭頭函數(shù)?
這些場景不需要訪問 Vue 實例,或需要固定this指向,箭頭函數(shù)能讓代碼更簡潔,避免手動綁定this的麻煩。
1. 數(shù)組方法回調(diào)(map/filter/forEach等)
數(shù)組方法的回調(diào)函數(shù)如果用普通函數(shù),this會指向window(非嚴(yán)格模式),需要用that = this或bind(this)綁定;用箭頭函數(shù)能直接繼承外層實例的this,代碼更簡潔。
- 對比示例:
methods: {
handleList() {
const list = [1, 2, 3];
// 普通函數(shù):需要手動保存this
const normalResult = list.map(function(item) {
return item * this.multiplier; // 這里的this是window,需綁定
}.bind(this)); // 綁定this為組件實例
// 箭頭函數(shù):自動繼承外層this(handleList的this是實例)
const arrowResult = list.map(item => {
return item * this.multiplier; // 直接使用實例的multiplier
});
console.log(arrowResult); // 正確輸出:[2,4,6](若multiplier=2)
},
data() {
return { multiplier: 2 };
}
}
2. 異步請求回調(diào)(axios/Promise)
異步操作的回調(diào)函數(shù)(如接口請求成功 / 失敗后),普通函數(shù)的this會指向回調(diào)的調(diào)用者(如axios內(nèi)部對象),而非 Vue 實例;箭頭函數(shù)能繼承外層實例的this,方便后續(xù)操作數(shù)據(jù)。
- 正確示例(接口請求后更新數(shù)據(jù)):
methods: {
fetchUser() {
// 外層this是組件實例
axios.get("/api/user")
.then(res => {
// 箭頭函數(shù):this指向?qū)嵗?,更新data
this.userInfo = res.data;
})
.catch(err => {
// 箭頭函數(shù):this指向?qū)嵗?,更新錯誤信息
this.errorMsg = err.message;
});
}
}
3. Vue 3setup函數(shù)內(nèi)(全部用箭頭函數(shù))
Vue 3 的Composition API中,setup函數(shù)沒有this(this指向undefined),所有函數(shù)定義都推薦用箭頭函數(shù),避免依賴this導(dǎo)致混亂。
- 示例:
<script setup>
import { ref } from "vue";
const count = ref(0);
// 箭頭函數(shù):無需考慮this,直接操作ref
const increment = () => {
count.value++; // 正確修改ref值
};
// 異步請求示例
const fetchData = () => {
axios.get("/api/data")
.then(res => {
// 直接操作ref或reactive數(shù)據(jù)
});
};
</script>
<template>
<button @click="increment">{{ count }}</button>
</template>
四、避坑指南:90% 開發(fā)者會犯的 3 個錯誤
錯誤 1:在methods中混用箭頭函數(shù)和普通函數(shù)
有些開發(fā)者為了 “簡潔”,在methods中部分函數(shù)用箭頭函數(shù),導(dǎo)致部分功能失效。記?。?code>methods里所有函數(shù)都必須用普通函數(shù)。
錯誤 2:Vue 2 生命周期鉤子用箭頭函數(shù)
雖然 Vue 2 中created: () => { this.init() }能運行,但這是 “巧合”—— 如果后續(xù)修改外層代碼(如把鉤子函數(shù)嵌套到其他函數(shù)中),this會立即失效。
錯誤 3:Vue 3setup中用普通函數(shù)
setup中沒有this,普通函數(shù)的this是undefined,如果在普通函數(shù)中用this,會直接報錯。比如:
<script setup>
// 錯誤:setup中普通函數(shù)的this是undefined
const wrongFunc = function() {
console.log(this.count); // 報錯:Cannot read property 'count' of undefined
};
</script>
五、總結(jié):1 個判斷標(biāo)準(zhǔn),搞定所有場景
遇到函數(shù)定義時,不用記復(fù)雜規(guī)則,只需問自己:這個函數(shù)需要訪問 Vue 實例的data/props/methods嗎?
- 是 → 用普通函數(shù)(如
methods、computed、watch); - 否 → 用箭頭函數(shù)(如數(shù)組回調(diào)、異步回調(diào)、Vue 3
setup)。
掌握這個標(biāo)準(zhǔn),就能徹底避免 Vue 中因函數(shù)類型用錯導(dǎo)致的this問題,讓代碼邏輯更清晰、更易維護(hù)。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解基于 Nuxt 的 Vue.js 服務(wù)端渲染實踐
這篇文章主要介紹了詳解基于 Nuxt 的 Vue.js 服務(wù)端渲染實踐,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10
Vue.js 帶下拉選項的輸入框(Textbox with Dropdown)組件
這篇文章主要介紹了Vue.js 帶下拉選項的輸入框(Textbox with Dropdown)組件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04

