2017-12-31 72 views
1

私のシナリオでは、条件付きでバインドしたいmouseoverイベントとmouseoutイベントを持っています(たとえば、ユーザーがマウスを持つデバイスにいる場合のみ)。条件付きイベントバインディング - vuejs

私はイベントハンドラ自体で条件を持つことができますが、それでも不要なイベントハンドラのメモリを割り当てていることがわかります。

イベントバインディング自体を作成する方法はありますか条件付き?

(私が欲しいものを、明確にする条件がfalseの場合、短絡イベントサブスクリプションのことができるようにすることですので、根本的にaddEventListener操作が起こることはありません)

+2

あなたは 'V-IF hasMouse'を使用して、イベントやなしに他との一方の枝を持っている可能性が...あなたの ユースケースごとに評価します。おそらく[scoped slots](https://vuejs.org/v2/guide/components.html#Scoped-Slots)を使用して共通コードを挿入します。 –

+0

非常に単純なコンポーネントであれば問題ありませんが、テンプレートが充実している場合(私はこの場合複雑なSVGで作業しています)、痛みになります – asi

+0

計算されたプロパティはすばらしい答えに見えます。あなたがそれを打ち込み、受け入れられた答えとしてマークしたくない理由はありますか? –

答えて

1

あなたはそのような何かをしたい場合

マークアップ

を:あなただけの条件が満たされた場合 mountedフックでイベントリスナーをバインドすることを利用して、その後、 elementあなたがイベントを適用する上で refを追加することによって、手動でイベントリスナーを適用することができ
<button ref="button"> 
    Mouse Over Me 
</button> 

Vueのインスタンス

new Vue({ 
    el: '#app', 
    mounted() { 
    let hasMouse = true; 

    // If the user has a mouse, add the event listeners 
    if (hasMouse) { 
     let button = this.$refs.button 

     button.addEventListener('mouseover', e => { 
     this.mouseover = true 
     }) 

     button.addEventListener('mouseout', e => { 
     this.mouseover = false 
     }) 
    } 

    }, 
    data: { 
    mouseover: false 
    } 
}) 

ここでは、そのためにJSFiddleです:https://jsfiddle.net/0fderek6/

あなたはそのアプローチが気に入らない場合、あなたはまたdirectiveを使用して、そこに条件を置くことができ、あなたは可能性がありそれをmixinに入れて再利用できるようにします。

ミックスイン

<button v-mouse-events> 
    Mouse Over Me 
</button> 
const mouseEvents = { 
    directives: { 
    mouseEvents: { 
     bind(el, binding, vnode) { 
     let hasMouse = true; 

     if (hasMouse) { 
      el.addEventListener('mouseover', e => { 
      vnode.context.mouseover = true 
      }) 

      el.addEventListener('mouseout', e => { 
      vnode.context.mouseover = false 
      }) 
     } 
     } 
    } 
    }, 
    data: { 
    mouseover: false 
    } 
} 

Vueのインスタンス

new Vue({ 
    el: '#app', 
    mixins: [mouseEvents] 
}) 

マークアップは、ここではそのためJSFiddleです:https://jsfiddle.net/nq6x5qeq/

EDIT

あなたがdirectiveアプローチが好きなら、あなたがする必要があるすべてのリスナーを削除するunbindフックを追加している、あなたはその後、binding argは、イベント型で持つことができるとbinding valueハンドラなる:

Vue.directive('mouse', { 
    bind(el, binding) { 
     if (hasMouse) { 
     console.log(binding.arg + ' added') 
      // bind the event listener to the element 
     el.addEventListener(binding.arg, binding.value) 
     } 
    }, 
    unbind(el, binding) { 
     if (hasMouse) { 
     console.log(binding.arg + ' removed') 
     el.removeEventListener(binding.arg, binding.value) 
     } 
    } 
}); 

は、今あなたがする必要があるすべてはv-bindと正確にご希望の各リスナーを追加している:ここではそれがどのように動作するかをお見せするためにJSFiddleだ

<div v-mouse:mouseover="mouseOverFunction"></div> 

https://jsfiddle.net/59ym6hdb/

+0

これには1つの欠点があります: 'beforeDestroy'ライフサイクルイベントで完全な' removeEventListener'を実行しません。多くのアンマウント - >マウントでは、条件をイベント自体に移動するよりもパフォーマンスが劣りますが、イベントリスナーを削除しなくても追加できます! –

+0

@AndreiGlingeanu私はこれを両方とも複雑にしていると思います。ディレクティブでリスナーをアンバインドする必要があります(ディレクティブフック間で状態を共有することを意味します)。レンダリング関数は実際にはメンテナンスできません。私は実際にははるかに簡単な@RoyJによって提供されるソリューションに行くだろう。 –

+0

真。しかし、時には、同じノード上で条件付きでイベントを本当にスキップする必要があります。これは、単純なドラッグアンドドロップを実装する多くのマウス*リスナーのように、単一のDOMノードに多くのロジックをアタッチした場合に発生し、クリックイベントをスキップするだけで済みます。もちろん、私たちはそれについて永遠に議論することができます。私はより単純でより低レベルの代替ソリューションを提供しました。 –

2

さらに簡単にレンダー機能を使用することもできます。リスナーを手動で削除して世話をする必要はありません。また、ミックスインなしでシンプルなJS構文を使用します。

new Vue({ 
    el: "#app", 
    data:() => ({ 
    counter: 0 
    }), 
    methods: { 
    handleClick() { 
     this.counter++; 
    } 
    }, 
    render(h) { 
    return h(
     "div", 
     IS_MOBILE_DEVICE 
     ? {} 
     : { 
      on: { click: this.handleClick } 
      }, 
     this.counter 
    ); 
    } 
}); 

全例:これを達成するための最良の方法は、あなたがに加入することに興味があるイベントを含む仕様オブジェクトにV-に結合し、同様にそこにあなたの条件文を配置することです表示されますthis discussionhttps://codesandbox.io/s/nw6vyo6knj

+0

レンダリング関数は非常に単純なコンポーネントではうまくいくが、いくつかの場合(私は複雑なSVGで作業している)、扱いにくい – asi

0

そう:

<div v-on="{ mouseover: condition ? handler : null, click: ... }">

いくつかの注意:

  • ハンドラのヌルを渡すと、基礎となるaddEventLisetenerないが起こることを意味します - 私たちは何をしたい
  • である。これは、別にそれを分割ではなく、その後つのV-上 属性にすべてのイベントサブスクリプションをグループ化し、意味明示的な バインディング(<div @mouseover='...' @click='...'/>

  • これは長い生き成分であり、基になるデータは、(再バインドにつながる)頻繁に を変更する場合は、注意を払うべきである 1回のバインドパスで行われたサブスクリプションとしてのサブスクリプション(つまり、対応するremoveEventListener)の廃棄には、後のサブスクリプションには廃棄されません。