Skip to content

Conversation

@tesscat
Copy link
Collaborator

@tesscat tesscat commented Jan 19, 2026

Note that this hackpack links to other uncreated hackpacks and should be reviewed once hosting is sorted.

Copy link
Collaborator

@aak523 aak523 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really comprehensive HackPack, great job.

Just a bit more detail needed in some places (mostly towards the end).

Vue.js provides two key improvements over 'vanilla' HTML/JS:

- **Reactivity**: Vue.js automatically changes the DOM (the actual document displayed to the user) in response to JavaScript state changes, without having to explicitly dispatch updates.
- **Declarativeness**: Vue.js allows for declarative rendering and building of components — the say-what-you-want style, as opposed to the say-how-to-make-it.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might need a bit more explanation on this. Makes sense to me, but I'm not sure less experienced hackers will know the difference between declarativeness/imperativeness and why you'd prefer one over the other.


#### Lifecycle hooks

Vue.js also uses **lifecycle hooks** to manage component creation and destruction. These can be hooked into to run constructor code when your component needs to. There's a lot of them (eight in total) but it's worth being aware of their existence. Running code that depends on child components will need to be delegated to one of these, since the parent component is initialised before any child is.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could flesh this out more with some snippets (or link to one below, given you've not started writing Vue code yet). It might not be apparently obvious what the use of 'running constructor code' actually is for a complete Vue beginner.

While Vue.js was originally designed around incremental adoption, it's very common to build complete applications in it, which is what we'll be doing here. A number of tools exist to streamline this process — not least the various npm scripts. After you've [installed NodeJS and NPM](/getting-started/README.md#javascript--typescript), running `npm create vue@latest` will create a blank Vue.js app we can use as a template to build upon.

You'll want to [enable TypeScript](TYPESCRIPT HACKPACK HERE), the *Router* (we'll go into this later!), and optionally *ESLint* and *Prettier*. The name doesn't matter yet as we'll just be looking at the example here before starting from scratch properly, so keep the example code, since we want to observe the resultant directory structure:

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to link to the actual example project repository here to encourage people to check out the code directly? You could also link to the files/directories you've listed below.


While Vue.js was originally designed around incremental adoption, it's very common to build complete applications in it, which is what we'll be doing here. A number of tools exist to streamline this process — not least the various npm scripts. After you've [installed NodeJS and NPM](/getting-started/README.md#javascript--typescript), running `npm create vue@latest` will create a blank Vue.js app we can use as a template to build upon.

You'll want to [enable TypeScript](TYPESCRIPT HACKPACK HERE), the *Router* (we'll go into this later!), and optionally *ESLint* and *Prettier*. The name doesn't matter yet as we'll just be looking at the example here before starting from scratch properly, so keep the example code, since we want to observe the resultant directory structure:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where exactly are you prompted for the name / how do you ignore it?

import Counter from './components/Counter.vue';
```

We should also tell Vue that we're using the Counter component in our App component. Via the Options API, we export it as part of the exported object (note the script is not marked setup!):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not too obvious already, I might also specify that we're still in App.vue. When I saw 'via the Options API', part of me thought that meant I should navigate to a different file.


The object returned from `data()` is merged with the component, so we can now access `this.count`. Importantly, updating this from the code-side will dynamically update any DOM elements that use the data.

Vue's reactive state uses reactive proxies under-the-hood. The only important thing to keep in mind is non-reactive things do not become reactive when copied. In the following case:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are reactive proxies?

Also might be good to clarify what the difference between reactive and non-reactive things is in practice / for the user.


`newObject` does not become reactive, and while updating `newObject` will update `someData`, it won't trigger components that depend upon `someData` to re-compute their state. Always use `this` to update reactive state.

To have a DOM element that does this, we can use template syntax - Vue.js uses a Handlebars style. Writing double-braces in the HTML results in the contained TypeScript code being executed, and the result spliced into the DOM where the braces were.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hackers might not necessarily be familiar with template syntax, the example below is good but you might benefit from a one-sentence explainer before you introduce it.


#### Lifecycle hooks and raw HTML

This section is more of an explainer
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO()?

> [!WARNING]
> `v-on` will only catch custom events in a custom component, not a regular HTML element.

We can emit events using `this.$emit(event_name, event_data)`. The `event_data` parameter is optional. In the `<template>` body, you can use just `$emit(...)` since `this` is implied there.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does it mean to emit an event?

</template>
```

Again, there's not much new here, just Router components. Using `<RouterView to...>` instead of `<a href...>` enables the router to switch components fluidly, enabling the SPA feel and preventing page loads.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is SPA feel?

@tesscat tesscat requested a review from aak523 January 25, 2026 20:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants