關(guān)于vue data中的this指向問題
vue data的this指向
在data里定義Object類型的變量時,會發(fā)現(xiàn)Object中訪問不到vue的this屬性。
例如:
export default {
? data(){
? ? return {
? ? ? a: "123",
? ? ? b: {
? ? ? ? c: this.a
? ? ? }
? ? };
? },
? created() {
? ? console.log("b: ", this.b.c); // undefined
? }
}想在b中訪問this.a的數(shù)據(jù),直接訪問會返回undefined,因為這時c中的this指向的是b。
這種情況可以用到Object的get屬性進行屬性定義。
例如:
export default {
? data(){
? ? return {
? ? ? a: "123",
? ? ? b: {
? ? ? ? _target: () => this,
? ? ? ? get target() {
? ? ? ? ? return this._target();
? ? ? ? },
? ? ? ? get c() {
? ? ? ? ? return this.target.a;
? ? ? ? },
? ? ? },
? ? };
? },
? created() {
? ? console.log("b: ", this.b.c); // 123
? }
}此處將this映射到了Object變量內(nèi)部,然后通過get的形式定義屬性并獲取。
當(dāng)get定義的屬性所依賴的屬性的值發(fā)生改變時,get定義的屬性的值也將發(fā)生改變。
例如:
export default {
? data(){
? ? return {
? ? ? a: "123",
? ? ? b: {
? ? ? ? _target: () => this,
? ? ? ? get target() {
? ? ? ? ? return this._target();
? ? ? ? },
? ? ? ? get c() {
? ? ? ? ? return this.target.a;
? ? ? ? },
? ? ? ? d: 123,
? ? ? ? get e() {
? ? ? ? ? return `依賴于d的值, 會同步發(fā)生改變, d的值為: ${this.d}`;
? ? ? ? }
? ? ? },
? ? };
? },
? created() {
? ? console.log("b: ", this.b.c); // 123
? ? console.log("e: ", this.b.e); // e: ?依賴于d的值, 會同步發(fā)生改變, d的值為: 123 c: 123
? ? setTimeout(() => {
? ? ? this.b.d = 456;
? ? ? console.log("e: ", this.b.e); // e: ?依賴于d的值, 會同步發(fā)生改變, d的值為: 456 c: 123
? ? }, 1000);
? ? setTimeout(() => {
? ? ? this.a = "456";
? ? ? console.log("e: ", this.b.e); // e: ?依賴于d的值, 會同步發(fā)生改變, d的值為: 456 c: 456
? ? }, 2000);
? }
}當(dāng)前方法更像是一種深度計算屬性(computed),會隨著所依賴的項發(fā)生改變而改變。
vue關(guān)于this指向的重要原則
在學(xué)習(xí)js的時候,偶爾會涉及到this的指向問題。大部分情況下,在一個函數(shù)中,誰調(diào)用這個函數(shù),this就指向誰。
在Vue中,this的指向卻顯得尤為重要。本節(jié)博客將為大家解釋Vue中this的指向問題,同時告訴讀者,為什么this的指向在Vue中非常重要,以及我們在平時寫Vue代碼時需要注意的相關(guān)內(nèi)容。
vue底層的相關(guān)原理
1.1 MVVM模型的復(fù)習(xí)
Vue的設(shè)計收到了MVVM模型的影響,在看this指向問題前,我想帶讀者們復(fù)習(xí)一下MVVM模型的相關(guān)知識。
M:Model模型,對應(yīng)的是data中的數(shù)據(jù);V:View視圖,對應(yīng)的是模板,也就是頁面結(jié)構(gòu);VM:視圖模型,對應(yīng)的是Vue實例對象。
這里用一個html文件給大家劃分一下具體結(jié)構(gòu):

1.2 通過差值語法看vm的屬性
所有vm中的屬性,利用差值語法都可以看到。
為了測試,我們先看看vm是什么。此處,我們先打印一下this,可以看到此時的this是Vue。
準確來說使我們創(chuàng)建的Vue實例。這里面的所有屬性都可以通過插值語法看到。

為了驗證上面說的話,現(xiàn)在我利用差值語法隨意看Vue實例對象中的一些東西:


