Basics: Component building in Meteor + VueJS

It’s the same way you would use React. You only manually “render” a single component that renders your <App /> or something similar, and it will handle all of its children, and they handle all of their children, etc.

So when you do this

// App.vue
<template>
   <h1>Hello!</h1>
   <my-component />
</template>

<script>
import MyComponent from `./components/my-component.vue`

export default {
   components: {
      MyComponent
   }
}

</script>

Vue will make a new instance of MyComponent and render it without you needing to call any constructor. Vue and React both take the component-driven approach where your whole app is mounted on a single top-most component, then that component will render children. So you’d have something like this where the <app> component renders your whole app by having everything as a child of it

<app>
   <header>
       <navigation />
   </header>
   <content>
      ...
   <content/>
   <footer/>
</app>
2 Likes

Everyone, I need help building a guiding philosophy when it comes to Vue components (as I’m using them as the building blocks of my new application). This is what seems best so far (please help me flush this out):

Multiple simple components are better than one highly customizable ones?

It seems easy to get into a habit of building a few really generic components that can be used in lots of places. But I think Components should be dumb, only relying on their props.

Yet I keep running into the situation where I need to show/hide or disable/enable a component based on the state of other components. Should inject the smarts into the component via props, allowing it to respond to events from other sibling components or should the parent component become an orchestrator, taking in events from child components and emitting events based on knowledge from all child components?

  1. Sibling components injected via props with smarts to react to situations (smarter components)

  1. Sibling components injected with only the basics, needing the parent to react to events and then determine its state (dumb component) at the base levels

You have a third option. The parent component doesn’t react to events of child components. The events of child components are passed to Vuex (or just a simple store object) and it changes the state which is then passed to the parent, which now knows which children to show, without having to deal with children’s events at all and without the children having additional “should i even exist” functionality.

I agree with @gusto, after working with some larger React+Redux and Vue+Vuex apps for awhile I’ll never go back to not putting all UI state in a global store. By “UI state”, I mean any variable that changes something visible on screen.

Once you’ve got 50+ UI elements that all change visibility, being collapsed, enabled/disabled, etc. depending on certain state values, if you don’t follow a strict paradigm like Vuex it becomes a game of hunting down where that particular isSomethingVisible variable was defined and where it was changed. Was it in a parent component? Maybe a child emitted an event and another component listened to it? Maybe a resource hit an API and finally got a response a second later and then changed the variable?

If you use Vuex or Redux, every single change to the UI state always goes through action -> mutation -> store -> component, and you know instantly that isSomethingVisible variable you were looking fo` is only ever changed in your entire codebase in one place, making everything way more predictable and bugs insanely easier to find. Plus you get the benefits of tooling like the Vue chrome developer tools, with time-travel debugging.

2 Likes

Thank you @efrancis & gusto!

I just thought I’d look at non-vuex solutions since when I asked about it the other day on here I got a little pushback (saying it was overkill).

I think I’ll now invest in learning vuex – any resources that help learning vuex are appreciated.

(saying it was overkill).

I don’t adhere to the mindset that you should start with a simple codebase and add more complexity as time goes on. That just means you’re constantly refactoring as you grow. I like to just pick the pattern that will be scaleable for development regardless of codebase size or team size. It’s a little bit more effort initially and a lot of time saved later on IMO. To each their own of course.

The best docs and guides for Vuex are the official docs, a little dense but if you take the time to read through all of it and understand it you’ll be in great shape.

3 Likes

@efrancis do you always use action -> mutation for each state property, with dispatch instead of commit? At the moment, I’m doing it only if I plan to pass different value to mutation that was passed from the component. What disadvantages of that would you find?

I prefer to just always use an action. You can commit directly as long as you’re not doing anything async, but I find the uniformity of always using actions better when I’m trying to fix bugs because I know state changes are always initiated from actions, instead of looking into a component first to check if it used dispatch or commit. It is a little more boilerplate sometimes, but on larger codebases that uniformity brings a level of predictability that makes maintaining things easier when you didn’t write something or when you haven’t touched some part of code in awhile. I think the strict structure of Vuex is it’s biggest selling point, everything becomes more predictable.

1 Like

I think I’ll now invest in learning vuex – any resources that help learning vuex are appreciated.

I have purchased and went through the whole course in Udemy:

Max is really good at explaining stuff. He basically will tell you all the things you can find on the guide, but I also like to videos besides reading. Vuex is explained in there as well.

These I haven’t watched, but maybe are not as in-depth as the ones he sells:

2 Likes

That’s funny you suggest that, I just paid for this learning course the other day after I noticed how well he explained Vue concepts!

I haven’t gotten to Vuex yet, but will report back here after I’m done :slight_smile:

1 Like

Hi everyone, I need help… been pulling my hair out with an error I’m getting… I’ve setup Meteor + Vue + Vuex + VueRouter…

The Meteor build goes fine, but loading in the browser I keep getting this error:
Uncaught Error: Cannot find module ‘babel-runtime/helpers/extends’

The thing is, everything was working fine until I couldn’t take the Meteor build times anymore and started
playing around with file locations and removing packages to try and get client file to reload faster…

I’m probably missing something trivial, but I’ve been at it for 2 days! If anyone can help me debug this
issue I’ll totally appreciate it… thank u :slight_smile:

(yeah, body is too similar to something that i’ve posted and deleted)

Fine, but… there’s nothing to debug. What’s your package list, what versions, what’s your configuration?

Also, why do you want to make client file to reload faster, does hot module reload not work for you by default?

There are two separate issues here. First is the error message, second are the slow build times on the client.

For the first one, start with deleting the whole node_modules folder and do meteor npm install again.

For the second one, the reason may be mixing Vue and Blaze templates in the same project, as I assume hot module reload will only work for Vue templates. Are Blaze templates absolutely necessary for your project?

@gusto You’re right, two issues. I’d love to know how you’re getting HMR and fix the build times but of course first I need to get the project working again… I left in the Blaze templates just for the easy drop-in of the accounts package, if that’s the stopper for hot reloads I can remove it and make the login forms with Vue.

Regarding the error message, I’ve tried deleteing and installing node_modules… I’ve tried creating a completely new meteor project from scratch, reinstalling all npm/meteor packages and copying the needed files over… still same error, tried switching around file locations, my guess was the error had something to do with how .vue files are resolved, because for example module.resolve of account related files and others load up babel-runtime/helpers/*.js (many files in that location) with no problem…

thx for the help.

I’m not 100% sure to be honest. Thinking of it, imho that would be a stopper, but I never mixed Vue with Blaze so I can’t guarantee it. Hot module reload works out of the box with new Vue+Meteor project. Whenever I save the changes in the client files, I instantly see the updates in the browser, even with a bigger project.

What version of meteor is that? 1.4.2.3?

While I can’t help more, I hope you resolve that.

It works with just akryum:vue and akryum:vue-component. It also works with your configuration, with vue-meteor-tracker from npm instead of akryum:vue, I checked it.

Yes, I’m using Vuex and Vue-router from npm and it works without any issues.

It will be difficult to use Blaze and Vue in the same project. Specially if you use nested route or parameters on the route. It’s recommended to use vue-router, and this router will have issues with Blaze in this way.

It’s best to start green field with meteor + vue and you can get started by using this install instructions: Basics: Setting up a Meteor + VueJS project. If you have to mix, you should wait for this initiative to take off: Vue as the base of Blaze 2.0.

I have a sister application that is all Blaze and uses Accounts. This new system will be only Meteor + VueJS. They’ll both use the same MongoDB. I’ll need to tie the VueJS system into the Accounts system, which will require custom calls to Accounts, and of course we’ll need to add custom forms for login.

In another VueJS thread there is a reference to using Accounts with VueJS I think (can’t find the link ATM). But we should collaborate on this effort to help one another and others that come behind us – we’re trail “blazing” here. :slight_smile: Once I get to it, I’ll post a repo of what I’m working on in this area if there’s not already something out there.

I don’t think it conflicts with the HMR system.

Please could you post the full error trace? And maybe if you could publish your code on GitHub or somewhere else for us to check (if possible)?

Hi akryum, I’ve tried to start with a clean project to reproduce the initial error I was getting,
but now I fell even deeper into the erroRabbit hole… getting a strange issue with rendering
.vue components, where the style tags are exported instead of the template??

I created a simple gitrep, hopefully you can see the issue also:

thanks for your help.

I don’t get any <style> related error. I do get errors in App because of you using multiple root elements in the template and some router related error, but nothing about CSS.

What’s more, the CSS is working properly, the background has the color it should.