Vue.js 3 Cookbook
上QQ阅读APP看书,第一时间看更新

Creating a component using the composition API

The composition API is a new way to write Vue components, based on the use of functions to compose the component, and it makes the organization and reusability of the code better.

This method is inspired by React Hooks and introduces the technique of creating a special function to compose the applications that can be shared without the need to be inside the Vue application because of the use of the exposed Vue APIs.

In this recipe, we will learn how to create an external function that fetches the user's geolocation and displays that data on the screen using the composition API.

How to do it...

Here, we will create a component using the composition API, which will fetch the user GPS position and show that information on the screen:

  1. Using the base example from the 'Creating the base file' section, create a new file named component.html and open it.
  2. In the empty <script> HTML element, create the constants of the functions that will be used using the object destructuring method, calling the createApp, defineComponent, setup, ref, onMounted, and onUnmounted methods from the Vue global constant:
const {
createApp,
defineComponent,
setup,
ref,
onMounted,
onUnmounted,
} = Vue;
  1. Create a fetchLocation function and, inside this, create a let variable named watcher. Then, create a constant named geoLocation and define it as navigator.geolocation. Next, create a constant named gpsTime and define it as the ref function, passing the Date.now() function as the argument. Finally, create a constant named coordinates and define it as the ref function, passing a JavaScript object as the argument, with the properties accuracy, latitude, longitude, altitude, altitudeAccuracy, heading, and speed defined as 0:
function fetchLocation() {
let watcher;
const geoLocation = navigator.geolocation;
const gpsTime = ref(Date.now());
const coordinates = ref({
accuracy: 0,
latitude: 0,
longitude: 0,
altitude: 0,
altitudeAccuracy: 0,
heading: 0,
speed: 0,
});
}
  1. Then, inside the fetchLocation function, following the creation of the constants, create a function named setPosition with a parameter named payload. Inside the function, define gpsTime.value as the payload.timestamp argument and coordinates.value as the payload.coords argument:
function setPosition(payload) {
gpsTime.value = payload.timestamp
coordinates.value = payload.coords
}
  1. Following creation of the setPosition function, call the onMounted function, passing an anonymous function as the argument. Inside the function, check whether the browser has the geoLocation API available, and define watcher as the geoLocation.watchPostion function, passing the setPosition function as the argument:
onMounted(() => {
if (geoLocation) watcher = geoLocation.watchPosition(setPosition);
});
  1. After calling the onMounted function, create an onUnmounted function passing an anonymous function as the argument. Inside the function, check whether watcher is defined and then execute the geoLocation.clearWatch function, passing watcher as the argument:
onUnmounted(() => {
if (watcher) geoLocation.clearWatch(watcher);
});
  1. Finally, in the fetchLocation function, return a JavaScript object, and as the properties/values define, pass the coordinates and gpsTime constants:
return {
coordinates,
gpsTime,
};
  1. Create a constant named appComponent and define it as the defineComponent function, passing a JavaScript object with the properties setup and template as the argument:
const appComponent = defineComponent({
setup() {},
template: ``
});
  1. In the setup function, create a constant, which is an object destructuring with the properties coordinates and gpsTime of the fetchLocation function:
setup() {
const {
coordinates,
gpsTime,
} = fetchLocation();
}
  1. Inside the setup function, create another constant named formatOptions, and define it as a JavaScript object with the properties yearmonthdayhour, and minute as 'numeric'. Then, define the property hour12 as true:
const formatOptions = {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
hour12: true,
};
  1. Following the creation of the formatOptions constant, create a constant named formatDate and define it as a function, which receives a parameter named date. Then, return a new Intl.DateTimeFormat function, passing navigator.language as the first argument, and the formatOption constant as the second argument. Then, prototype chain the format function, passing the date parameter:
const formatDate = (date) => (new 
Intl.DateTimeFormat(navigator.language,
formatOptions).format(date));
  1. Finally, at the end of the setup function, return a JavaScript object with the properties defined as coordinatesgpsTime, and formatDate constants:
return {
coordinates,
gpsTime,
formatDate
};
  1. In the template property, do the following:
    • Create an h1 HTML element with the text "My Geo Position at {{ formatDate(new Date(gpsTime) }}".
    • Create a ul HTML element and add three li HTML elements as children.
    • In the first child element, add the text "Latitude: {{ coordinates.latitude }}".
    • In the second child element, add the text "Longitude: {{ coordinates.longitude }}".
    • In the third child element, add the text "Altitude: {{ coordinates.altitude }}":
template: `
<h1>My Geo Position at {{formatDate(new
Date(gpsTime))}}</h1>
<ul>
<li>Latitude: {{ coordinates.latitude }}</li>
<li>Longitude: {{ coordinates.longitude }}</li>
<li>Altitude: {{ coordinates.altitude }}</li>
</ul>
`
  1. Finally, call the createApp function, passing the appComponent constant as an argument. Then, prototype chain the mount function, and, as an argument of the function, pass the div HTML element id attribute, ("#app"):
createApp(appComponent)
.mount('#app');

How it works...

In this recipe, first, we imported the exposed APIs - createApp,  defineComponentsetuprefonMounted, and onUnmounted, – as constants, which we will use to create the component. Then, we created the fetchLocation function, which has the responsibility of getting the user's geolocation data and returning it as reactive data that can be automatically updated when the user changes their location.

The ability to fetch the user GPS positions was possible because of the navigator.geolocation API present on modern browsers, which are able to fetch the user's current GPS position. Using this data provided by the browser, we were able to use it to define the variables created with the Vue ref APIs.

We created the component using the setup function of the Vue object declaration, so the rendering knows that we are using the new composition API as the component creation method. Inside the setup function, we imported the dynamic variables of the fetchLocation function and created a method that formats the date to use as a filter on the template.

Then we returned the imported variables and the filter, so they can be used on the template section. In the template section, we created a title adding the time of the last GPS position, used the filter to format it, and created a list of the user's latitude, longitude, and altitude.

Finally, we created the application using the createApp exposed API and mounted the Vue application.

See also

You can find more information about Navigator.geolocation at https://developer.mozilla.org/en-US/docs/Web/API/Navigator/geolocation.

You can find more information about Intl.DateTimeFormat at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat.