I spent a few days on and off learning parts of Vue to write a small app. I wrote the same app with Angular. I'm sharing my experience of working through Vue for the first time to help others that may be curious about the JavaScript framework landscape.
This post explores the code for both the Angular and Vue apps. Spoiler: you'll find that the code and concepts are very similar. :) I had a lot of fun working through Vue with Sarah Drasner. Pair programming or simply just talking to friends about code is a great way to learn and share ideas.
We all benefit when we learn to enjoy and embrace the similarities and the differences that help push the Web forward.
Both apps are very small. Both apps are not indicative of how we may refactor to expand to build a large scale app. In fact, the tldr; is that both apps in Angular and Vue have a lot in common.
Here are the posts in this series, if you want to catch up or jump around:
- Post 1 - File Structure
- Post 2 - Learning Materials
- Post 3 - Familiar Code
- Post 4 - Vue with TypeScript
index.html
Let's begin with the file that starts it all: index.html
. Notice that both of these are very similar and very short. Each uses WebPack for a build process and thus defers to WebPack to crank things up.
On the left, Angular adds a few extra things. Here we see a <base>
tag which is useful once we add routing. We haven't added routing yet, so the <base>
tag is uncesessary at this moment. Angular also adds the viewport and a favicon. None of this is a big deal.
The <body>
is where we find Angular hosting the root component app-root
and Vue hosting a <div>
where the root component will be associated. Again, fairly similar.
The Vue code adds in a build.js
script, and at first glance, it seems the Angular one does not. Angular adds the startup scripts in the built version of the app. In other words, when we build the Angular app, the index.html
will contain these scripts too.
Thus the index.html
files are fairly similar, and it's kinda cool how small they are.
main.js
Both apps kick their code off from a main.js
file. Wait, the Angular app uses TypeScript, so isn't it a main.ts
file? Yeah - but - TypeScript compiles to JavaScript, and it becomes - you guessed it - main.js
.
Both apps import from their frameworks, respectively. Both apps then import the root file for their frameworks. Angular imports the AppModule
while Vue imports the root App
component. Angular then has a quick check to disable some features when it is running a production build vs. a development build which is helpful for turning off debug capabilities.
The syntax to kick things off and launch the starting root component then follows. Angular bootstraps the AppModule
while Vue associates the App
component with the HTML element with the id app
that we saw in index.html
.
Notice that the Vue app also declares the component
App
. We'll come back to this in the next section.
Different syntax, different frameworks, but again, pretty simple stuff to kick things off from both.
app.module
This is one of the more apparent differences between Angular and Vue: Angular apps contain a manifest of the leading players in an app while Vue doesn't have this concept. The file app.module.ts
contains AppModule
which defines a class decorated with the @NgModule()
decorator.
In this Angular app, the app.module.ts
file declares the components used by the app, imports Angular features (e.g., browser, forms, and HTTP), declares the services and defines which component should kick things off. Remember I mentioned how the Vue app declared one of its components in the main.js
? It's not the same exact thing, but we can see here that the Angular app has a similar declaration. Except with Angular, the file app,module.ts
declares all of the components in this small app.
The Vue app kicks off the root component App
in it's main.js
, while the Angular app kicks off its root component AppComponent
in app.module
. Different patterns, but very once again, easily digestible patterns to follow in both cases.
App Component
Each app has a root component. The Angular one uses a convention to name its components with a suffix of Component
. So Angular has AppComponent
while Vue has App
. Both have similar templates. Vue's App
component has an id
in the div and both frameworks list their child components' selectors differently with app-hero-list
and HeroList
, for Angular and Vue respectively. Both apps also contain some root styling.
The Angular app has a small class with one model property for title
. The Vue component defines one model property for title
, too. The Vue App
component declares it's child component, HeroList
here, directly in the component that uses it. The Angular app declares these back in the manifest in the app.module.ts
file.
One difference that stands out is that the Angular app uses a *.ts
file while Vue uses a *.vue
file. As long as the editor and tooling know how to display them, let us edit them, give us tooling, and build them, I don't think it matters much what the extension is.
Once again, we see how easy it is to observe the similarities.
Hero List Component
Each app has a component for displaying the heroes to the user, from where they can select a hero to see his/her details. Both are using inline templates, which define the HTML for the compoennts.
The Angular component, hero-list.component.ts
, imports from its framework, then it imports a model for the Hero
class, then imports a HeroService
. The Vue app imports a hero service (down on line 31) and then it imports its child component, from HeroDetail.vue
. They both import a service, but the other files differ. These are minor differences, though.
Angular already declared its HeroDetailComponent
component in app.module
. The Angular app uses a declared Hero
model class. The Vue app could certainly use a model, but there was no need to do so here.
Here comes the coolest part of the similarities: the templates are extremely similar to each other. Take a moment to look at the HTML templates side by side. They both have the same number of lines and very similar syntax. The Angular app defines the template in a string while the Vue app establishes the template inside of a <template>
tag.
The binding syntax is quite interesting too. We'll explore the syntax for template bindings in more the next post in this series.
The bindings for Angular and Vue are indeed interesting. In Angular, we have a (click)
binding syntax while in Vue we use @click
. Here are some other similarities in the bindings, in the following table.
binding | Angular | Vue |
---|---|---|
click event | (click) | @click |
enter key-up event | (keyup.enter) | @keyup.enter |
add/remove content | *ngIf | v-if |
model binding | [(ngModel)] | v-model |
HTML element reference | # | ref |
Wait! What about the code? Once again, very very similar code.
The Angular app defines a TypeScript class with properties that define the hero list's model. The Vue app establishes the model in a data
property. These are the same three model properties.
The Angular app uses dependency injection to get a reference to the hero service, while the Vue app imports its similar service. Different styles, but it is easy for us to make the transition in either direction here.
Both apps have the same set of methods. Angular uses RxJS by convention to communicate with HTTP while Vue uses Axios with promises by convention. That's why we see subscribe
for Angular and then
for Vue in the calls to the service, for the asynchronous operations. These are just different techniques, and the code is very similar in this side by side example.
Both of these components also have scoped styling using SASS. Scope styling is kinda cool since the styles will only apply to the components. This makes it easy to identify which styles will apply to the component and perhaps, more importantly, this makes it easy to ensure that styles only apply where we intend.
Hero Detail Component
Both hero detail components are also very similar. The Angular file hero-detail.component.ts
starts by importing the features (referencing them). Then they both define their respective templates. Angular tends to explicitly define the features they use, which is why we see more imports at the top of the file.
The templates are similar other than binding syntax, just like the hero list components' templates.
The code for these components is quite interesting. The Angular HeroDetailComponent
uses the @Input()
decorator to identify that the hero
model property can be passed in (via a binding) from the parent component. The Vue HeroDetail
component uses the props
property to identify its hero
model property can be passed in from its parent component. We get the same result, with different techniques.
Each component defines two model properties for addingHero
and editingHero
. Angular does this with class properties while Vue does it as members of the data
property.
Both apps set focus to elements once they are rendered and ready on the Web page. However, the way they get to those elements is interesting. The Angular app grabs references to the two elements using the @ViewChild()
decorators while the Vue app uses an inline reference in the template combined with this.$refs
in its code to reference its elements. The Angular the app handles the focus in the life cycle event ngAfterViewInit
while the Vue app is handling setting the focus in the mounted
event.
Take a close look at the @Output()
decorators in the Angular app and we'll see that these help us emit events from the HeroDetailComponent
to its parent component. Notice that for Angular, the event emits on line 64 in the clear
method. The Vue app also emits events. Vue uses the this.$emit
function to do the same thing (see line 56 in Vue's HeroDetail
component). Obviously Angular and Vue have different syntax for some things.
In and Out of Components | Angular | Vue |
---|---|---|
input property | @Input() | props |
emit an event | @Output() with EventEmitter | this.$emit |
Overall, the components are once again very similar and it is easy to see how once you know one of these frameworks, it can be easy to use the other.
Summary
Where does this leave us? Good question. The takeaway for me is that I found it quite easy to straddle the line between Vue and Angular. I can take an Angular app and see fairly quickly how to translate the way I do things in Angular and how Vue might do them.
The intent here is to show two interesting ways to solve a problem - to build apps for the modern web. Both Angular and Vue share some interesting concepts. Both are paying close attention to how the Web is evolving, and they are evolving with it.
We all benefit when there are multiple great options, especially when we look at them in a friendly, welcoming, and open-minded way. Both Angular and Vue are popular (along with some others like React). All of these are great solutions.
I'll repeat this because it's important ...
We all benefit when we learn to enjoy and embrace the similarities and the differences that help push the Web forward.
Source Code
You can find the source code for these apps here:
- Angular app - in the
vue-similar
branch - Vue app - in the
connect2017
branch