6

Building a Apps with Vue 3

 4 years ago
source link: https://morioh.com/p/d5f7657ee12d?f=5c22e47440738156a7078a19
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Building a simple Applications with Vue 3

60fca23c22c4.jpg

In this Vue.js 3 Tutorial, I'll walk you through the creation of a simple app using an alpha version of Vue 3, with the specific intention of highlighting new features of Vue 3

Vue.js 3 has not officially been released yet, but the maintainers have released experimental "alpha" versions. These cannot be used in production apps, but are great for you to try out and learn some of the new features.

The only problem is that the Vue docs haven't been updated for version 3, so it takes a bit of digging around to figure out exactly what's different.

In this article, I'll walk you through the creation of a simple app using an alpha version of Vue 3, with the specific intention of highlighting new features.

Note that this article is current for alpha version 8. Some of the syntax shown could change in later versions.

Should you wait for the v3 release before learning Vue?

If you're new to Vue.js, you'll need to start by learning version 2, as that is presumed knowledge for this tutorial.

However, don't feel like you're wasting your time learning Vue 2 when Vue 3 is on the horizon. While some APIs will be added or changed, almost all of the key features and patterns of Vue 2 will still be used in Vue 3.

Table of contents:

  • Vue 3 installation and setup
  • Creating a new Vue app
  • Adding state properties
  • Using a root component
  • Creating a template
  • Composition API

Vue 3 installation and setup

Rather than installing Vue 3 directly, let's clone the project vue-next-webpack-preview which will give us a minimal Webpack setup including Vue 3.

$ git clone https://github.com/vuejs/vue-next-webpack-preview.git vue3-experiment
$ cd vue3-experiment
$ npm i

Once that's cloned and the NPM modules are installed, all we need to do is remove the boilerplate files and create a fresh main.js file so we can create our Vue app from scratch.