1.3 為什么差值語法可以看到vm的內(nèi)部屬性
==因為在Vue中,this指向的是vm實例對象Vue。==所以可以利用this看到vm的所有屬性。希望讀者朋友們可以牢記這一點。
記住這一點在時時刻刻的應(yīng)用中:我們不要輕易的改變this的指向,如若改變,this不再是vm,頁面上的元素將無法正常被渲染。
這里給大家看一個例子:
這段代碼的需求是,在 頁面中寫出姓和名,讓Vue幫我們合成姓名。并且在我們修改姓或者名后停頓1s后再幫我們合成。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"><br>
名:<input type="text" v-model="lastName"><br>
全名:<span>{{ fullName }}</span>
</div>
<script>
new Vue({
el: '#root',
data: {
firstName: '張',
lastName: '三',
fullName: ''
},
watch: {
firstName(newValue, oldValue) {
setTimeout(() => {
this.fullName = newValue + this.lastName
console.log(this)
}, 1000)
},
lastName(newValue, oldValue) {
setTimeout(() => {
this.fullName = this.firstName + newValue
console.log(this)
}, 1000)
}
}
})
</script>
</body>
</html>上述代碼是沒有什么問題的。并且在定時器中,使用箭頭函數(shù),打印出來的this都是vue實例

原因:箭頭函數(shù)中的this指向它的外層調(diào)用者。
現(xiàn)在看一個反例:我們把箭頭函數(shù)改成普通函數(shù),則會出現(xiàn)問題:
<body>
<div id="root">
姓:<input type="text" v-model="firstName"><br>
名:<input type="text" v-model="lastName"><br>
全名:<span>{{ fullName }}</span>
</div>
<script>
new Vue({
el: '#root',
data: {
firstName: '張',
lastName: '三',
fullName: ''
},
watch: {
firstName(newValue, oldValue) {
setTimeout(() => {
this.fullName = newValue + this.lastName
console.log(this)
}, 1000)
},
// lastName(newValue, oldValue) {
// setTimeout(() => {
// this.fullName = this.firstName + newValue
// console.log(this)
// }, 1000)
// }
// 這是一個錯誤寫法,因為它改變了this的指向。它的this是window。那么就沒辦法讀到vue中的數(shù)據(jù)了
lastName(newValue, oldValue) {
setTimeout(function() {
this.fullName = this.firstName + newValue
console.log(this)
}, 1000)
}
}
})
</script>沒辦法正常運行并且,this打印出來的是window:


==原因:普通函數(shù)中的this指向它的直接調(diào)用者。
==由于定時器的this指向的是window。此時此刻,改變了this的指向,所以會報錯。
心得
1.所被Vue管理的函數(shù),最好寫成普通函數(shù)。這樣的this指向?qū)嵗龑ο螅?/p>
2.所有不被Vue所管理的函數(shù)(定時器,ajax,回調(diào))最好寫成箭頭函數(shù),這樣this依舊指向Vue或者組件的實例對象。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用vue-router切換頁面時實現(xiàn)設(shè)置過渡動畫
今天小編就為大家分享一篇使用vue-router切換頁面時實現(xiàn)設(shè)置過渡動畫。具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10
element-plus日歷(Calendar)動態(tài)渲染以及避坑指南
這篇文章主要給大家介紹了關(guān)于element-plus日歷(Calendar)動態(tài)渲染以及避坑指南的相關(guān)資料,這是最近幫一個后端朋友處理一個前端問題,elementUI中calendar日歷組件內(nèi)容進行自定義顯示,實現(xiàn)類似通知事項的日歷效果,需要的朋友可以參考下2023-08-08
Vue基礎(chǔ)之MVVM,模板語法和數(shù)據(jù)綁定
這篇文章主要為大家介紹了Vue之MVVM,模板語法和數(shù)據(jù)綁定,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2021-12-12
select的change方法傳遞多個參數(shù)的方法詳解
element-ui中的select,checkbox等組件的change方法的回調(diào)函數(shù)只有當(dāng)前選擇的val,如果想再傳入自定義參數(shù)怎么辦,本文給大家分享select的change方法如何傳遞多個參數(shù),感興趣的朋友一起看看吧2024-02-02

