比如el-upload中的 :on-success= fn,其實是給組件el-upload傳遞一個prop,這樣寫的話fn只能接受upload組件規定的參數,如果想自己傳遞父組件中的參數比如b,要寫成:on-success= ()=>{fn2(b)}
原理要從Vue的render函數的生成講起
第一種情況:v-bind,綁定普通方法
<child :trans_method="test">點擊</child>
它的父元素的render函數是這樣的:
ƒ anonymous(
) {
with(this){return _c('div',{attrs:{"id":"app"}},[_c('child',{attrs:{"trans_method":test}},[_v("點擊")])],1)}
}
這里的this是父組件vm,可以看到子組件將來接受到的trans_method將會是test這個方法,v-bind是給子元素的屬性,如果子元素是普通節點而不是組件節點,v-bind一個方法是沒啥用的,如果子元素是組件節點,這個屬性傳遞給子組件后,怎么調用要看子組件的邏輯,這里是形成不了閉包(這個說法有問題,准確的表達應該是“新生成一個匿名函數,它的會保留作用域鏈上的this的屬性傳遞出去”,但是意思知道就行)的。
第二種情況:v-bind,綁定匿名方法:
<child :trans_method="()=>{fn1(name)}">點擊</child>,
render函數是這樣的
ƒ anonymous(
) {
with(this){return _c('div',{attrs:{"id":"app"}},[_c('child',{attrs:{"trans_method":()=>{fn1(name)}}},[_v("點擊")])],1)}
}
可見能形成閉包,匿名函數的參數是子組件調用的時候傳入,fn1可以傳入父組件的參數。
第三種情況,再進一步 如果寫成數組:
<child v-for="item in array" :trans_method="()=>{fn1(item)}">點擊</child>
render函數是這樣的:
ƒ anonymous(
) {
with(this){return _c('div',{attrs:{"id":"app"}},_l((array),function(item){return _c('child',{attrs:{"trans_method":()=>{fn1(item)}}},[_v("點擊")])}),1)}
}
_l函數是renderList,邏輯是第二個參數(方法)調用array的元素-item,返回_c方法執行后生成的Vnode數組,可見也有閉包,只不過稍微復雜了一點點
注意:v-bind=“fn1()”而不是="fn1" 那綁定的將是fn1執行的返回值。
下面看v-on
v-on在普通節點上比如@click="fn1"方法,那么click指向的是($event)=>{fn1($event)},調用的時候傳入$event到fn1的參數中,如果綁定的是fn1(),綁定的是($event)=> {return fn1()},不傳入$event到fn1中,需要的話自己在fn1參數中寫,注意這里綁定的不是方法的返回值,而是新構造了一個匿名函數。
注意這里有閉包,所以v-on的方法,直接寫方法調用。
v-on寫在組件節點上,要加.native,因為組件是沒有on事件的,on指向的是傳遞給組件的屬性,需要加上.native告訴組件做不同處理,把on事件綁定到vmComponent掛載的節點上。