When you want to start phasing in Vue into a project, it’s tempting to not rely on custom components. Instead, you’ll likely use manually mounted Vue instances through the vm.$mount
method. However, it’s not clear how you can pass in props using this strategy. The props documentation bases all of its examples around custom components. Instead of passing in props, you can rely on the created
lifecycle hook. But that doesn’t feel as clean or communicative as using props for their intended purpose. How can you pass in a prop when you’re manually mounting a component?
Manually mounted Vue instances
Vue gives you the ability to create custom HTML components. That’s the way that the documentation suggests you use Vue. It looks like this:
You use a custom tag that Vue then mounts and renders via its DOM-manipulation capabilities. This is great on a greenfield application: it allows you to express your app in a domain-specific way. However, when you use Vue to clean up a mess of jQuery spaghetti, you likely want to keep your existing HTML as a precursor to moving to custom elements.
Manually mounting Vue instances looks like the following:
This mounts the Vue view model on some pre-existing HTML, such as the following:
The advantage of this is that you can start to remove your jQuery spaghetti without completely replacing your HTML until you’re ready.
The problem
If you’ve used a recent JavaScript library for rendering components, you’ve probably heard the term “props” bandied about. Props, which I believe is short for “properties”, are values that you pass into your component via attributes on the element. For example:
The title
and body
attributes on the <card>
element are two “static props” for the card. The card uses them as input data and can use them like any other piece of data. I’m not sure if this part is correct, but it seems like you should use props in non-parent components as data that do not change. Not necessarily immutable, but treated as if they are constants.
A first attempt
My first attempt to use props in this situation looked like this:
This solution raises the following warning and does not render anything:
This means that, when manually mounted, components don’t care about props that we set on their mounted element. What else could we try?
Getting it to work
The solution to this problem came after I read the Options / Data documentation and saw that you can pass in a propsData
attribute. Thus, if you can get the necessary data from somewhere on the page, you can inject it using propsData
. To do this, I landed on the following:
Using this pattern, the data remains where you want it, but within the element’s dataset
rather than as a direct prop. You still mount the element manually, but you inject the prop data via the propsData
option. The component renders how you want it to and you can move on with your day.
Have you run into this issue? How did you solve it?