简体   繁体   中英

VueJS XHR inside reusable component

Asking for best practice or suggestion how to do it better:

I have 1 global reusable component <MainMenu> inside that component I'm doing XHR request to get menu items.

So if I place <MainMenu> in header and footer XHR will be sent 2 times.

I can also go with props to get menu items in main parent component and pass menu items to <MainMenu> like:

<MainMenu :items="items">

Bet that means I cant quickly reuse it in another project, I will need pass props to it.

And another way is to use state, thats basically same as props.

What will be best option for such use case?

If you don't want to instantiate a new component, but have your main menu in many places you can use ref="menu" which will allow you to access it's innerHTML or outerHTML . I've created an example here to which you can refer.

<div id="app">
  <main-menu ref="menu" />
  <div v-html="menuHTML"></div>
</div>

refs aren't reactive so if you used v-html="$refs.menu.$el.outerHTML" it wouldn't work since refs are still undefined when the component is created. In order to display it properly you would have to create a property that keeps main menu's HTML and set it in mounted hook:

data() {
  return {
    menuHTML: ''
  }
},
mounted() {
  this.menuHTML = this.$refs.menu.$el.outerHTML;
}

This lets you display the menu multiple times without creating new components but it still doesn't change the fact that it's not reactive.

In the example, menu elements are kept in items array. If the objects in items array were to be changed, those changes would be reflected in the main component, but it's clones would remain unchanged. In the example I add class "red" to items after two seconds pass.

To make it work so that changes are reflected in cloned elements you need to add a watcher that observes the changes in items array and updates menuHTML when any change is noticed:

mounted() {
  this.menuHTML = this.$refs.menu.$el.outerHTML;
  this.$watch(
    () => {
        return this.$refs.menu.items
    },
    (val) => {
      this.menuHTML = this.$refs.menu.$el.outerHTML;
    }, {
    deep: true
    }
  )
}

You can also watch for changes in any data property with:

this.$refs.menu._data

With this you don't need to pass props to your main menu component nor implement any changes to it, but this solution still requires some additional logic to be implemented in it's parent component.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM