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

좋아, 내가 지시어에 (최신 뷰 버전 또는 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

그래서 뷰 ​​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'}); 
} 

장점 :

한 모든 핸들러가
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); } 
} 

편집 : 2.1에서

+ 당신은 바인딩이 내부 지침을 사용할 수 있습니다

vnode.context.$emit(eventname) 
+0

위대한 작품! 방출 함수 호출에 끝 대괄호가 없습니다. 편집을 시도했지만 SO는 6자를 편집해야한다고 말합니다. –

+0

[email protected]v2.5에서'vnode.context. $ emit()'이이 예제에서 작동하지 않습니다. 어떻게 수정합니까? 하지만 방출 기능은 여전히 ​​잘 작동합니다. –

+0

내 경험상 이벤트가 전달 된 후에 만'vnode.context. $ emit ('name')'호출 할 수 있습니다 ... element.addEvenetListener ('click',() => { ) vnode.context . $ emit ('handleClick');}); ' 작품! 하지만 일반적인'vnode.context. $ emit ('handleClick')' 을 이벤트 트리거 외부에서 실행하면 실제로 emit이 제대로 호출되지 않으므로 수신 할 수 없습니다. 나는 틀릴 수도 있지만 [email protected]에서 방금 경험 한 것입니다. – djowinz

3

솔루션을 나를 위해 일하지 않았다. 실제로 vnode.data.on 항상 이벤트를 트리거하기 위해 노력 무엇

을 정의되지 않은 한이 도움이

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

희망했다.

+4

는 나를 위해 undefined를주었습니다. '''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