防止在由mixin

时间:2019-08-12 09:29:11

标签: javascript typescript vue.js dom

最小的,可复制的示例

bug或是故意的?

如果您要渲染到一个组件中,以便两个组件共享一个Element,似乎会导致一个$el上的全局混合装入增加一倍。

Vue.mixin({
  mounted: function() {
    //debugger;
    this.$el.addEventListener("contextmenu", (w) => {
        console.log("contextmenu")
        w.stopPropagation();
        w.preventDefault();
    })
  }
});

Vue.component("App", {
  render(h) {
    return h("div", {
      style: "height: 100vh;width: 100vw;background: gray"
    });
  }
});

new Vue({
  render: h => h("App")
}).$mount("#el");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="el"></div>

心态

目前,我正在构建一个vue-electron插件,以通过使用装饰器来简化上下文菜单:

@MenuItems.Copy
@Component<myComponent>({})
class myComponent extends Vue{}

很好,一切正常。

某些组件除外。

这些人在上触发了两次

我插入钩子的部分:

import Vue, { VueConstructor } from 'vue';
import { remote } from 'electron';
const { Menu } = remote

export default function applyMixin(_Vue: VueConstructor){

    _Vue.mixin({
        beforeCreate: contextMenuInit,
        mounted: popup
    })

    function popup(this: Vue){

        const onContextmenu = ((e: Event) => {
            const menu = new Menu();
            for(let menuItem of this.$contextMenuItems){
                menu.append(menuItem)
            }
            menu.popup()
            e.preventDefault()
            e.stopPropagation()
        }).bind(this)
        // <injection of events>        
        this.$el.addEventListener('contextmenu', onContextmenu, false)
        this.$once('hook:beforeDestroy', () => {
            this.$el.removeEventListener('contextmenu', onContextmenu, false)
        })
        // </injection of events> 
    }

    function contextMenuInit(this: Vue){

        const options = this.$options 
        if(options.contextMenuItems){
            this.$contextMenuItems = options.contextMenuItems;
        } else if(options.parent && options.parent.$contextMenuItems){
            this.$contextMenuItems = options.parent.$contextMenuItems.slice()
        }
    }
}

1 个答案:

答案 0 :(得分:0)

FIX:

问题出在父级上-子级都调用已注册的钩子,并且当它们共享$el时,不需要一个孩子就可以从钩子中返回

if(this.parent && this.parent.$el === this.$el) return;

function ev(w){
    console.log("contextmenu")
    w.stopPropagation();
    w.preventDefault();
}
Vue.mixin({
  mounted: function() {
    //debugger;
    if(this.parent && this.parent.$el === this.$el) return;
    
    this.$el.addEventListener("contextmenu", ev)
    this.$once('hook:beforeDestroy', () => {
      this.$el.removeEventListener("contextmenu", ev)
    })
  }
});

Vue.component("App", {
  render(h) {
    return h("div", {
      style: "height: 100vh;width: 100vw;background: gray"
    });
  }
});

new Vue({
  render: h => h("App")
}).$mount("#el");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="el"></div>