Skip to content

Tutorial 05 - Vue.js 4 #60

Description

@braughtg

Tutorial 05 - Vue.js 4

In this tutorial you will learn about Vue Single File Components and how they allow you to encapsulate and reuse user interface elements across your applications.

Getting Started

You will start and work on this tutorial in the same way as you have for the previous tutorials. You should be starting to internalize this process making you less reliant on reading the detailed instructions each time.

Tasks

  1. If you don't remember all of the steps for getting started and working on the extension tasks, you should review the relevant parts of the workflow using the links in the "QuickReference" document as necessary.
  2. Open Susan Buck's Vue.js Simplified Course.

Self Check

  1. Which steps do you still need to look up?
  2. What can you do to commit more of those steps to memory?

Single File Components

Vue Single File Components (SFCs) are one Vue mechanism that allows you decompose your application down into smaller reusable parts that are easier to build and test.

Tasks

  1. Watch and follow along with the "Single File Components" video (19:19).
    • Note: As you follow along with Susan's changes, some of the code she uses will be flagged by the linters in our project. This code will be underlined with squiggles indicating potential issues. Susan's code will work just fine. However, when you try to commit the changes the pre-commit hook will prevent the commit due to the linting issues. Ignore these issues for now. We will fix the linting errors in later sections of this tutorial and you will be able to commit your changes once they are fixed.

Self Check

  1. What are the advantages of using components in designing software?
  2. What naming conventions are used when creating a Vue single file component?What filename extension is used for Vue single file components?
  3. There is a lot of new vocabulary associated with Vue single file components (SFCs).
    • Where is the scoped attribute used and what does it mean?
    • What are props? What are they analogous to in other programming languages such as Python or Java? What is the syntax for adding a prop to a SFC?
    • What are events? What are they analogous to in other programming languages? What is the syntax for emitting an event from a SFC?
  4. Where do you need to use this in a SFC?
  5. How do props and events work together to allow a parent component (e.g., App.vue) and a child component (e.g., WordCard) to communicate with each other?
  6. In App.vue is it necessary for the event name incrementCorrectCount and the method that handles the event incrementCorrectCount to have the same name?

The Linting Issues

As mentioned above there are a number of issues that the linters for our project have found in Susan's code that will prevent you from committing your work. This doesn't mean that Susan's code doesn't work correctly, as you saw it does. However, fixing the issues that the linters have flagged will give us an implementation that follows code style and software design guidelines a little better.

You can see each of the linting issues:

  • in the code editor where they are underlined with squiggly lines (orange for warnings, red for errors). Point at the code with the squiggly underline to see a popup with the description of the issue.
    Popup showing the description of the linting issue.
  • in the "Problems" panel at the bottom of the window or in the output of the pre-commit hook, both of which give the description of the issue and file and line number where the issue exists.
    Problems panel showing the linting messages.

The following sub-sections each explain one of the linting issues that are flagged and walks you through the fix. Clicking a linting message in the "Problems" tab will take you directly to the code where the problem exists.

Prop "word" should define at least its type

When declaring a prop for a Vue Single File Component (SFC) you should also specify the type of value that should be passed to the prop and whether the prop is required or not. This helps to document your component, making it easier for other developers to use it. Doing so can also help with debugging by making it possible for Vue to check that the values passed to the prop are of the correct type as the program runs and display useful error messages if they are not. The Vue documentation lists the types that can be used for props.

Tasks

  1. Open the "Problems" tab.
  2. Click the message "Prop "word" should define at least its type." in the Problems tab.
  3. Point at the underlined text (word) or right click the issue in the "Problems" tab.
  4. Choose the "Fix" option to ask Copilot to suggest a fix.
  5. Copilot will suggest the following syntax for declaring the type and required state of the word prop.
    . Copilot's suggestion that declares the type of the prop and that it is required. .
  6. Click "Keep" to accept the suggestion.
  7. Notice that the linting issue has been resolved.

Self Check

  1. Why did Copilot suggest the type Object for the word prop? Hint: Look at the words array in the Vue data property in App.vue.
  2. What is the syntax for declaring the type of a prop in an SFC?

