One place for hosting & domains

      Vuejs

      How To Use Built-In and Custom Directives in Vue.js


      The author selected Open Sourcing Mental Illness to receive a donation as part of the Write for DOnations program.

      Introduction

      As a front-end framework, Vue.js can be thought of as a mixture of React and Angular. Vue borrows the prop-driven approach of React, but also uses directives, which were made popular by Angular. In this context, directives are reusable chunks of code or logic that developers can use within an HTML template. These can allow you to manipulate your HTML in many different ways, such as conditionally rendering an element, connecting events to an element, or creating dynamic attributes that depend on your Vue code.

      In this tutorial, you will try out some of the most common built-in Vue directives, such as v-if, v-show, v-on, v-bind, v-model, and v-html. For these first sections, the tutorial will lead you through examples that you can follow in an online Vue playground like the Vue Single File Component Playground. In addition to this, you will create a new Vue project to try out custom directives that you can add to HTML elements for additional functionality.

      Prerequisites

      Using the v-if, v-else, and v-else-if Directives

      Vue.js comes pre-packaged with a number of directives that developers commonly use when working within the framework. Directives such as v-if, v-show, v-on, v-model, v-bind, v-html, and more are all provided for you out-of-the-box. All of these provided directives start with v-.

      The v-if, v-else, and v-else-if directives allow you to create conditionally rendered HTML elements, and work similarly to JavaScript’s if, else if, else conditions. Instead of returning HTML or code like you would in JavaScript, Vue will conditionally render that block of code.

      To apply a Vue directive, you will add it to an HTML element in the template section of your Vue single-file component. For example, if you wanted to add a v-if directive to a paragraph element, you would use the following syntax:

      <p v-if="https://www.digitalocean.com/community/tutorials/condition"></p>
      

      In this case, the highlighted condition is a placeholder for the boolean expression that determines if the paragraph element is rendered or not.

      To illustrate how the v-if directives work in a real situation, create the following code for a user welcome page:

      <template>
        <p v-if="user.firstName && user.lastName">
          Welcome, {{ user.firstName }} {{ user.lastName }}!
        </p>
        <p v-else-if="user.username">
          Welcome, {{ user.username }}!
        </p>
        <div v-else>
          <button>Login</button>
          <button>Create Account</button>
        </div>
      </template>
      
      <script setup>
          const user = {
          firstName: 'Sammy',
          lastName: 'Shark',
          username: 'sammyDO'
        }
      </script>
      

      In this code, there are a number of HTML elements, including two <p> tags and a <div> tag with two buttons. However, when this code runs in the browser, only one of these chunks of code will render, depending on the condition that evaluates to true. HTML with false conditions will not render in your DOM (Document Object Model).

      As it is now, since both firstName and lastName have values in the <script> tag, the expression user.firstName && user.lastName will evaluate to true, and the browser will render the paragraph. This will look like the following image in your browser:

      Web page with the words

      If either firstName or lastName is not defined, the condition will evaluate to false, and Vue will move to the v-else-if directive. This directive is attached to the user.username expression, so if this evaluates to true it will render the attached paragraph element. To try this, delete the firstName in your <script> tag:

      ...
      <script setup>
          const user = {
          lastName: 'Shark',
          username: 'sammyDO'
        }
      </script>
      

      Since the condition user.firstName && user.lastName now evaluates to false but user.username evaluates to true, the username will render instead. This is shown in the following image:

      Web page with the words

      Lastly, if all the conidtions evaluate to false, control will pass to the v-else directive, which here renders two buttons to log in or create an account. To try this out, delete the username data in the script element:

      ...
      <script setup>
          const user = {
          lastName: 'Shark',
        }
      </script>
      

      Now you will find default buttons rendered in the browser:

      Web page with

      It is important to note that you must have an element with a v-if directive directly before a v-else-if or v-else directive. Otherwise it will not work.

      As an example, the following code snippet is considered invalid and you will get an error in your browser’s console:

      <template>
        <p v-if="user.firstName && user.lastName">
          Welcome, {{ user.firstName }} {{ user.lastName }}!
        </p>
        <p v-else-if="user.username">
          Welcome, {{ user.username }}!
        </p>
        <h1>Some Title</h1>
        <div v-else>
          <button>Login</button>
          <button>Create Account</button>
        </div>
      </template>
      
      <script setup>
          const user = {
          firstName: 'Sammy',
          lastName: 'Shark',
          username: 'sammyDO'
        }
      </script>
      

      Since the <h1> element after the paragraph with the v-else-if directive has no directive, this code will fail to render and will yield the following syntax error:

      Output

      SyntaxError: v-else/v-else-if has no adjacent v-if.

      With this summary of v-if covered, you can now try out another way to conditionally display HTML elements: the v-show directive.

      Using the v-show Directive

      Beyond the v-if-related directives, there is another directive that you can use to display HTML elements based on a condition. That directive is v-show. It’s similar to v-if, with the exceptions that there are no else-if and else counterparts and the elements are conditionally displayed rather than conditionally rendered.

      Take a look at the following code that addresses a similar situation as in the last section:

      <template>
        <div v-show="!userIsLoggedIn">
          <button>Login</button>
          <button>Create Account</button>
        </div>
        <div v-show="userIsLoggedIn">
          <p>Welcome!</p>
        </div>
      </template>
      
      <script setup>
          const userIsLoggedIn = true
      </script>
      

      In this code, you’ve attached v-show to two <div>s, along with conditional expressions. v-show will display the attached HTML if the condition in the quotation marks is met. In this example, userIsLoggedIn evaluates to true, so the browser will display the <div> with the Welcome! paragraph:

      Web page with the words

      Now change the userIsLoggedIn value to false:

      ...
      <script setup>
          const userIsLoggedIn = false
      </script>
      

      You will again find the login buttons:

      Web page with

      It is worth emphasizing the difference between v-if and v-show. v-if conditionally renders the HTML; if the conditional expression evaluates to false, the DOM will not include it at all. v-show on the other hand will always render the HTML in the DOM. But the element will not appear in the browser because it will be hidden with the display: none CSS style.

      With the conditional v-if and v-show directives covered, you can now move on to the v-on directive to tie events to HTML elements.

      Using the v-on Directive

      The v-on directive executes functions on a specific event. This can be a custom event or a standard JavaScript event, such as click, hover, or mouseenter. When using the v-on directive, you must provide the event type after a colon (:) and the function to be executed. The component’s function name will reside in-between the quotation marks.

      As an example of this, examine the following highlighted code:

      <template>
        <button v-on:click="handleClick">Click Me</button>
      </template>
      
      <script setup>
          function handleClick() {
          alert('You clicked the button!')
        }
      </script>
      

      In this example, the component function handleClick will execute when the user clicks on the <button> element that the directive is attached to. If you run this code and click on the button, you will receive an alert that reads You clicked the button!:

      Browser popup box that reads

      Events with the v-on directive can also have event modifiers chained to the event itself. These event modifiers can change how the event is executed, and can save time when writing functionality that would normally take multiple lines of JavaScript. Some modifiers provided by Vue include:

      • once: Limits the event to fire only once.
      • self: Event will only trigger if the event target is the same element that holds the directive.
      • prevent: Stops the event from happening.
      • stop: Stops the event from propagating.

      Next, you will run through an example of the once event modifier to try out the syntax. Add the following highlighted code to the previous snippet:

      <template>
        <button v-on:click.once="handleClick">Click Me</button>
      </template>
      ...
      

      With the .once modifier, the function handleClick will only execute one time. Try clicking the Click Me button, and the alert will pop up. Clear the alert, then click it again. The event will not fire because it has already fired once.

      The v-on directive also has a shorthand syntax. To use the shorthand syntax, replace v-on: with @.

      <template>
        <button @click.once="handleClick">Click Me</button>
      </template>
      ...
      

      This will lead to the same behavior as v-on:click.once.

      Now that events have been addressed with v-on, you can move on to binding data to template elements with v-bind and v-model.

      Using the v-bind and v-model Directives

      Vue.js is a Model-View-ViewModel (MVVM) framework, which means separate data (the model) updates the HTML (view), and the view in turn updates the model. This separation means that view, or what renders in the browser, can operate independently of the data processing.

      To enact the MVVM approach, Vue provides ways for data, props, and computed properties to pass into a Vue component. This is done with two-way data binding, which allows for the view and model to interact with each other.

      In the following code, you have a <p> element with dynamic content that changes depending on the data values:

      <template>
        <p>I am from {{ city }}.</p>
      </template>
      
      <script setup>
          const city = 'Cincinnati'
      </script>
      

      In this snippet, {{ city }} is a data reference to the city constant in the <script> element after it. As it is now, {{ city }} will evaluate to the string "Cincinnati", and a paragraph element with the words I am from Cincinnati will render in your browser. If you were to change Cincinnati to Seattle, the {{ city }} in the template would update accordingly.

      For this dynamic content, you don’t need to use a directive: The template has access to the city constant automatically. However, if you wanted to make an HTML attribute dynamic by referencing the <script> data, you would have to explicitly bind the data with v-bind.

      To illustrate this, you will enclose the {{ city }} placeholder in a link (<a>) tag that will dynamically lead to the Wikipedia page for the city assigned to the city constant. First, wrap the {{ city }} in an <a> tag so the user can click on it and get more information on the city itself. After that, create a computed property called wikipediaLink and have it return the appropriate URL. Add the highlighted code:

      <template>
        <p>I am from <a href="">{{ city }}</a>.</p>
      </template>
      
      <script setup>
        import { computed } from 'vue'
      
          const city = 'Cincinnati"https://www.digitalocean.com/community/tutorials/const wikipediaLink = computed(() =>`https://en.wikipedia.org/wiki/${city}`)
      </script>
      

      In the <script> element, you imported the computed function from the Vue library, then used it to assign a URL to wikipediaLink. The URL string uses a template literal to change depending on the value of city.

      Now that you have your Wikipedia link, go ahead and add the computed property name to the href attribute of the anchor tag you added earlier:

      <template>
        <p>I am from <a href="https://www.digitalocean.com/community/tutorials/wikipediaLink">{{ city }}</a>.</p>
      </template>
      ...
      

      If you were to view this in a browser at this point, you would recieve a console error. This is because right now Vue.js thinks wikipediaLink is a string literal, which is not a valid URL.

      To tell Vue.js to use the returned value of the wikipediaLink computed property, you need to use the v-bind directive. This will bind the reference in the template to the computed property, as shown in the following:

      <template>
        <p>I am from <a v-bind:href="https://www.digitalocean.com/community/tutorials/wikipediaLink">{{ city }}</a>.</p>
      </template>
      ...
      

      Now, the href value will be the URL for the Cincinnati Wikipedia page. This URL will update if the city property changes to another city, such as Seattle.

      Similar to v-on, v-bind also has a shorthand that you can opt to use. To use the shorthand, replace v-bind: with :, as shown in the following:

      <template>
        <p>I am from <a :href="https://www.digitalocean.com/community/tutorials/wikipediaLink">{{ city }}</a>.</p>
      </template>
      

      There is another directive in Vue.js that is used to bind a value to a data property. However, this directive only works for input tags:

      <template>
        <input v-model="city" type="text" />
      </template>
      
      <script setup>
        const city = 'Cincinnati'
      </script>
      

      When using the v-model directive, you are binding the input fields value attribute to the data property in the quotation marks. It is recommended to use the v-model directive over v-bind for form <input /> tags.

      This Vue component will render a text input box with the default text of Cincinnati, as shown in the following image:

      Text input box with

      This section covered different ways to bind HTML attributes to variable or computed data. Next, you will use the v-html directive to inject HTML into your template.

      Using the v-html Directive

      The last pre-packaged directive that this tutorial will go over is v-html. This directive converts HTML inside of a string literal into raw HTML for the browser to read, which will allow you more flexibility in how you create and apply your HTML.

      In this hypothetical component, you have a <div> that has a v-html directive with a data property as its value:

      <template>
        <div v-html="someHtmlCode" />
      </template>
      
      <script setup>
        const someHtmlCode = `<p>Some <span>HTML</span> in this string</p>`
      </script>
      

      The v-html directive is telling Vue.js to inject the string of the someHtmlCode data reference into the <div /> in the template. When compiled by Vue, you will find the following in your DOM:

      <div>
        <p>Some <span>HTML</span> in this string</p>
      </div>
      

      The HTML will also render in your browser:

      A browser window with

      This directive is useful if you need to render HTML that comes from a REST API service or large HTML from an external JavaScript file.

      At this point in the tutorial, you’ve tried out the directives that are provided to you by Vue.js. However, there may be times when you will need a directive that Vue doesn’t provide. In cases such as these, you can create a custom directive to handle specific logic in your HTML template.

      Creating a Custom Directive

      In the Vue.js framework, you have the ability to create custom directives to suit the individual needs for your project. In this section, for example, you will create a v-theme directive that applies a specific style to an element of your template.

      Up to this point, you did not have to follow along with a stand-alone Vue project. However, in this section, you will create a fresh project generated from the Vue CLI.

      Open your terminal and generate a new project with the following command. The name of this project will be custom-directive, which will also be the name of the root directory:

      • vue create custom-directive

      For this tutorial, select Vue 3x for Choose Vue Version. Once the app has been created, open your generated project in your text editor of choice. Then open the main.js file in the src directory.

      First, you will get this file set up. Store createApp(App) into a const so you can reference it later:

      custom-directive/src/main.js

      import { createApp } from 'vue'
      import App from './App.vue"https://www.digitalocean.com/community/tutorials/const app = createApp(App)
      
      app.mount('#app')
      

      Now with that createApp function in its own const, you can extend this app by adding a directive:

      custom-directive/src/main.js

      import { createApp } from 'vue'
      import App from './App.vue'
      
      const app = createApp(App)
      
      app.directive("theme", {})
      
      app.mount('#app')
      

      In this code, you are leveraging the directive() function on the Vue instance. This function accepts two arguments: the directive name (theme in this case) and an object with lifecycle hooks.

      You will set this code up so that it executes when the component is mounted. This mounted hook accepts two arguments: el, the HTML element, and binding, the value passed into the directive. With this information, you can construct the following:

      custom-directive/src/main.js

      const app = createApp(App)
      
      app.directive("theme", {
        mounted(el, binding) {
      
        }
      })
      
      app.mount('#app')
      

      For this theme directive, you will pass in a string to determine the element’s styling. This string will either be primary, secondary, or tertiary, each of which corresponds to a color in a hypothetical colorscheme.

      Now that the directive code is in place, you can add the logic. To access the value inside of the quotaion marks of the directive, you can use binding.value. To change the color of the element’s text, you will use JavaScript to access the el properties:

      custom-directive/src/main.js

      const app = createApp(App)
      
      app.directive("theme", {
        mounted(el, binding) {
          if (binding.value === 'primary') {
            el.style.color="red"
          } else if (binding.value === 'secondary') {
            el.style.color="green"
          } else if (binding.value === 'tertiary') {
            el.style.color="blue"
          } else {
            el.style.color="black"
          }
        }
      })
      
      app.mount('#app')
      

      The highlighted section of this snippet is a series of if/else statements. If the value passed into the directive is primary, the text color will be red, secondary will be green, tertiary will be blue, and no value will revert to the default black.

      Close and save your main.js file.

      At this point, you have created a custom directive that you can use in your Vue.js application. Vue will automatically prefix the directive name with v-, so the template can access your directive as v-theme.

      Open your App.vue file in your text editor of choice. In the template, add a <p> tag with some text in it:

      custom-directive/src/App.vue

      <template>
        <p>This text will change color based on the directive value!</p>
      </template>
      

      Save this file, then start the application with npm run serve. This will run your project on the :8080 port on your localhost:

      To view your generated project, open your browser of choice and visit localhost:8080 in the URL bar. You will find your paragraph element rendered in black:

      The words

      Next, change the color by adding your directive to the HTML:

      custom-directive/src/App.vue

      <template>
        <p v-theme="`primary`">This text will change color based on the directive value!</p>
      </template>
      

      Save this file and open it in your web browser. The value inside the quotation marks is a raw value and automatically bound to Vue, so inside the quotation marks you will need to wrap primary using back ticks to convert it to a string.

      Save your file and the text on your rendered site will turn red:

      The words

      The directive reads the value in the binding object and executes the code accordingly. Since the value is primary, JavaScript will change the color of the text to red.

      In this section, you created a custom directive, registered it, and executed its logic. You also added your new custom directive and assigned it to an HTML element in the template.

      Conclusion

      In this tutorial, you ran through exercises to test out what directives are and how to use them. Specifically, you used the most common built-in directives, including v-if, v-on, v-show, and v-html. In addition to this, you registered and created your own custom directive. This directive, v-theme, can now be used on any HTML element to execute a JavaScript function.

      While you went over a number of directives, there are many more made available to you by Vue.js. For more information regarding directives, it is recommended to review the official Vue.js Documentation. For more tutorials on Vue, check out the How To Develop Websites with Vue.js series page.



      Source link

      How To Use Vue.js Environment Modes with a Node.js Mock Data Layer


      The author selected Open Sourcing Mental Illness to receive a donation as part of the Write for DOnations program.

      Introduction

      When it comes to software development, there are two ends of the stack. A stack is a collection of technologies used for your software to function. Vue.js, the progressive user interface framework, is part of the frontend, the part of the stack that a user directly interacts with. This frontend is also referred to as the client and encompasses everything that is rendered in the user’s browser. Technologies such as HTML, JavaScript, and CSS are all rendered in the client. In contrast, the backend commonly interacts with data or servers through technologies like Java, Kotlin, or .NET.

      The application is the data itself, and the interface (frontend) is a way to display data meaningfully to the user for them to interact with. In the begining phase of software development, you don’t need a backend to get started. In some cases, the backend hasn’t even been created yet. In a case such as this, you can create your own local data to build your interface. Using Node environments and variables, you can toggle different datasets per environment or toggle between local data and “live” data via a network call. Having a mock data layer is useful if you do not have data yet, because it provides data to test your frontend before the backend is ready.

      By the end of this tutorial, you will have created several Node environments and toggled these datasets with Node environment variables. To illustrate these concepts, you will create a number of Vue components to visualize this data across environments.

      Prerequisites

      To complete this tutorial, you will need:

      Step 1 — Creating Environments with Modes

      Modes are an important concept when it comes to Vue CLI projects. A mode is an environment type, or a set of variables that gets loaded during a build. These variables are stored in .env files in the root directory of your project. As part of the default vue-cli-service plugin, you immediately have access to three modes. These are:

      • development: used when vue-cli-service serve is executed.
      • test: used when vue-cli-service test:unit is executed.
      • production: used when vue-cli-service build and vue-cli-service test:e2e are executed.

      Perhaps the most used mode is development mode. This is the mode that Vue.js developers use when working on their application on their local machine. This mode starts a local Node server with hot-module reloading (instant browser refreshing) enabled. The test mode, on the other hand, is a mode to run your unit tests in. Unit tests are JavaScript functions that test application methods, events, and in some cases, user interaction. The last default mode is production. This compressess all of your code and optimizes it for performance so it can be hosted on a production server.

      The project that is generated for you from Vue CLI has these commands pre-mapped to npm run serve, npm run test:unit, and npm run build.

      Each environment is associated with its own .env file, where you can put custom Node environment key/value pairs that your application can reference. You will not have these files after generating a project from the CLI, but you can add these using one command in your terminal.

      You will now generate a development environment file, which you will use later in the tutorial. Open your terminal and enter the following in the root directory of your project:

      Open the newly created file in your text editor of choice. In this file, you’ll want to explicitly define the environment type. This is a key/value pair that could be anything you want. However, it’s considered best practice to define the environment type that corresponds with the name of the .env file.

      You will be using this NODE_ENV later in the tutorial by loading different data sets depending on the environment or mode selected on build. Add the following line:

      .env.development

      NODE_ENV="development"
      

      Save and exit the file.

      The key/value pairs in this file will only affect your program when the application is in development mode. It’s important to note that Git will automatically commit these files unless you add the file in your .gitignore file or append the .local extension to the file name: .env.development.local.

      You are not limited to the standard environments that Vue.js provides. You may have several other environments that are specific to your workflow. Next, you’ll create a custom environment for a staging server.

      Start by creating the .env file for the staging environment. Open your terminal of choice and in the root directory run the following:

      In this file, create a key/value pair that’ll define the NODE_ENV of this project. You may open this file in your text editor of choice, or you can modify it using the terminal. Nano is an editor that is used in the terminal window. You may have other editors such as Vim.

      You will be using this NODE_ENV later in the tutorial by loading different data sets depending on the environment or mode selected on build.

      Add the following to the file:

      .env.staging

      NODE_ENV="staging"
      

      Save and exit the file. In nano, you can save the file with CTRL+X then CTRL+Y.

      In order to use this environment, you can register a new script in your package.json file. Open this file now.

      In the "scripts" section, add the following highlighted line:

      package.json

      {
        ...
        "scripts": {
          ...
          "staging": "vue-cli-service serve --mode staging",
        },
        ...
      }
      

      Save this file, then exit the editor.

      You’ve just created a new script that can be executed with npm run staging. The flag --mode lets Vue CLI know to use the .env.staging (or .env.staging.local) file when starting the local server.

      In this step, you created custom NODE_ENV variables for two Vue.js modes: development and staging. These modes will come in handy in the following steps when you create custom datasets for each of these modes. By running the project in one mode or the other, you can load different data sets by reading these files.

      Step 2 — Creating a Mock Data Layer

      As stated in the Introduction, you can start developing your user interface without a backend by using a mock data layer. A mock data layer is static data that is stored locally for your application to reference. When working with Vue, these data files are JavaScript objects and arrays. Where these are stored is your personal preference. For the sake of this tutorial, mock data files will be stored in a directory named data.

      In this tutorial, you’re building a “main/detail” airport browser application. In the “main” view, the user will see a number of airport codes and locations.

      In your terminal, in the root project directory, create a new directory using the mkdir command:

      Now create a .js file named airports.staging.mock.js using the touch command. Naming these files is personal preference, but it’s generally a good idea to differentiate this mock data from essential files in your app. For the sake of this tutorial, mock files will follow this naming convention: name.environment.mock.js.

      Create the file with the following command:

      • touch data/airports.staging.mock.js

      In your editor of choice, open this newly created JavaScript file and add the following array of objects:

      data/airports.staging.mock.js

      const airports = [
          {
              name: 'Cincinnati/Northern Kentucky International Airport',
              abbreviation: 'CVG',
              city: 'Hebron',
              state: 'KY'
          },
          {
              name: 'Seattle-Tacoma International Airport',
              abbreviation: 'SEA',
              city: 'Seattle',
              state: 'WA'
          },
          {
              name: 'Minneapolis-Saint Paul International Airport',
              abbreviation: 'MSP',
              city: 'Bloomington',
              state: 'MN'
          }
      ]
      
      export default airports
      

      In this code block, you are creating objects that represent airports in the United States and providing their name, abbreviation, and the city and state in which they are located. You then export the array to make it available to other parts of your program. This will act as your “staging” data.

      Next, create a dataset for another environment like “development"—the default environment when running npm run serve. To follow the naming convention, create a new file in your terminal with the touch command and name it airports.development.mock.js:

      • touch data/airports.development.mock.js

      In your editor of choice, open this newly created JavaScript file and add the following array of objects:

      data/airports.development.mock.js

      const airports = [
          {
              name: 'Louis Armstrong New Orleans International Airport',
              abbreviation: 'MSY',
              city: 'New Orleans',
              state: 'LA'
          },
          {
              name: 'Denver International Airport',
              abbreviation: 'DEN',
              city: 'Denver',
              state: 'CO'
          },
          {
              name: 'Philadelphia International Airport',
              abbreviation: 'PHL',
              city: 'Philadelphia',
              state: 'PA'
          }
      ]
      
      export default airports
      

      This will act as your "development” data when you run npm run serve.

      Now that you’ve created the mock data for your environments, in the next step, you are going to iterate or loop through that data with the v-for directive and start building out the user interface. This will give you a visual representation of the change when using the different modes.

      Step 3 — Iterating Through Mock Data in App.vue

      Now that you have your mock data, you can test out how useful environments are by iterating through this data in the App.vue component in the src directory.

      First, open up App.vue in your editor of choice.

      Once it is open, delete all of the HTML inside the template tags and remove the import statement in the script section. Also, delete the HelloWorld component in the export object. Some general styles have also been provided to make the data easier to read.

      Add the following highlighted lines to your App.vue file:

      src/App.vue

      <template>
      
      </template>
      
      <script>
      export default {
        name: 'App',
      }
      </script>
      
      <style>
      #app {
        font-family: Avenir, Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-align: center;
        color: #2c3e50;
        margin-top: 60px;
      }
      
      .wrapper {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        grid-column-gap: 1rem;
        max-width: 960px;
        margin: 0 auto;
      }
      
      .airport {
        border: 3px solid;
        border-radius: .5rem;
        padding: 1rem;
      }
      
      .airport p:first-child {
        font-weight: bold;
        font-size: 2.5rem;
        margin: 1rem 0;
      <^>}
      
      .airport p:last-child {
        font-style: italic;
        font-size: .8rem;
      }
      </style>
      

      In this case, CSS Grid is being used to create these cards of airport codes into a grid of three. Notice how this grid is set up in the .wrapper class. The .airport is the card or section that contains each airport code, name, and location.

      Next, import the development mock data that was created earlier. Since this is vanilla JavaScript, you can import it via an import statement. You will also need to register this data with the data property so the Vue template has access to this data.

      Add the following highlighted lines:

      src/App.vue

      ...
      <script>
      import airports from '../data/airports.development.mock'
      
      export default {
        name: 'App',
        data() {
          return {
            airports
          }
        }
      }
      </script>
      ...
      

      Now that the mock data has been imported, you can start using it to build your interface. In the case of this application, iterate through this data with the v-for directive and display it in your template:

      src/App.vue

      <template>
        <div class="wrapper">
          <div v-for="airport in airports" :key="airport.abbreviation" class="airport">
            <p>{{ airport.abbreviation }}</p>
            <p>{{ airport.name }}</p>
            <p>{{ airport.city }}, {{ airport.state }}</p>
          </div>
        </div>
      </template>
      ...
      

      v-for in this case is used to render the list of airports.

      Save and close the file.

      In your terminal, start the development server by running the command:

      Vue CLI will provide you a local address, generally localhost:8080. Visit that addresss in your browser of choice. You will find the data from airports.development.mock.js rendered in your browser:

      Styled cards containing airport data from the development dataset.

      At this point, you created a static mock data layer and loaded it when you executed npm run serve. However, you will notice that if you stop the server (CTRL+C) and start the staging environment, you will have the same result in your browser. In this next step, you are going to tell your app to load a set of data for each environment. To achieve this, you can use a Vue computed property.

      Step 4 — Loading Environment-Specific Data with Computed Properties

      In Vue, computed properties are component functions that must return a value. These functions cannot accept arguments, and are cached by Vue. Computed properties are very useful when you need to perform logic and assign that return value to a property. In this respect, computed properties act similar to data properties as far as the template is concerned.

      In this step, you will use computed properties to use different datasets for the staging and the development environment.

      Start by opening src/App.vue and importing both sets of data:

      src/App.vue

      ...
      <script>
      import DevData from '../data/airports.development.mock'
      import StagingData from '../data/airports.staging.mock'
      
      export default {
        name: 'App',
        ...
      }
      </script>
      ...
      

      If you still have one of the environments running, your data will disappear. That is because you removed the data property that connected your JavaScript mock data to the template.

      Next, create a computed property named airports. The function name is important here because Vue is taking the return value of the function and assigning it to airports for the template to consume. In this computed property, you’ll need to write a bit of logic; an if/else statement that evaluates the Node environment name. To get the value of the Node environment in Vue, you can access it with process.env.NODE_ENV. When you created your Node environments, Vue automatically assigned NODE_ENV to development and staging respectively.

      src/App.vue

      ...
      <script>
      import DevData from '../data/airports.development.mock'
      import StagingData from '../data/airports.staging.mock'
      
      export default {
        name: 'App',
        computed: {
            airports() {
              if (process.env.NODE_ENV === 'development') return DevData
              else return StagingData
            }
        }
      }
      </script>
      ...
      

      Now you are loading each set of data per its respective environment.

      In your terminal, start the local development environment with npm run serve.

      The data will be identical to what it was before.

      Now, start the staging environment by first stopping the server and then executing npm run staging in your terminal window.

      When you visit localhost:8080 in your browser, you will find a different set of data.

      Styled cards containing airport data from the staging dataset.

      Conclusion

      In this tutorial, you worked with different Vue.js environment modes and added environment scripts to your package.json file. You also created mock data for a number of environments and iterated through the data using the v-for directive.

      By using this approach to make a temporary backend, you can focus on the development of your interface and the frontend of your application. You are also not limited to any number of environments or the default environments provided by Vue. It isn’t uncommon to have .env files for four or more environments: development, staging, user acceptance testing (UAT), and production.

      For more information on Vue.js and Vue CLI 3, it’s recommended to read through their documentation. For more tutorials on Vue, check out the Vue Topic Page.



      Source link

      How To Generate a Vue.js Single Page App With the Vue CLI


      The author selected Open Sourcing Mental Illness to receive a donation as part of the Write for DOnations program.

      Introduction

      Vue.js is a popular JavaScript framework for creating user interfaces. Created in 2014 by Evan You (formally of Google), Vue.js is often described as a combination of React and Angular, borrowing the prop-driven development of React and the templating power of Angular. This makes Vue an accessible framework for beginners to pick up, especially since it focuses on traditional HTML and CSS, rather than being a CSS-in-JS framework like React or relying on TypeScript (a superset of JavaScript) like Angular does.

      When starting a new project, it’s best to familiarize yourself with the technology’s tools and features. One important tool for Vue.js development is its command line interface (CLI) known as Vue CLI 3. The Vue CLI offers a number of useful features that enhance the Vue development experience, but the main feature is its ability to generate and pre-configure a new single-page application with the vue create command.

      By the end of this tutorial, you will have a working Vue.js application running on a local Node server. This local server uses hot module reloading via Webpack to provide immediate feedback, rendered in-browser as you work. Along the way, you will create .vue single-file components (SFC), such as a header and a footer. All of this you can save as a solid foundation for any future Vue projects.

      Prerequisites

      To follow this tutorial, you will need the following:

      Step 1 — Downloading Vue CLI 3

      To download Vue CLI 3, you will need to run a command either via npm or Yarn, whichever you prefer. npm or Node Package Manager is a way to download and manage other people’s code to use in your project as a dependency. Yarn, on the other hand, executes NPM commands under the hood but provides additional features like caching. It’s up to personal preference regarding which one to use. However, it is important to note that it’s not recommended to mix commands. It’s best to be consistent with one or the other for the duration of your project.

      Moving forward, this tutorial will use npm commands. The following command will download the necessary Vue CLI files from the registrar, which in this case is the npm (Node Package Manager) service:

      npm i -g @vue/cli
      

      Note: On some systems, installing an npm package globally can result in a permission error, which will interrupt the installation. Since it is a security best practice to avoid using sudo with npm install, you can instead resolve this by changing npm’s default directory. If you encounter an EACCES error, follow the instructions at the official npm documentation.

      You install this globally in order to use the CLI anywhere on your machine. If you don’t install this globally, it will only work in the directory that you installed it at. In the case of the command options, i means “install” and -g is a flag to install the code globally on your computer.

      To verify if Vue CLI 3 was properly installed, run the following:

      vue --version
      

      You will receive the following output with a version number. Your version number may differ, but if you receive a response with a version number, you’ve properly installed Vue CLI 3:

      Output

      @vue/cli 4.5.6

      To update Vue CLI 3, run the previous commands in this section, and the latest version will be installed.

      At this point, you have successfully downloaded npm globally along with the Vue CLI tool that you will use in the next section to create a generated Vue.js project.

      Step 2 — Generating a Single-Page Application

      As you develop Vue.js applications, you may find that manually configuring a project is not the most productive use of your time, since configuring a new Vue.js project from scratch can take hours. This is the true power of Vue CLI: It provides you with a pre-generated template that is based on your specifications. Because of this, it’s already configured so you can start developing your website or application right away. Vue CLI 3 will ask you a few questions via a command line prompt about your project, download the required files, and pre-configure it for you so you are ready to work as soon as it’s done.

      To generate a single-page application, navigate to the directory you’d like your Vue project in, then run the following:

      vue create vue-starter-project
      

      The highlighted section of the command is the name of the root directory of the project. This will be the name of the folder that contains all of your Vue.js project files. This can be whatever you’d like, but in the case of this tutorial, you will use vue-starter-project.

      Once you type out that command, continue by pressing Enter. You will then receive the following prompt:

      Vue CLI v4.5.6
      ? Please pick a preset: 
        Default ([Vue 2] babel, eslint) 
        Default (Vue 3 Preview) ([Vue 3] babel, eslint) 
      ❯ Manually select features 
      

      If you do not want to configure your project and opt for the defaults, you can do so with either Vue 2 or Vue 3. For the purpose of this tutorial though, it’s recommended to manually select your features. By selecting specific features, you will see how each option you selected was installed by the CLI.

      Select Manually select features with ENTER. Immediately you’ll receive a number of different options, including: Choose Vue version, TypeScript, Router, and Vuex. Notice that some of these items are already selected (the bubble is filled in). You may select as many or as few as you’d like. However, for this tutorial, select the following by pressing <space> on the entry:

      ...
       ◉ Choose Vue version
       ◉ Babel
       ◉ TypeScript
       ◯ Progressive Web App (PWA) Support
       ◉ Router
       ◉ Vuex
       ◉ CSS Pre-processors
       ◉ Linter / Formatter
      ❯◯ Unit Testing
       ◯ E2E Testing
      

      Once you have your options selected, press the ENTER key. The CLI will ask you further questions regarding each of the features you selected for your project, in order. The first question will ask which version of Vue you’d like to use: 2.x or 3.x. You’ll use Vue 3 for this tutorial, but you may want to use Vue 2 if you want greater support from the Vue Community:

      ...
      ? Choose a version of Vue.js that you want to start the project with 
        2.x 
      ❯ 3.x (Preview)
      

      The next question is regarding TypeScript integration. If you are not familiar with TypeScript, that’s alright. This option was intentionally selected to illustrate how Vue CLI 3 downloads what you defined as required for unique project. This tutorial will not use the class-style syntax, but will use Babel alongside TypeScript.

      When encountering the following, enter N:

      ...
      Use class-style component syntax? (y/N) N
      

      In the following prompt, enter Y:

      ...
      ? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? (Y/n) Y
      

      Next, Vue CLI will ask about history mode. History mode will make each route its own URL. This means you will not have the /#/ (hash) in your application’s URL. If you do use history mode, you will need a Node server to run your project. This is not a problem, because Vue CLI 3 provides you with a Node server.

      Type Y to answer yes to history mode:

      ...
      ? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) Y
      

      The next question is regarding CSS pre-processors such as Sass or LESS. A CSS pre-processor is CSS with added features like nesting and variables. The browser cannot read this, so when the project is built, Node will compile all of your SCSS or LESS code to traditional CSS. Since you are using Node to build your project, it’s recommended to select Sass/SCSS (with node-sass) as your pre-processor. Later on, you’ll add lang attributes in your .vue components to enable SCSS on a per component basis:

      ...
      ? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): 
        Sass/SCSS (with dart-sass) 
      ❯ Sass/SCSS (with node-sass) 
        Less 
        Stylus 
      

      After that, you will receive some questions regarding the linter style. A linter is a program that evaluates your code as you develop your application. This linter can enforce a number of syntactical rules during development. In addition to this, your integrated development environment (IDE) can read this configuration file and format your code on save. This will keep your code consistent no matter who works on your project and what operating system or IDE a developer is using.

      For this tutorial, choose ESLint + Standard config:

      ...
      ? Pick a linter / formatter config: 
        ESLint with error prevention only 
        ESLint + Airbnb config 
      ❯ ESLint + Standard config 
        ESLint + Prettier 
        TSLint (deprecated) 
      

      This selects a set of rules for ESLint to enforce. These configurations include options like the use of trailing commas, semi-colons at the end of a line, or using const over var in JavaScript.

      The next option is selecting when you want ESLint to format your code. This can be either on save or when you commit your code to a service like GitHub, GitLab, or BitBucket. It’s recommended to select Lint on save so you can review any changes before committing to version control:

      ...
      ? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)
      ❯◉ Lint on save
       ◯ Lint and fix on commit
      

      Once you select your lint features, Vue CLI will ask you about how you want to store these configurations, whether in dedicated files or in the package.json. It’s considered standard practive to store configurations in their own files for a few reasons. One, configurations are easier to share between projects this way, and two, you’ll be keeping your package.json as legible as possible by only defining the important information about your app:

      ...
      ? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
      ❯ In dedicated config files 
        In package.json
      

      Once you are done, the CLI tool will ask if you want to save this selection as a preset for future projects. This is useful if you are generating projects for your employer and you want everything to stay consistent.

      Go ahead and save this configuraion as a preset; Vue CLI will ask you to rename it. Name it DigitalOcean Vue Tutorial Series:

      ...
      ? Save this as a preset for future projects? Yes
      ? Save preset as: DigitalOcean Vue Tutorial Series
      

      Now you can use these exact same settings for a future project.

      At this point, you will have something along the lines of this in your terminal summarizing all of your options:

      ? Please pick a preset: Manually select features
      ? Check the features needed for your project: Choose Vue version, Babel, TS, Router, Vuex, CSS Pre-processors, Linter
      ? Choose a version of Vue.js that you want to start the project with 3.x (Preview)
      ? Use class-style component syntax? No
      ? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
      ? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
      ? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with node-sass)
      ? Pick a linter / formatter config: Standard
      ? Pick additional lint features: Lint on save
      ? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
      ? Save this as a preset for future projects? (y/N) 
      

      Press ENTER, and Vue CLI will start creating your app.

      When completed, cd (change directory) in your project name (vue-starter-project):

      Next, start the application with npm run serve. This will run your project at a port on your localhost, usually :8080. If it’s a different port, the CLI will tell you:

      npm run serve
      

      You do not need to download dependencies, as the CLI already did that for you. To view your generated project, open your browser of choice and visit localhost:8080 in the URL bar. You will find a welcome screen with the Vue logo and the technologies you’ve selected in the previous steps.

      Vue template screen

      You can leave this server running throughout this tutorial to monitor your changes.

      In this section, you selected a number of options specific to the project you are creating. Vue CLI downloaded all of the code needed and pre-configured it for you. You can now start working in the generated code base, including creating your own single-file .vue components.

      Now that you have a single-page application running on a Node server, make some changes to this by creating a standard header and footer. These AppHeader.vue and AppFooter.vue components will be imported in such a way that they’ll be present on each route.

      In a new terminal window, navigate into the root of your vue-starter-project folder and list out the files with the following command:

      You will receive the following output:

      Output

      README.md babel.config.js node_modules package-lock.json package.json public src tsconfig.json

      You can also view the contents of your project by opening your project in your editor of choice, such as Visual Studio Code. In either case, you will have access to a number of different files and directories. These config files in the root directory have been created because of the selections made during the intial generation of this project. The option In dedicated config files told Vue CLI to create config.js files for each service you are using, such as Babel, TypeScript, and ESLint. In addition to these files, there are a number of directories. This tutorial will go over these as you get to them.

      First, create a .vue file in the components directory and name it AppHeader.vue. You can do this right-clicking in the components directory and creating a new file in IDEs like VS Code. If you prefer terminal commands, you can do this in your computer’s terminal with the bash command touch:

      touch src/components/AppHeader.vue
      

      In this step, you are creating a single-file component that will contain all of the HTML, JavaScript, and SCSS that this chunk of code needs. Every .vue component contains three basic concerns or sections: <template>, <script>, and <style>. In this case, template is the component’s HTML.

      Open up the new file in your text editor.

      In this file, create a header by using the <header> tag inside of <template>. Inside of this <header>, add the Vue.js logo and a <p> element with the content My Vue.js Application:

      vue-starter-project/src/components/AppHeader.vue

      <template>
        <header>
          <img alt="Vue logo" src="https://www.digitalocean.com/community/tutorials/assets/logo.png" height="50">
          <p>My Vue.js Application</p>
        </header>
      </template>
      

      Keep your development server running throughout development. If you close or cancel the server process, you will not be able to view your application in the browser.

      Save the file.

      At this point, when you open your browser, you will not see the HTML rendered. That is because you need to import the newly created AppHeader.vue component into a component that is already mounted. Since App.vue is your main entry point, it’s best to import it there so our header appears on every route.

      Open up the App.vue file in your text editor, then delete the div with the ID of nav and add the following highlighted code:

      vue-starter-project/src/App.vue

      <template>
        <app-header />
        <router-view/>
      </template>
      
      <script>
      import AppHeader from '@/components/AppHeader.vue'
      
      export default {
        components: {
          AppHeader
        }
      }
      </script>
      

      When you import using ES6, you are essentially creating a variable to later reference in your code. In this case, you are storing the code from AppHeader.vue into a variable called AppHeader. You need to register it via the components property before you can use it.

      Once it’s imported, you deleted the #nav in the template and added <app-header /> before the <router-view />. This renders the component in the HTML.

      After completing this step, save any unsaved file and open your browser back to localhost:8080. Thanks to hot module reloading, you will now find your newly created header at the top of the page:

      Vue template with new header

      You’ve now created a single-file Vue component, used import to bring it into a mounted component, and monitored the change with hot module reloading (HMR). Moving forward, you will extend the functionality of components through the use of child components. You will also use SCSS (the pre-processor you selected earlier) on a per component basis with the lang attribute.

      Now that the header is imported properly into the application, return to AppHeader.vue in your text editor. Add navigation underneath <p>My Vue.js Application</p> by adding the following highlighted code:

      vue-starter-project/src/components/AppHeader.vue

      <template>
        <header>
          <img alt="Vue logo" src="https://www.digitalocean.com/community/tutorials/assets/logo.png" height="50">
          <p>My Vue.js Application</p>
          <nav>
            <ul>
              <li><router-link to="/">Home</router-link></li>
              <li><router-link to="/about">About</router-link></li>
            </ul>
          </nav>
        </header>
      </template>
      

      Now, style this to make it look more like a traditional navigation bar. Create a <style> tag at the end of the file.

      vue-starter-project/src/components/AppHeader.vue

      <template>
        <header>
          <img alt="Vue logo" src="https://www.digitalocean.com/community/tutorials/assets/logo.png" height="50">
          <p>My Vue.js Application</p>
          <nav>
            <ul>
              <li><router-link to="/">Home</router-link></li>
              <li><router-link to="/about">About</router-link></li>
            </ul>
          </nav>
        </header>
      </template>
      
      <style lang="scss">
      </style>
      

      During the inital setup, you selected the Sass/SCSS (with node-sass) option. This is why you added on the lang="scss" attribute to your style tag. If you are unfamiliar with SCSS, it’s recommended to view their official documentation for specifics on when to use nesting or variables.

      This lang attribute will give you the ability to write SCSS in your single-file component. Add the following highlighted contents in the style element:

      vue-starter-project/src/components/AppHeader.vue

      ...
      <style lang="scss">
        header {
          display: flex;
          border-bottom: 1px solid #ccc;
          padding: .5rem 1rem;
      
          p {
            margin-left: 1rem;
          }
        }
      
        nav {
          margin-left: auto;
      
          ul {
            list-style: none;
          }
      
          ul li {
            display: inline-flex;
            margin-left: 1rem;
          }
        }
      </style>
      

      This SCSS creates a horizontal navigation bar with declarations such as display: inline-flex (using Flexbox) and spaces each item out with margin-left auto. To separate the header from the rest of the content, some padding is applied with padding: .5rem 1rem along with a bottom border using border-bottom: 1px solid #ccc. You may notice that the p styles are inside of the header SCSS block. In traditional CSS, that is not allowed, but thanks for SCSS, you can do that. This is refered to as nesting. In this case, the p inside the header is the same as selecting header p in traditional CSS.

      Save your file and navigate to localhost:8080 in your browser to find the new style:

      New style for header in Vue template

      You now have created and styled your header component. Next, you will create the footer component.

      Now that you have a header, you will complete your example application with a footer. In the same components directory, create a new file with the name AppFooter.vue. The process of creating this component is the same as creating the AppHeader.vue. You can create the file in your editor or through the touch base command.

      touch src/components/AppFooter.vue
      

      As before, import this into your App.vue file. Open up App.vue and add the following highlighted code:

      vue-starter-project/src/App.vue

      <template>
        <app-header />
        <router-view/>
        <app-footer />
      </template>
      
      <script>
      import AppHeader from '@/components/AppHeader.vue'
      import AppFooter from '@/components/AppFooter.vue'
      
      export default {
        components: {
          AppHeader,
          AppFooter
        }
      }
      </script>
      ...
      

      This time, you’re importing the component after the router-view tag.

      Save the file, then open up AppFooter.vue. In your AppFooter.vue file, use the <footer> HTML tag with a paragraph:

      vue-starter-project/src/components/AppFooter.vue

      <template>
        <footer>
          <p>Copyright &copy; "current year" </p>
        </footer>
      </template>
      

      You now have a basic footer. Continue to expand on this to include the current year programmatically. This will be dynamic depending on what the year is. To achieve this, you will create a computed property. A computed property is a reactive value calculated with JavaScript.

      In Vue 3, you need to wrap your properties in the setup() function and return these values. Essentially, you are telling Vue to construct this component and provide the template to these reactive computed properties.

      To create a computed property, you’ll first need to deconstruct the computed function from the vue library. You will store this computed function and its value into a const. In Vue 3, you need to pass an anonymous function that returns a value:

      const year = computed(() => new Date().getFullYear())
      

      To add the setup function to your file, add the following script to the end of AppFooter.vue:

      vue-starter-project/src/components/AppFooter.vue

      ...
      <script>
      import { computed } from 'vue'
      
      export default {
        setup () {
          const year = computed(() => new Date().getFullYear())
        }
      }
      </script>
      

      After that, you will need to provide access to the computed property you created for the <template> to consume and render. Return an object with the year property and value in your setup() function:

      /vue-starter-project/src/components/AppFooter.vue

      ...
      setup () {
        const year = computed(() => new Date().getFullYear())
        return { year }
      }
      ...
      

      To use this value in the <template>, use interpolation with double curly braces. This is sometimes referred to the “moustache syntax”:

      /vue-starter-project/src/components/AppFooter.vue

      <template>
        <footer>
          <p>Copyright &copy; {{ year }}</p>
        </footer>
      </template>
      

      Save the file. You will now have the current year in your footer:

      Sample vue application with a computed header

      Conclusion

      In this tutorial, you downloaded the Vue CLI and created your own single-file components with AppHeader.vue and AppFooter.vue. You successfully generated a Vue.js Single Page Application (SPA) with selected features from the initial setup, and learned how all of those pieces come together. In addition, you’ve now reviewed the basic architecture of most SPAs and can use that knowledge to futher expand this project.

      Vue.js is a growing ecosystem with a number of tools at your disposable. These tools can help you quickly get started and save time by storing options as a preset. This is just the start of what Vue.js has to offer, but the CLI is perhaps one of the most important tools you will use in your Vue.js journey.

      For more information on Vue.js and Vue CLI 3, it’s recommended to read through their documentation. The CLI tool specifically has many additional features that weren’t covered in this tutorial. For more tutorials on Vue, check out the Vue Topic Page.



      Source link