Multiple Vue Instances on same page using same codebase
Asked Answered
A

3

8

I'm working on bringing the functionality of Vue.js, into the WordPress ecosystem, and my first project is for Search and Filtering on a page.

Because the main website is being rendered initially by WordPress with PHP/HTML, I have Vue initializing on the page attaching to an HTML element I output using WordPress. This all works perfectly fine, but now i'm trying to take this a step further by having multiple instances of the same codebase (that can work together)

Take this example screenshot from indeed (just assume this is a WordPress site): multiple vue instances

Because the entire output is not being done in Vue.js, I have to output multiple HTML DIV elements from the WordPress side, and initialize Vue on them.

Because the form/fields will be dynamically generated based on user configuration/setup, the same code base would be used for both instances ... but i somehow need to make it so they can work together in unison, to say, update the results on the page, when a value is selected or changed, in any of the instances.

The idea here is in my main JS file using vanilla javascript to detect all of my specific HTML elements that exist on the page (maybe even define a slug for each one in a data object), and then doing a foreach loop to then init a new Vue() on each instance.

My first thought is to use Vuex storage, attaching the single storage to all instances, storing any selected values, and triggering a dispatch to update the listings when any of them change.

Has anybody done anything similar to this before? Anything I should be weary about in doing this? Or anybody have any better suggestions on how this should be done?

Figured it would be better for me to ask on here instead of learning the hard way and then finding out later that it may not be possible, or that there will be issues in doing so.

Any suggestions, comments, criticisms, or ideas are greatly appreciated

update Had one suggestion to just bind the Vue instance to the body, remove the render function, and then just output the component HTML element where needed (instead of outputting a div then attaching to it). Going to test this out, but curious on thoughts surrounding this?

Ana answered 29/8, 2019 at 17:25 Comment(1)
An event bus is the thing to be looking at here. With it, you can have multiple Vue instances (and their components inside) talking to each other. VueX can do the job as well, but many would consider it overkill since this is not an SPA.Fifth
A
9

For anybody that comes across this, I ended up just initializing the Vue instances like this:

const sections = document.getElementsByClassName( "my-wrapper" )

for ( var i = 0; i < sections.length; i ++ ) {
    new Vue( {
         el: '#' + sections[ i ].id,
         store
     })
}

Basically initializing new Vue instance on each output found on the page, passing the shared store to each one.

Ana answered 22/9, 2020 at 21:58 Comment(3)
How well did this end up working for you? (assuming your project moved forward)Suellensuelo
@robert worked great still using it today, thousands of installs and no real "major" issues that i've foundAna
Thanks. Good to hear! I've moved away from Vuex in my Vue3+ work, so I'm pondering messages between instances (like mkuehn here: forum.vuejs.org/t/…)Suellensuelo
B
3

I haven't done this multiple Vue instances setup myself, but I read at a couple places that Vue is designed to support this use-case. See for example here: Vue: is multiple Vue apps for a single website okay?

Vuex is great for a bigger SPA with multiple components and what you suggest is essentially the same thing without a shared root instance between all the components. This is where the Vuex store will be very useful by keeping every Vue component on the page synchronized with a single "source of truth" of the app's data.

I'm not sure I get that part of your question though:

My first thought is to use Vuex storage, attaching the single storage to all instances, storing any selected values, and triggering a dispatch to update the listings when any of them change.

When the data is updated in the Vuex store, if you setup Vuex properly, updates to the DOM will happen "reactively" automatically. There is no action to take other than modifying the store's data.

Regarding your update, maybe it will work, but it doesn't seem like a good idea to me. It sounds like going against the way Vue is normally used and I don't recall any part of the documentation that mentions such a setup.

Like I said, I don't have direct experience with your proposed design, so I may have missed something. Thought I'd share anyway.

Boldfaced answered 29/8, 2019 at 22:31 Comment(0)
I
0

to perform more instanze vue you have to separate the elements to which you attach vue (note the elements el ) of the following code :

<div id="app" class="container">
        <my-component 
        v-for="(item,index) in array_2_element" 
        v-bind:item="item"
        v-bind:index="index"
        v-bind:key="item.name"
        > test componente <br> <my-component>
      </div>
      <hr><br>
  </div>
</div>

  <div id="todo-list-example">
    <form v-on:submit.prevent="addNewTodo">
      <label for="new-todo"> add a todo </label>
      <input type="text" 
      v-model="newTodoText"
      id="new-todo"
      placeholder="E.g. Feed to cat "
      >
      <button type="button" class="btn btn-primary"> add</button>
    </form>
    <ul>
      <li
      is="todo-item"
      v-for="(todo,index ) in todos "
      v-bind:key="todo.id"
      v-bind:title="todo.title"
      v-on:remove="todos.splice(index,1)"
      ></li>
    </ul>
  </div>

<script> 
    var vm2= new Vue({
    el: '#todo-list-example',
    // do somethings 
});

var vm = new Vue({
    el: '#app',
    // do somethings 
})
</script>
Idioblast answered 3/2, 2022 at 14:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.