The "incrementCorrectCount" event has been triggered but not declared...

Similar to declaring the types for the props in a Vue SFC, you should also declare each of the events that are emitted by a SFC.

Tasks

  1. Click the message "The "incrementCorrectCount" event has been triggered but not declared..." message in the "Problems" tab.
  2. Point at the underlined text (word) and choose the "Quick fix..." option (The quick fix option.) or right click the issue in the "Problems" tab to generate some IntelliSense options.
  3. Choose "Add the emits option with the array syntax ..." from the dropdown menu.
  4. Notice the new emits option that was added just above the methods section that now declares that the WordCard SFC emits an incrementCorrectCount event.

Self Check

  1. What is the difference between a "Quick fix" and a "Fix"?
  2. What property is used to declare the events that are emitted by a SFC?

Unexpected mutation of "word" prop

As a general rule a SFC should not make changes to any of the props that are passed to it. Michael Thiessen has a good article that goes into depth on why you should Avoid Mutating a Prop Directly if you are interested. The short reason is that doing so can make your application behave incorrectly and violates good design principles such as separation of concerns, abstraction, and encapsulation resulting in code that difficult to debug and maintain.

If we look at the code for WordCard we can see that it modifies attributes in the word prop in two places:

  • In the checkAnswer method it assigns a new value to this.word.correct:
    checkAnswer() {
      this.word.correct = this.word.word_b == this.word.answer;
      ...
    },
  • In the template it binds this.word.answer (via v-model) to the value in the text input:
    <input
      type="text"
      v-if="!word.correct"
      v-model="word.answer"
      v-on:keyup.enter="checkAnswer()"
    />

The way to fix each of these issues is to create local data properties within the SFC for correct and answer, and then to use those data properties instead of those in the word prop. The tasks below will guide you through these changes.

Tasks

  1. Add the Vue data property shown below to WordCard between the emits property and the methods property. This creates data properties for correct and answer inside of the SFC (similar to fields or attributes in a class in an object oriented language).
    data() {
      return {
        correct: false,
        answer: '',
      };
    },
  2. Modify the rest of the WordCard SFC to use the correct and answer properties in the SFC's data instead of the word.correct and answer.correct properties from the word prop.
    • You can make the changes manually, or asking Copilot for a "fix" at this point should make all of the right changes.

Self Check

  1. Review: Why does using v-model change word.answer?
  2. At first glance it looks like we could have used a local variable for correct inside of checkAnswer instead of creating a data property. Why wouldn't that work correctly?

Custom elements in iteration require v-bind:key directives

In App.vue we use a v-for that iterates over shuffledWords creating one WordCard for each element of shuffledWords. The elements within shuffledWords are objects (i.e., "custom elements). So the linter message is telling us that because we are iterating over an array of objects we need a v-bind:key directive.

A key can be any property of the objects that is a unique identifier (i.e., is different in every object). In the case of the elements of words (or shuffledWords) word_a seems like good choice for the key. In the Tasks below we'll fix this linting issue by using word_a as a key.

The reasons for needing a key have to do with Vue's reactivity system and are somewhat technical. If you are interested in the details, the VueSchool site has an excellent article explaining some Tips and Gotchas for Using key with v-for in Vue.js 3.

Tasks

  1. Find the code that is causing the "Custom elements in iteration require v-bind:key directives" linting issue.
  2. Use a Copilot "Fix" to solve the problem.

Self Check

  1. What other properties of the word objects could be used as the key? Why might word_a still be the best choice?
  2. When is it necessary to use a v-bind:key directive in a v-for?
  3. What is the syntax for using a v-bind:key directive in a v-for?

Turning in Your Work

Once you have finished all of the work in this tutorial you will need to officially submit it.

Task

  1. Use the steps for "Completing a Tutorial" to submit your work. You should be starting to internalize this process making you less reliant on reading the detailed instructions each time.

Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License This Tutorial is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs workA tutorial or extension that requires additional work before it is ready for class use.tutorialAn assignment (a collection of lessons) to be completed.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions