Vue mount multiple applications vs using Teleport in loop - vue.js

I'm writing a browser extension to add a check mark on multiple elements on the current page.
I want to build this check mark (and its own tooltip) with Vue.
Assume I have a document.querySelectorAll('selector for multiple') to attach my Vue component to it, I see two options:
Loop through the element, and for each, create a new App:
const div = document.createElement('div')
element.parentElement.insertBefore(div, element)
createApp(App).mount(div)
Mount the App once, and inside the App use Teleport to mount a component to each element:
<Teleport v-for="element in elements" :to="element">
<my-check-mark />
</Teleport>
I think the second option is better, since I'm using only one Vue engine, but Vue recommendation is to create multiple instances:
If you are using Vue to enhance server-rendered HTML and only need Vue to control specific parts of a large page, avoid mounting a single Vue application instance on the entire page. Instead, create multiple small application instances and mount them on the elements they are responsible for.
Why it is better?
Is it more efficient?

Related

Vue/Jasmine: grabbing an element without using a ref

<div :class="$style.dateOf" v-if="hasName">
test
</div>
I am trying to grab an element to test in Jasmine but each time I've done it prior, I grabbed by a ref:
await this.wrapper.setProps({ hasName: true });
await this.wrapper.vm.$nextTick();
const container = this.vm.$refs.containerMain as Vue;
I don't want to arbitrarily add refs just for testing purposes. Is there another way
to grab the element in the vm without using a ref?
Template refs are used in Vue application to restrict from uncontrolled direct access to DOM that leads to poor quality code. There's no such restriction for tests.
Vue Test utils already has everything to access DOM elements:
wrapper.find('div');
It makes sense to have element attributes that allow for unique selectors for testing purposes, conventionally data-testid.

Differences between Vue.component and new Vue?

Please tell me what are the differences between Vue.component and new Vue.
The second parameter of the Vue.component method ( the options object ), is the same first parameter of new Vue constructor. right?
Are there any differences between two methods, in meaning and parameter options?
Thanks
Let's introduce both of them first and we'll talk about the difference after it.
What is New Vue?
using new Vue we create a new vue instance; Every Vue application starts by creating a new Vue instance with the Vue function like following:
var vm = new Vue({
// you'r options here
})
According to official docs(this link):
A Vue application consists of a root Vue instance created with new Vue, optionally organized into a tree of nested, reusable components.
now that we know what vue instance is let's take a look at components.
What is Vue.component?
Components are reusable Vue instances with a name and we can use them as custom elements inside a root Vue instance
What are the differences?
Since components are reusable Vue instances, they accept the same options as new Vue, such as data, computed, watch, methods, and lifecycle hooks. The only exceptions are a few root-specific options like el.
A root Vue instance is a Vue application launcher, Vue component is an extension of the Vue instance.
Read this post for additional info.
When you call new Vue(), you're creating what is called a vue instance. A Vue instance basically is a JavaScript object that has some capabilities to interact with the DOM.
Vue components happen to be Vue instances, too. But the main difference is that components belong to other components/vue instances, while bare instances are mounted directly into an existing element of the DOM (with existing, I mean HTML that is not generated by Vue and existed previously to the instance creation).
So, basically, the main difference comes from the use: you usually create a bare Vue instance with new Vue when you need to attach that instance directly to the DOM as your root element. Vue components, on the other hand, are always attached to ** other components**.
In general, it is really common to have a single root vue instance in your Vue application, but you could have several bare instances in the same web page: you could get creative and span several Vue instances and make them interact with the DOM at the same time, as if they were components.
However, it is better to have a single root element with several components, since it is easier to reason about your code in that way, and also facilitates the use of plugins like Vuex or Vue-router.
Maybe this link about this matter can serve you as well.

Target and manipulate single DOM element in vue

Somehow I still can't wrap my head around some core vue concepts.
I have made some simple webpage using phalcon. Created it so, that it would work without JS and now is the time to add some bells and whistles - ajax queries and the like, for the user experience to be better.
I wanted to do everything using vue, to see how it all adds up. But after hours of googling I still can't find solution for the simplest of tasks.
Say: I want to get a text paragraph in a series of <li>-s and change it somewhat. Maybe make excerpt of it and add 'see more' button behind it. Now, in jQuery I would just iterate with each() and perform the tasks. With vue targeting set of DOM elements is much harder for me, probably because of whole paradigm being "the other way round".
I know I could iterate with v-for, but these elements are already in the DOM, taken from the database and templated with volt. I had even this wild idea of creating .js files from phalcon, but it would completely negate my strategy of making functional webpage first and then enhance it progressively.
Frankly speaking I feel like I'm overcomplicating for the sake of it, right now. Is vue even fit for a project like this, or is it exclusively a tool to build app from the ground up?
Vue's templating is client-side, which means if you are delivering an already templated html page (by your backend) there is little vue can still do for you. Vue needs data, not DOM elements to build its viewmodels.
This becomes pretty obvious when building a single page application for example, which would be rendered only on the client-side. You'd simply load the data asynchronously from a backend api (REST for example) and then do all the rendering on the client.
As far as I understand your usecase you want to mix client and server side rendering, rendering most of the non-interactable content using your backend's templating engine and adding some interactivity using vue. In this case you'll need to add some vue components (with their own rendering logic) to your backend template and pass data to that component using vue's data-binding.
Here's an example:
...
<div id="app">
<my-vue-list :products="{% products %}"></my-vue-list>
</div>
...
And in your JS:
var app = new Vue({
el: '#app',
data: {
components: {MyVueList} // You will have to register all the components you want to use here
}
})
Vue provides the ref attribute for registering a reference to a dom element or child component:
// accessible via this.$refs.foo
<li ref="foo">...</li>
Do note, however, that refs are not reactive, as stated in the docs:
$refs is also non-reactive, therefore you should not attempt to use it in templates for data-binding.

How to disable replacing the app root div with the component HTML while using templates

So basically, when using components - the app root passed to the Vue instance gets replaced by whatever HTML is in the component. Is there a way to disable this and just nest the stuff Vue renders inside the app root instead?
for example - if index.html has a wrapper of
<div id="myVueApp"></div>
and I set el: "#myVueApp" on the Vue instance, the whole node will get removed and replaced by whatever I have in my template resulting in
<div id="myComponent">...</div>
Is there a way to make it into
<div id="myVueApp">
<div id="myComponent">...</div>
</div>
Should work. From what I understand, you want to have multiple parts of your Vue app to be splitted up in the rendered HTML output as well, more specifically into multiple divs.
I think this should work if you use multiple Vue instances.
Set up a structure in your HTML file and give them appropriate id's.
Then, create the Vue instances you want and assign each of them to their specific div using el.
However, I can't tell you if this is a good idea and follows the best practice..
Hope this helps!

Differences between vue instance and vue component?

I'm new to vue js and have some questions when learning it.
I'm now a little confused about the relationship between its instance and component. As far as I learned, every app build by vue should only have one instance and one instance only, it can have as many components as you like if needed. But recently I've seen a demo, and in that demo it has more than one instance.
So my question is, is that ok to have multiple intances in one app( the demo code works fine, but is that the correct way)? What's the best practice to use instance and component in vue app?
It's ok to have two instances in the same project, however, you probably don't want to do that.
A good scenario is to have one main instance to control your app, specially if you are creating a Single Page Application (SPA). Then use as many components as you want.
Components are a great way to reuse code and keep it organized, and, with Vue.js, is very easy to communicate between your components and your "main" Vue instance.
It depends very much on your situation.
I work on a large web project which is not an SPA. We have a Vue instance for each "silo" of the application. We are slowly transitioning an older project from a mostly jQuery frontend so it's possible that as it evolves We'll be able to condense down to a single Vue instance but we're having no trouble with multiple instances. The ease of using Vue in existing projects was one of the biggest deciding factors in choosing it over another library such as react.
I have taken a different approach with green development, one instance and many components.
There are something in common, and some difference between Vue instance and Vue component.
From Vue docs:
all Vue components are also Vue instances, and so accept the same options object (except for a few root-specific options).
The root Vue instances accept properties like el, router, the Vue components cannot.
The data property in root Vue instances is an object, but in Vue components must be a function.
The design target is different:
A root Vue instance is a Vue application launcher, Vue component is an extension of the Vue instance.
Vue components can create elements to be reused in many places. This is Vue characteristic of componentization mainly reflect point.
Vue instance can associated with and manipulate an element which is already exist.
Vue component more suitable for create new element and reuse it at anywhere.
Think of a Vue Component as a blueprint or set of rules on how to create something that can be inserted into the DOM that the user can interact with.
So when you create a Vue file you are going to define exactly one component with a set of rules that tells Vue how to display stuff on the screen and tells a user how to interact with it.
On the other hand is a Vue instance, its an instance of a Vue component, it represents something that has been inserted into the DOM and is something that a user can interact with.
If you have a background in Object-Oriented Programming, think of a Vue Component as being like a class and a Vue instance as an instance of that class.
What has not been mentioned in previous answers that I will cover in regards to the difference between Vue instance and Vue component is how we define the data property that we are working with.
If we are working with a Vue instance, then we can define the data property as an object or a function that returns an object like so:
With a Vue Component that data property must be a function that returns an object.
So for example this is a Vue component:
export default {
name: "App",
components: {
SearchBar,
VideoList
},
And if we want to make use of data inside of that Vue component, we have to make a function that returns an object.
Vue components extends Vue instances
but Vue instances accept properties like el, router, the Vue components cannot.
best practice:
one Vue instance
many Vue component