Some kind of menu plugin as alternative to QMenu?



  • I have a fairly complex component, with several menus that might be available to privileged users, and those menus may have many options. Currently all is working with <q-menu> components, but of course that means every menu is part of the template, whether or not it is visible. Many of the items on the menu are reactive to the components current state, and we’re seeing that once there are many tens or hundreds of components (each with several menus), performance starts to degrade—I assume because those menus are being reactively updated from item data.

    Each component could share a single menu (one menu open at a time is fine), but then that menu would have to live in the parent, and so becomes decoupled from the component it’s tightly integrated with.

    Is there some kind of analogy to the Dialog plugin where a menu could be created dynamically in code, only when the user clicks an <q-btn>?



  • @dsl101 You can load components dynamically at the time when you need it. I am not sure if this would help you but have a look at “Async Components” if you haven’t yet.
    https://vueschool.io/articles/vuejs-tutorials/async-vuejs-components/

    Btw you say “Each component could share a single menu”. That doesn’t sound that bad to me. If there is a repetition going on and these menus more or less look the same only the items change within the menu that sound like good idea to me.

    You can couple them back together something like this:

    <the-component>
        <the-component-menus>
            <!-- contains all the menus this component has according to what is in the vuex state -->
            <a-component-menu for="menu in $store.state[component_name].menuitems" />
        </the-component-menus>
            
        <the-component-data>
            <!-- what ever the component displays -->
        </the-component-data>
    <the-component>
    

    I guess if I understand it correctly a similar situation could be a basic two column layout where the left side contains unique content to each page but the layout of the pages look identical.

    Let’s say I have 1000’s of pages each fitting the same layout. I wouldn’t I want to repeat the layout in all the pages just because the content inside the left side unique to that page. I use the vuex state to control what appears in the left column of the layout.





  • Yes, I’m using dynamic components in some places, but I’ve found they do need quite a bit of boilerplate to avoid premature loading, and then they need careful handling to get them to open with the data (e.g. I’m using them for seldom-used dialogs). I end up with lots of code like this:

        <component :is="editor"
          ref="edit"
          title="Edit Item"
          :item-text="item.text"
          @edit="handleEdit"
        />
    
        components: {
          EditFeedback: () => import('components/editors/EditorDialog')
        },
        methods: {
          handleOpenEditor (what) {
            this.item.text= what.text
            if (this.editor === null) {
              this.editor = 'EditFeedback'
            }
            setTimeout(() => { this.$nextTick(this.$refs.edit.show) }, 0)
          }
        }
    

    Without using both setTimeout() and $nextTick(), I find that either this.$refs.edit is undefined, or the props haven’t rippled down into the component.

    I’ve decided to refactor things into a parent component which only contains the multiple child components that used to contain menus, and instead have all the children emit an event which allows the parent to open an (already templated) menu based on the id of the child passed up in the event. I think this solves the problem without too much extra code like above.


Log in to reply