2016-11-17 18 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:

ठीक है, मैं पाया है कि अगर मैं निर्देश में (नवीनतम Vue संस्करणों में या fns()) vnode.data.on.bar.fn(); फोन यह 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); 
    } 
} 

और इसे यह वा कॉल करें 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

बढ़िया काम करता है! आपके एमिट फ़ंक्शन कॉल में एंडिंग ब्रैकेट गुम है। मैंने संपादित करने की कोशिश की, लेकिन एसओ कहता है कि मुझे 6 अक्षरों को संपादित करना होगा। –

+0

'vnode.context। $ Emit()' [email protected] के तहत इस उदाहरण में काम नहीं कर रहा है, इसे कैसे ठीक करें? लेकिन उत्सर्जन समारोह अभी भी अच्छी तरह से काम करता है। –

+0

मेरे अनुभव में आप केवल एक घटना भेज दिए जाने के बाद 'vnode.context। $ Emit (' name ')' को कॉल कर सकते हैं ... 'element.addEvenetListener ('क्लिक करें',() => { vnode.context $ emit ('हैंडलक्लिक');}); ' काम करता है! लेकिन एक सादा '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' है, और आप' ऑन-ड्रैग-स्टार्ट ',' ऑन-ड्रैग-एंड ',' ऑन-ड्रैग ',' ऑन-ड्रैग-एरर 'ईवेंट चाहते हैं 'मुझे नहीं लगता कि आपका दृष्टिकोण साफ होगा। हालांकि अच्छा कॉल। – euvl

+0

@euvl मुझे लगता है कि यह निर्देश पर थोड़ा सा निर्भर करता है (ओपी बहुत विशिष्ट नहीं था)। मुझे लगता है कि आप कॉलबैक के लिए भी एक तर्क दे सकते हैं, लेकिन फिर आप एक तरह से घटनाओं को फिर से बना रहे हैं, इसलिए आपका समाधान तब क्लीनर हो सकता है। – Husky