<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
問題
最近在使用自定義指令時遇到一個問題,我想在指令裡通過this直接去存取vue範例資料,但是顯示未定義,經大佬提醒,裡面的this很可能不是指向vue範例
在函數裡增加第三個引數vnode,vnode.context就是指向當前的vue範例
總結
指令裡的this不是指向vue範例,可以使用vnode.context獲取this
自定義指令可傳入以下引數
el
:指令所繫結的元素,可以用來直接操作 DOM。binding
:一個物件,包含以下 property:name
:指令名,不包括 v- 字首。value
:指令的繫結值,例如:v-my-directive=“1 + 1” 中,繫結值為 2。oldValue
:指令繫結的前一個值,僅在 update 和 componentUpdated 勾點中可用。無論值是否改變都可用。expression
:字串形式的指令表示式。例如 v-my-directive=“1 + 1” 中,表示式為 “1 + 1”。arg
:傳給指令的引數,可選。例如 v-my-directive:foo 中,引數為 “foo”。modifiers
:一個包含修飾符的物件。例如:v-my-directive.foo.bar 中,修飾符物件為 { foo: true, bar: true }。vnode
:Vue 編譯生成的虛擬節點。oldVnode
:上一個虛擬節點,僅在 update 和 componentUpdated 勾點中可用。最近寫vue專案遇到很多this指向的問題,今天來寫一下我總結的this指向
看了很多文章、部落格,對於正常函數,誰呼叫的它,this就指向誰,而箭頭函數沒有this,它的this指向一般就是上下文中,與誰呼叫它沒關係。
但是在Vue範例中,methods、生命週期函數中如果用的是正常函數,那麼它的this就指向Vue範例,也就是vm(本文中的vm是指const vm = new Vue({···})中的vm);如果是箭頭函數,在非嚴格模式下this就指向window物件,嚴格模式下是undefind。
這裡我分別來說一下普通函數中的this和Vue中的this
普通函數的this是由動態作用域決定,它總指向於它的直接呼叫者。具體可以分為以下四項:this總是指向它的直接呼叫者, 例如 obj.func() ,那麼func()裡的this指的是obj。在預設情況(非嚴格模式,未使用 'use strict'),如果函數沒有直接呼叫者,this為window;在嚴格模式下,如果函數沒有直接調者,this為undefined使用call,apply,bind繫結的,this指的是繫結的物件
簡單總結:
(1)全域性函數中的this指向window
(2)物件中的方法(函數)中的this,指向物件,理解:obj.m=function(){},m和fn等價,因此呼叫m也相當於呼叫fn,原理同3)
(3)建構函式中的this指向呼叫該建構函式的範例物件
(4)特殊this指向: 箭頭函數沒有繫結this,this繼承自外圍作用域,理解:檢視上一層級的函數的this的指向,繼承它!!
(5)繫結this指向:apply,call,bind繫結的物件
接下來用範例來介紹下各種this問題
1.全域性環境下,this 始終指向全域性物件(window), 無論是否嚴格模式
console.log(this.document === document); // true // 在瀏覽器中,全域性物件為 window 物件: console.log(this === window); // true this.a = 3; console.log(window.a); // 3
2.函數直接呼叫,普通函數內部的this分兩種情況,嚴格模式和非嚴格模式
//嚴格模式下, this為undefined function f2(){ "use strict"; // 這裡是嚴格模式 return this; } f2() === undefined; // true //而非嚴格模式下,this 預設指向全域性物件window function f1(){ return this; } f1() === window; // true
3.物件中的this,物件內部方法的this指向呼叫這些方法的物件
//函數的定義位置不影響其this指向,this指向只和呼叫函數的物件有關。 //多層巢狀的物件,內部方法的this指向離被呼叫函數最近的物件(window也是物件,其內部物件調 //用方法的this指向內部物件, 而非window)。 //例一: var obj = { prop: 37, f: function() { return this.prop; } }; console.log(obj.f()); //37 var a = obj.f; console.log(a()); //undefined var obj = {prop: 37}; function independent() { return this.prop; } obj.f = independent; console.log(obj.f()); //37 //例二: obj.b = { num: independent, prop: 42 }; console.log(obj.b.num()); //42
4.原型鏈中this,原型鏈中的方法的this仍然指向呼叫它的物件
var obj = { f : function(){ return this.a + this.b; } }; var p = Object.create(obj); p.a = 1; p.b = 4; console.log(p.f()); // 5 //在p中沒有屬性f,當執行p.f()時,會查詢p的原型鏈,找到 f 函數並執行,但這與函數內部this指向物件 //p 沒有任何關係,只需記住誰呼叫指向誰。 //以上對於函數作為getter & setter 呼叫時同樣適用。
5.建構函式中this,建構函式中的this與被建立的新物件繫結
注意:當構造器返回的預設值是一個this參照的物件時,可以手動設定返回其他的物件,如果返回值不是一個物件,返回this。
6.call & apply
當函數通過Function物件的原型中繼承的方法 call() 和 apply() 方法呼叫時, 其函數內部的this值可繫結到 call() & apply() 方法指定的第一個物件上, 如果第一個引數不是物件,JavaScript內部會嘗試將其轉換成物件然後指向它。
7.bind 方法
bind方法在ES5引入, 在Function的原型鏈上, Function.prototype.bind。通過bind方法系結後, 函數將被永遠繫結在其第一個引數物件上, 而無論其在什麼情況下被呼叫。
8.DOM事件處理常式,當函數被當做監聽事件處理常式時, 其 this 指向觸發該事件的元素 (針對於addEventListener事件)
// 被呼叫時,將關聯的元素變成藍色 function bluify(e){ console.log(this);//在控制檯列印出所點選元素 e.stopPropagation();//阻止時間冒泡 e.preventDefault();//阻止元素的預設事件 this.style.backgroundColor = '#A5D9F3'; } var elements = document.getElementsByTagName('*');// 獲取檔案中的所有元素的列表 // 將bluify作為元素的點選監聽函數,當元素被點選時,就會變成藍色 for(var i=0 ; i<elements.length ; i++){ elements[i].addEventListener('click', bluify, false); }
9.內聯事件,內聯事件中的this指向分兩種情況:
10.setTimeout & setInterval,對於延時函數內部的回撥函數的this指向全域性物件window(當然我們可以通過bind方法改變其內部函數的this指向)
//預設情況下 function Person() { this.age = 0; setTimeout(function() { console.log(this); }, 3000); } //通過bind繫結 function Person() { this.age = 0; setTimeout((function() { console.log(this); }).bind(this), 3000); } var p = new Person();//3秒後返回建構函式新生成的物件 Person{...}
11.箭頭函數中的 this,由於箭頭函數不繫結this, 它會捕獲其所在(即定義的位置)上下文的this值, 作為自己的this值
// call() / apply() / bind() 方法對於箭頭函數來說只是傳入引數,對它的 this 毫無影響。 //考慮到 this 是詞法層面上的,嚴格模式中與 this 相關的規則都將被忽略。(可以忽略是否在嚴格 //模式下的影響) //因為箭頭函數可以捕獲其所在上下文的this值 所以: function Person() { this.age = 0; setInterval(() => { this.age++;// 回撥裡面的 `this` 變數就指向了期望的那個物件了 }, 3000); } var p = new Person(); //以上程式碼可以得到我們所以希望的值,下圖可以看到,在setTimeout中的this指向了建構函式新生成 //的物件,而普通函數指向了全域性window物件
1.Vue methods
來看看官方檔案給出的解釋:
methods 將被混入到 Vue 範例中。可以直接通過 範例vm 存取這些方法,或者在指令表示式中使用。方法中的 this自動繫結為 Vue 範例(vm)。
注意,不應該使用箭頭函數來定義 method 函數 (例如 plus: () => this.a++)。理由是箭頭函數繫結了父級作用域的上下文,所以 this 將不會按照期望指向 Vue 範例,this.a 將是 undefined。
長話短說,官方的意思是:在Vue範例中,methods中如果用的是正常函數,那麼它的this就指向Vue範例;如果是箭頭函數,this就指向window物件;
總結:
Vue methods 中不應該箭頭函數定義methods函數,因為箭頭函數繫結了父級作用域上下文,所以 this 列印出的結果是Window 物件;不使用箭頭函數的情況下,this 實際上是指向了一個 Proxy 物件。
原因是vue 內部實際上對methods屬性中的方法進行了遍歷,將對應的方法通過bind繫結了this,使得this指向範例vm
2.Vue中生命週期勾點和自定義方法中的this指向當前的 Vue 範例
所有的生命週期勾點自動繫結 this 上下文到範例中,因此你可以存取資料,對 property 和方法進行運算。這意味著你不能使用箭頭函數來定義一個生命週期方法 (例如 created: () => this.checkTodos())。這是因為箭頭函數繫結了父上下文,因此 this 與你期待的 Vue 範例不同,this.checkTodos 的行為未定義。
3. Vue 中回撥函數中的 this:
4. Vue 中 addEventListener 中的 this
通常,事件監聽函數中的 this 都指向繫結事件的那個元素, 但是在 Vue 中,監聽函數中的 this 也指向 Vue 範例
5.在data裡定義Object型別的變數時的this
在data裡定義Object型別的變數時,會發現Object中存取不到vue的this屬性,例如:
export default { data(){ return { a: "123", b: { c: this.a } }; }, created() { console.log("b: ", this.b.c); // undefined } }
想在b中存取this.a的資料,直接存取會返回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變數內部,然後通過get的形式定義屬性並獲取,這樣就解決問題啦。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45