2016-11-17 36 views
7
的發射事件

是否可以發出自定義事件指令該指令附加到的組件。Vue.js - 來自指令

我期待它按照例子中的描述工作,但事實並非如此。

例子:

//Basic Directive 
<script> 
    Vue.directive('foo', { 
    bind(el, binding, vnode) { 
     setTimeout(() => { 
     //vnode.context.$emit('bar'); <- this will trigger in parent 
     vnode.$emit('bar'); 
     }, 3000); 
    } 
    }); 
</script> 


//Basic Component 
<template> 
    <button v-foo @bar="change">{{label}}</button> 
</template> 
<script> 
    export default{ 
    data() { 
     return { 
     label: 'i dont work' 
     } 
    }, 
    methods: { 
     change() { 
     this.label = 'I DO WORK!'; 
     } 
    } 
    } 
</script> 

對此事的任何想法?我錯過了什麼嗎?

的jsfiddle:https://jsfiddle.net/0aum3osq/4/

更新1:

好吧,我發現,如果我在指令調用vnode.data.on.bar.fn();(或fns()在最新版本的Vue公司),它會觸發bar事件處理程序。

更新2:

臨時解決方法:

/*temp. solution*/ 
    var emit = (vnode, name, data) => { 
    var handlers = vnode.data.on; 

    if (handlers && handlers.hasOwnProperty(name)) { 
     var handler = handlers[name]; 
     var fn = handler.fns || handler.fn; 

     if (typeof fn === 'function') { 
     fn(data); 
     } 
    } 
    } 

//Basic Directive 
<script> 
    Vue.directive('foo', { 
    bind(el, binding, vnode) { 
     setTimeout(() => { 
     emit(vnode, 'bar'); 
     }, 3000); 
    } 
    }); 
</script> 

回答

12

所以我使用Vue公司2+溶液(考慮到有至今還沒有答案):

在指令添加方法:

var emit = (vnode, name, data) => { 
    var handlers = (vnode.data && vnode.data.on) || 
    (vnode.componentOptions && vnode.componentOptions.listeners); 

    if (handlers && handlers[name]) { 
    handlers[name].fns(data); 
    } 
} 

並稱它爲wa Y:

bind(el, binding, vnode) { 
    emit(vnode, 'bar' , {some: 'event', data: 'here'}); 
} 

做法的好處:

1保持相同的代碼風格的項目,這意味着每個處理器可以聲明爲
v-on:handler_name和有意義的處理(針對開發商)辦法。其他解決方案,比如將回調函數作爲參數發送,有時會讓人感到困惑,如果不深入文檔/代碼,這種解決方案並不明顯

2使用內置事件系統還可以優雅地處理事件對象。例如,該代碼將完全正常工作:

<button v-foo @bar="bar(1, $event, 2)">{{label}}</button> 
... 
methods: { 
    bar(one, event, two) { console.log(one, event, two); } 
} 

編輯:

在V2.1 +你可以用這裏面的指令綁定:

vnode.context.$emit(eventname) 
+0

很好用!您的emit函數調用缺少結束括號。我試圖編輯,但是SO說我必須編輯6個字符。 –

+0

'vnode.context。$ emit()'在[email protected]下的這個例子中不起作用,該如何解決?但排放功能仍然運作良好。 –

+0

根據我的經驗,你只能叫'vnode.context。$發出( '名稱')'後事件已派出... 'element.addEvenetListener( '點擊',()=> { vnode.context 。$ emit('handleClick');});' 工程!但是,在事件觸發器之外做一個簡單的'vnode.context。$ emit('handleClick')' 實際上並沒有調用正確的發射,因此你不能聽它。我可能是錯的,但這是我剛剛[email protected]所經歷的。 – djowinz

3

您的解決方案沒有爲我工作。事實上vnode.data.on總是不確定的

什麼工作觸發事件是

vnode.child.$emit('myevent'); 

希望這有助於。

+4

給我沒有定義; '''vnode.context。$ emit'''是Vue v.2.1.10中的一個函數,至少 – shershen

+0

好極了,現在工作正常!謝謝。 – jlccaires

+0

vnode.child。$ emit('bar'); Vue v2.4.2中未定義的$ emit。 https://jsfiddle.net/Jimsan/vuv80dpn/7/ – JimSan

0

@ euvl的解決方案很好,但我認爲只需將函數作爲參數傳遞給您的指令就更簡單,更簡單。似乎也簡化了你的指令的接口。

<script> 
    Vue.directive('foo', { 
    bind(el, binding) { 
     setTimeout(() => { 
     binding.value(); 
     }, 3000); 
    } 
    }); 
</script> 

<template> 
    <button v-foo="change">{{label}}</button> 
</template> 

<script> 
    export default{ 
    data() { 
     return { 
     label: 'i dont work' 
     } 
    }, 
    methods: { 
     change() { 
     this.label = 'I DO WORK!'; 
     } 
    } 
    } 
</script> 
+1

恐怕這不會回答這個問題。另外,例如,如果你有指令'v-draggable',並且你想要有'on-drag-start','on-drag-end','on-drag','on-drag-error 「我認爲你的方法不會那麼幹淨。雖然好電話。 – euvl

+0

@euvl我想這取決於指令(OP不是非常具體)。我想你也可以爲這個回調提供一個參數,但是你以某種方式重新構建事件,所以你的解決方案可能會更清晰。 – Husky