$ rm -rf src/*
$ touch src/main.js

Now we'll run the dev server:

$ npm run dev

Creating a new Vue app

Straight off the bat, the way we bootstrap a new Vue app has changed. Rather than using new Vue() , we now need to import the new createApp method.

We then call this method, passing our Vue instance definition object, and assign the return object to a variable app .

Next, we'll call the mount method on app and pass a CSS selector indicating our mount element, just like we did with the $mount instance method in Vue 2.

main.js

import { createApp } from "vue";

const app = createApp({
  // root instance definition
});

app.mount("#app");

Reason for change

With the old API, any global configuration we added (plugins, mixins, prototype properties etc) would permanently mutate global state . For example:

main.js

// Affects both instances
Vue.mixin({ ... })

const app1 = new Vue({ el: '#app-1' })
const app2 = new Vue({ el: '#app-2' })

This really shows up as an issue in unit testing, as it makes it tricky to ensure that each test is isolated from the last.

Under the new API, calling createApp returns a fresh app instance that will not be polluted by any global configuration applied to other instances.

Adding state properties

In this tutorial, we'll create a classic "counter" app that allows a user to click a button to increment a displayed integer.

So let's add a new state property count which we'll give an initial value of 0 .

Under Vue 2, we could do this by creating a data property on our app instance and assigning an object to this where our count property would be declared i.e.:

main.js

const app = createApp({
  data: {
    count: 0
  }
});

This is no longer allowed. Instead, data must be assigned a factory function which returns the state object .

This is what you had to do for Vue components, but now it's enforced for Vue app instances as well.

main.js

const app = createApp({
  data: () => ({
    count: 0
  })
});

Reason for change

The advantage of using an object for data rather than a factory function is that, firstly, it was syntactically simpler, and secondly, you could share top-level state between multiple root instances e.g.:

main.js

const state = {
  sharedVal: 0
};

const app1 = new Vue({ state });
const app2 = new Vue({ state });

// Affects both instances
app1._data.sharedVal = 1;

The use case for this is rare and can be worked around. Since having two types of declarations is not beginner-friendly, it was decided to remove this feature.

Before we move on, let's also add a method to increment the count value. This is no different from Vue 2.

main.js

const app = createApp({
  data: () => ({
    count: 0  
  }),
  methods: {
    inc() {
      this.count++;
    }
  }
});

Using a root component

If you go to the browser now and check the console, you'll see the warning "Component is missing render function", since we haven't yet defined a template for the root instance.

The best practice for Vue 2 is to create a minimal template for the root instance and create an App component where the main app markup will be declared.

Let's do that here, as well.

$ touch src/App.vue

Now we can get the root instance to render that component. The difference is that with Vue 2, we'd normally use a render function for doing this:

main.js

import App from "./App.vue";

const app = createApp({
  ...
  render: h => h(App)
});

app.mount("#app");

We can still do that, but Vue 3 has an even easier way - making App a root component . To do this, we can remove the root instance definition and instead pass the App component.

main.js

import App from "./App.vue";

const app = createApp(App);

app.mount("#app");

This means the App component is not just rendered by the root instance but is the root instance.

While we're at it, let's simply the syntax a little by removing the app variable:

main.js

createApp(App).mount("#app");

Moving over to the root component now, let's re-add the state and method to this component:

App.vue

<script>
export default {
  data: () => ({
    count: 0  
  }),
  methods: {
    inc() {
      this.count++;
    }
  }
};
</script>

Creating a template

Let's now create a template for our root component. We'll use a text interpolation to display the count, and we'll add a button with a click handler to increment our counter.

App.vue

<template>
  <span>Button clicked {{ count }} times.</span>
  <button @click="inc">Inc</button>
</template>
<script>
...
</script>

Notice anything odd about this template? Look again. I'll wait.

That's right - there are two root elements. In Vue 3, thanks to a feature called fragments , it is no longer compulsory to have a single root element.

Composition API

The flagship feature of Vue 3 is the Composition API . This new API allows you to define component functionality using a setup function rather than with properties you add to the component definition object.

Let's now refactor our App component to use the Composition API.

Before I explain the code, be clear that all we're doing is refactoring - the functionality of the component not changed at all. Also note that the template is not changed as the Composition API only affects the way we define the component functionality, not the display.

App.vue

<template>
  <span>Button clicked {{ count }}</span>
  <button @click="inc">Inc</button>
</template>
<script>
import { ref } from "vue";
export default {
  setup () {
    const count = ref(0);
    const inc = () => {
      count.value++;
    };
    return {
      count,
      inc
    }
  }
};
</script>

setup method

Firstly, notice we import the ref function which allows us to define a reactive variable count . This variable is equivalent to this.count .

The inc method is just a plain JavaScript function. However, notice that to change the value of count in the method body, we need to change its sub-property value . That's because reactive variables created using ref are wrapped in an object. This is necessary to retain their reactivity as they're passed around.

Finally, we return count and increment from the setup method, as these are the values that get passed to the template when it's rendered.

Reason for change

Keep in mind that the Composition API is not a change as it's purely optional to use. The main motivation is to allow for better code organization and the reuse of code between components (as mixins are essentially an anti-pattern).

You'd be correct in thinking that refactoring the App component to use the Composition API is unnecessary. But, if this were a much larger component, or we needed to share its features with other components, that's when you'd see its usefulness.

Angular 9 Tutorial: Learn to Build a CRUD Angular App Quickly

What's new in Bootstrap 5 and when Bootstrap 5 release date?

What’s new in HTML6

How to Build Progressive Web Apps (PWA) using Angular 9

What is new features in Javascript ES2020 ECMAScript 2020

Vue vs. React: Why I choose Vue.js

f26b9e3b96bb.jpg

Vue.js is a great framework but so is React. So why did I choose to go to Vue.js rather than React? In this video I discuss why I think Vue.js is the better option over React.

Vue.js is a great framework but so is React. So why did I choose to go to Vue rather than React? In this video I discuss why I think Vue.js is the better option over React.

Getting Started with Vue Router - Create a simple SPA in Vue

9ac81eb34d14.jpg

In this Vue.js tutorial, how easy it is to get started with Vue Router and we'll setup a simple SPA that will show some information about popular cryptocurrencies. We'll call it "Crypto Info". It will have a few pages and link those pages using vue-router.

Vue is already a great Javascript library that allows you to create some really cool, dynamic, front-end applications. Vue is also great for single page applications (SPA). SPAs work a little differently that your standard backend web application built in something like PHP. Instead of making requests to different routes on the backend and getting a fully rendered page as a response, a SPA does all the page rendering on the front-end and only sends requests to the server when new data is needed or needs to be refreshed or saved.

This can improve the responsiveness of your web application because you can render the pages once and display them dynamically based on the current context of the application. In order to make this work, you need a way to distinguish the different views or pages from eachother. In SPAs this is done with a router. Luckily Vue has a fully supported first-party router library called vue-router.

In this tutorial we'll setup a simple SPA that will show some information about popular cryptocurrencies. We'll call it "Crypto Info". It will have a few pages and link those pages using vue-router. You should already be familiar with Vue as well as creating and using Vue components. Having experience with .vue files is helpful but not required.

Setup

To get started, let's use the handy Vue command line installer. Open a terminal and run the following.

# install vue-cli
$ npm install --global vue-cli
# create a new project using the "webpack" template
$ vue init webpack router-app

When prompted, answer the questions displayed on the screen like so. Make sure to answer "yes" for installing vue-router.

This will install Vue 2.x version of the template.

 For Vue 1.x use: vue init webpack#1.0 router-app

? Project name router-app <Enter>
? Project description A Vue.js project  <Enter>
? Author  <Enter>
? Vue build standalone  <Enter>
? Install vue-router? Yes
? Use ESLint to lint your code? No
? Setup unit tests with Karma + Mocha? No
? Setup e2e tests with Nightwatch? No

Once the app is setup, install all the dependencies and start up a dev server.

# install dependencies and go!
$ cd router-app
$ npm install
$ npm run dev

You should now be able to point a browser at http://localhost:8080 and see something like this.

viiEBvM.png!web

Digging In

The great thing about the Vue command line tool is that it will wire up vue-router for us. To get a better understanding of how it works, we can take a look the boilerplate that was created. Open /src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello
    }
  ]
})

The first two lines are importing vue and vue-router. The third line is importing a component called Hello. We will discuss why in a bit. The @ is just a nice alias for the /src directory that was setup in webpack by the Vue command line tool.

Next we tell Vue to use the vue-router plugin. Finally the router is configured with a single route. The router uses Vue components as pages. In the above example we want to render the Hello component whenever a user navigates to the / route.

Next open /src/main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})

The first line is importing Vue again. The second line is bringing in a component called App . This will serve as the root component for the application. The third line is importing the router setup we looked at earlier. The next line tells Vue whether or not to show tips and warnings in the developer console of your browser. In this case it is set to false.

Finally a new Vue instance is created and mounted to the #app div in our html and then it instantiated the App component. We also inject the router configuration from earlier.

Now open /src/App.vue

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-view></router-view>
  </div>
</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;
}
</style>

This, like I mentioned before, is the root component. It will serve as the point from which our page components will be rendered. Note that all the components we will use are in .vue files which allows us to save the template, javascript and styling into a single file.

Within the <template> tag we just have some simple markup. The important piece though is the <router-view> tag. The router uses this tag as a container for rendering the different components tied to the different routes. Just think of it as a placeholder.

The <script> tag just contains a simple Vue component object that does nothing. The <style> tag just contains some nice styling boilerplate provided by the Vue command line tool.

Now open /src/components/Hello.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>Essential Links</h2>
    <ul>
      <li><a href="https://vuejs.org" target="_blank">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li>
      <li><a href="https://gitter.im/vuejs/vue" target="_blank">Gitter Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li>
      <br>
      <li><a href="http://vuejs-templates.github.io/webpack/" target="_blank">Docs for This Template</a></li>
    </ul>
    <h2>Ecosystem</h2>
    <ul>
      <li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>
      <li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>
      <li><a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'hello',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: inline-block;
  margin: 0 10px;
}

a {
  color: #42b983;
}
</style>

This is very similar to the App component. Again, within the <template> tag there is the HTML markup for the component. In this case it's all the links and text shown when we pointed our browser to http://localhost:8080 . This is because in our router config, we specified that / or the root path of our application should point to Hello.vue .

Now let's get rid of the default content and create a simpler home page. Edit Hello.vue to look like the following:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
  export default {
    name: 'Hello',
    data () {
      return {
        msg: 'Welcome to Crypto Info'
      }
    }
  }
</script>

If you reload, you should now see a page like this.

rIF7Rz6.png!web

Creating and Linking to Routes

Now let's create a new page and add some links for navigating between the two. Open /src/router/index.js and edit it to look like the following.

import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'
import About from '@/components/About'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello
    },
    {
      path: '/about',
      name: 'About',
      component: About
    }
  ]
})

We've added a new route /about that points to a new component called About . We've also imported the new component at the top. We will create this shortly.

Now open /src/App.vue and edit the <template> section to look like this.

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-link :to="{ name: 'Hello' }">Home</router-link>
    <router-link to="/about">About</router-link>
    <router-view></router-view>
  </div>
</template>

As you can see, we added two <router-link> tags using two different methods. The router uses <router-link> to create html links to routes you created. The first method uses a named route. If you recall, in /src/router/index.js we added the name parameter to our routes. In this case the name of the route is Hello just like the component it points to. The second method is the standard method and just specifies the path we want to link to.

If you refresh the browser, you should see the original welcome page but with two links added.

m2ABJjZ.png!web

If you click the About link, you will get a blank page. This is because we haven't created the component yet. Let's fix this be creating /src/components/About.vue .

<template>
  <div class="about">
    <h1>What is a Crypto-Currency?</h1>
    <p>
      It's a digital currency in which encryption techniques are used to regulate the generation of units of currency 
      and verify the transfer of funds, operating independently of a central bank.
    </p>
  </div>
</template>

<script>
export default {
  name: 'About'
}
</script>

Now if you refresh the browser and click About you should see the new page.

jQVr22Y.png!web

Dynamic Routes

So we can create a new page and a route to point to it but what about passing parameters? We'll need a page that displays some useful info about various crypto currencies based on a string id passed in the URL. Let's make that happen. Open /src/router/index.js again and add a third route.

...
import Coins from '@/components/Coins'

...

export default new Router({
  routes: [
    ...
   {
      path: '/coins/:id',
      name: 'Coins',
      component: Coins
    }
  ]
})

In order to display up-to-date information on the various currencies, we'll use the popular axios http client to fetch data from the free Coin Market Capitalization API. We'll accept a string parameter in the URL called :id . This will be passed to the API to retrieve the relevant data.

First we need to install axios.

npm install --save axios

Next create a file called /src/components/Coins.vue

<template>
  <div>
    <p>Name: {{ coin.name }}</p>
    <p>Symbol: {{ coin.symbol }}</p>
    <p>Price (USD): {{ coin.price_usd }}</p>
  </div>
</template>
<script>
  import axios from 'axios'

  export default {
    name: 'Coins',

    data() {
      return {
        coin: {}
      }
    },

    created() {
      this.fetchData()
    },

    watch: {
      '$route': 'fetchData'
    },

    methods: {
      fetchData() {
        axios.get('https://api.coinmarketcap.com/v1/ticker/'+this.$route.params.id+'/')
        .then((resp) => {
          this.coin = resp.data[0]
          console.log(resp)
        })
        .catch((err) => {
          console.log(err)
        })
      }
    }
  }
</script>

You'll notice that in the data object of our component, we declare an empty object called coin . This will store our coin information after it is fetched. In the <template> section we have some markup to display the name, symbol and US dollar price of the coin. The created method is a special hook used by Vue that is called before the component is rendered. In this case we are calling the fetchData method which is making a GET request with axios to the Coin Market Capitalization API and passing the :id parameter at the end.

We get the parameter from the $route object params property. This object is auto injected by VueRouter. The paramater we want is the :id parameter which we defined in our router file. On success, as defined in the the then promise method, we save the data returned into our coin object. This is then rendered on in the template.

One other thing we need is to add a watch hook for the $route object. VueRouter components are only rendered once for speed. If you need to rerender, you need to do that manually so in this case we want to rerender when the :id parameter in $route changes and then fetch new data.

Now lets create a few more links in /src/App.vue to see how this new page might be used.

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-link :to="{ name: 'Hello' }">Home</router-link>
    <router-link to="/about">About</router-link>
    <router-link to="/coins/ethereum">Ethereum</router-link>
    <router-link to="/coins/bitcoin">Bitcoin</router-link>
    <router-view></router-view>
  </div>
</template>

If you refresh the browser and click on Ethereum you should see something like this.

naMjiqm.png!web

Now click on Bitcoin and you should see relevant information for that coin as well. If you want to try out other coins, have a look at https://api.coinmarketcap.com/v1/ticker/ and paste a few ids from the list into the URL of our app.

Conclusion

That's how easy it is to get started with Vue Router. There are a bunch of other great features as well and you can read about them in the official documentation. I hope this tutorial is enough to get you started making some cool SPAs in Vue!

Hello Vue 3: A First Look at Vue 3 and the Composition API

6684429beade.jpg

Vue 3 will be released in 2020 and it'll add one pretty neat nice feature: The Composition API. Time for a first look at Vue 3 and introduction to this new, optional way of writing your Vue components!

Vue 3 will be released in 2020 and it'll add one pretty neat nice feature: The Composition API. Time for a first look at Vue 3 and introduction to this new, optional way of writing your Vue components!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK