The very first alpha version of Vue 3 is released! There are a lot of exciting features coming with version 3: Vue exposes its reactivity system behind the new Composition API. If you haven't heard about it, I recommend reading the RFC describing it. At first, I was a bit skeptical, but looking at React's Hooks API, which is a bit similar, I decided to give it a shot.
In this article, we will be building a movie search application using the Composition API. We won't be using object-based components. I will explain how the new API works and how can we structure the application.
When we finish, we will see something similar to this:
The application will be able to search for movies via the Open Movie Database API and render the results. The reason for building this application is that it is simple enough not to distract the focus from learning the new API but complex enough to show it works.
If you are not interested in the explanations, you can head straight to the source code and the final application.
Setting up the project
For this tutorial, we will be using the Vue CLI, which can quickly generate the necessary environment.
npm install -g @vue/cli
vue create movie-search-vue
cd movie-search-vue
npm run serve
Our application is now running on http://localhost:8080 and looks like this:
Here you can see the default folder structure:
If you don't want to install all the dependencies on your local computer, you can also start the project on Codesandbox. Codesandbox has perfect starter projects for the most significant frameworks, including Vue.
Enabling the new API
The generated source code uses Vue 2 with the old API. To use the new API with Vue 2, we have to install the composition plugin.
npm install @vue/composition-api
After installing, we have to add it as a plugin:
import Vue from 'vue';
import VueCompositionApi from '@vue/composition-api';
Vue.use(VueCompositionApi);
The composition plugin is additive: you can still create and use components the old way and start using the Composition API for new ones.
We will have four components:
- App.vue: The parent component. It will handle the API calls and communicate with other components.
- Header.vue: A basic component that receives and displays the page title
- Movie.vue: It renders each movie. The movie object is passed as a property.
- Search.vue: It contains a form with the input element and the search button. It gives the search term to the app component when you submit the form.
Creating components
Let's write our first component, the header:
<template>
<header class="App-header">
<h2>{{ title }}</h2>
</header>
</template>
<script>
export default {
name: 'Header',
props: ['title'],
setup() {}
}
</script>
Component props
are declared the same way. You name the variables that you expect from the parent component as an array or object. These variables will be available in the template({{ title }}
) and in the setup
method.
The new thing here is the setup
method. It runs after the initial props
resolution. The setup
method can return an object and the properties of that object will be merged onto the template context: it means they will be available in the template. This returned object is also the place for placing the lifecycle callbacks. We will see examples for this in the Search component.
Let's take a look at the Search component:
<template>
<form class="search">
<input
type="text"
:value="movieTitle"
@keyup="handleChange"
/>
<input @click="handleSubmit" type="submit" value="SEARCH" />
</form>
</template>
<script>
import { ref } from '@vue/composition-api';
export default {
name: 'Search',
props: ['search'],
setup({ search }, { emit }) {
const movieTitle = ref(search);
return {
movieTitle,
handleSubmit(event) {
event.preventDefault();
emit('search', movieTitle.value);
},
handleChange(event) {
movieTitle.value = event.target.value
}
}
}
};
</script>
The Search component tracks keystrokes and stores the input's value on a variable. When we are finished and push the submit button, it emits the current search term up to the parent component.
The setup
method has two parameters.
The first argument is the resolved props
as a named object. You can use object destructuring to access its properties. The parameter is reactive, which means the setup
function will run again when the input properties change.
The second argument is the context object. Here you can find a selective list of properties that were available on this
in the 2.x API (attrs
, slots
, parent
, root
, emit
).
The next new element here is the ref
function. The ref
function exposes Vue's reactivity system. When invoked, it creates a reactive mutable variable that has a single property value
. The value
property will have the value of the argument passed to the ref
function. It is a reactive wrapper around the original value. Inside the template we won't need to reference the value
property, Vue will unwrap it for us. If we pass in an object, it will be deeply reactive.
Reactive means when we modify the object's value (in our case the value
property), Vue will know that the value has changed, and it needs to re-render connected templates and re-run watched functions.
It acts similar to the object properties returned from the data
method.
data: function() {
return { movieTitle: 'Joker' };
}
Gluing it together
The next step is to introduce the parent component for the Header and Search component, the App component. It listens for the search event coming from the Search component, runs the API when the search term changes, and passes down the found movies to a list of Movie components.
<template>
<div class="App">
<Header :title="'Composition API'" />
<Search :search="state.search" @search="handleSearch" />
<p class="App-intro">Sharing a few of our favourite movies</p>
<div class="movies">
<Movie v-for="movie in state.movies" :movie="movie" :key="movie.imdbID" />
</div>
</div>
</template>
<script>
import { reactive, watch } from '@vue/composition-api';
import Header from './Header.vue';
import Search from './Search.vue';
import Movie from './Movie.vue';
const API_KEY = 'a5549d08';
export default {
name: 'app',
components: {
Header, Search, Movie
},
setup() {
const state = reactive({
search: 'Joker',
loading: true,
movies: [],
errorMessage: null
});
watch(() => {
const MOVIE_API_URL = `https://www.omdbapi.com/?s=${state.search}&apikey=${API_KEY}`;
fetch(MOVIE_API_URL)
.then(response => response.json())
.then(jsonResponse => {
state.movies = jsonResponse.Search;
state.loading = false;
});
});
return {
state,
handleSearch(searchTerm) {
state.loading = true;
state.search = searchTerm;
}
};
}
}
</script>
We introduce here two new elements: reactive
and watch
.
The reactive
function is the equivalent of Vue 2's Vue.observable()
.
It makes the passed object deeply reactive: takes the original object and wraps it with a proxy (ES2015 Proxy-based implementation). On the objects returned from reactive
we can directly access properties instead of values returned from the ref
function where we need to use the value
property. If you want to search for equivalents in the Vue 2.x API, the data
method would be the exact match.
One shortcoming of the reactive
object is that we can not spread it into the returned object from the setup
method.
The watch
function expects a function. It tracks reactive variables inside, as the component does it for the template. When we modify a reactive variable used inside the passed function, the given function runs again. In our example, whenever the search term changes, it fetches the movies matching the search term.
One component is left, the one displaying each movie record:
<template>
<div class="movie">
<h2>{{ movie.Title }}</h2>
<div>
<img width="200" :alt="altText" :src="movie.Poster" />
</div>
<p>{{ movie.Year }}</p>
</div>
</template>
<script>
import { computed } from '@vue/composition-api';
export default {
name: "Movie",
props: ['movie'],
setup({ movie }) {
const altText = computed(() => `The movie titled: ${movie.Title}`);
return { altText };
}
};
</script>
The Movie component receives the movie to be displayed and prints its name along with its image. The exciting part is that for the alt
field of the image we use a computed text based on its title.
The computed
function gets a getter function and wraps the returned variable into a reactive one. The returned variable has the same interface as the one returned from the ref
function. The difference is that it's readonly. The getter function will run again when one of the reactive variables inside the getter function change. If the computed
function returned a non-wrapped primitive value, the template wouldn't be able to track dependency changes.
Cleaning up components
At this moment, we have a lot of business logic inside the App component. It does two things: handle the API calls and its child components. The aim is to have one responsibility per object: the App component should only manage the components and shouldn't bother with API calls. To accomplish this, we have to extract the API call.
import { reactive, watch } from '@vue/composition-api';
const API_KEY = 'a5549d08';
export const useMovieApi = () => {
const state = reactive({
search: 'Joker',
loading: true,
movies: []
});
watch(() => {
const MOVIE_API_URL = `https://www.omdbapi.com/?s=${state.search}&apikey=${API_KEY}`;
fetch(MOVIE_API_URL)
.then(response => response.json())
.then(jsonResponse => {
state.movies = jsonResponse.Search;
state.loading = false;
});
});
return state;
};
Now the App component shrinks only to handle the view related actions:
import Header from './Header.vue';
import Search from './Search.vue';
import Movie from './Movie.vue';
import { useMovieApi } from '../hooks/movie-api';
export default {
name: 'app',
components: { Header, Search, Movie },
setup() {
const state = useMovieApi();
return {
state,
handleSearch(searchTerm) {
state.loading = true;
state.search = searchTerm;
}
};
}
}
And that's it; we finished implementing a little application with the new Composition API.
Wrapping it up
We have come a long way since generating the project with Vue CLI. Let's wrap it up what we learned.
We can use the new Composition API with the current stable Vue 2 version. To accomplish this, we have to use the @vue/composition-api
plugin. The API is extensible: we can create new components with the new API along with old ones, and the existing ones will continue to work as before.
Vue 3 will introduce many different functions:
-
setup
: resides on the component and will orchestrate the logic for the component, runs after initialprops
resolution, receivesprops
and context as an argument -
ref
: returns a reactive variable, triggers re-render of the template on change, we can manipulate its value through thevalue
property. -
reactive
: returns a reactive object (proxy-based), triggers re-render of the template on reactive variable change, we can modify its value without thevalue
property -
computed
: returns a reactive variable based on the getter function argument, tracks reactive variable changes and re-evaluates on change -
watch
: handles side-effects based on the provided function, tracks reactive variable changes and re-runs on change
I hope this example has made you familiar with the new API and removed your skepticism as it did with me.
Top comments (86)
Thank you for writing and explaining things.
Now we're tracking the change with
handleChange()
function. As we use to do in React. What aboutv-model
approach here? Can we use it with composition API? Correct me if I am wrongI'm a bit late to the party - as I just started using the composition API myself - but it's definitely possible to use
v-model
, as before.Just remember to set the variable you wish to assign to
v-model
in thesetup()
function, using aref()
. As inconst newMovieName = ref('');
and usev-model="newMovieName"
.apkzar.com/kinemaster-mod/ kinemastermod apk
The function is called as an event handler and the
searchTerm
comes from the data passed toemit
. I have tried out the application on Codesandbox and it is working.Am I missing something?
You're right. I misread the definition.
awesome composition api of vue, and you can also try concent composition api for react!
here is an online example: stackblitz.com/edit/concent-regist...
more details see github.com/concentjs/concent
hope you like it, concent is a predictable、zero-cost-use、progressive、high performance's enhanced state management solution for react _^
Interesting solution, definitely an eye-catcher
thx _, concent is born for react, and power react from inside to outside.
1 predictable:
concent take over react.setState, and dispatch feature is base on setState, so every state changing behavior is predictable, no matter use setState or dispatch
see demo below:
stackblitz.com/edit/cc-zero-cost-use
2 zero-cost-use:
cause setState can be interactive with store, so you can use concent by register api on your classical react class writing without changing any code.
see demo below:
stackblitz.com/edit/cc-course-hell...
3 progressive
you can separate your business logic code to reducer from class later. it will keep your view clean.
see demo below:
stackblitz.com/edit/cc-multi-ways-...
4 high performance
with watchedKeys, renderKey, lazyDispatch, delayBroadcast features, concent render every view block only when it really need to been re-rendered
see watchedKeys demo:
stackblitz.com/edit/concent-watche...
see renderKey demo:
stackblitz.com/edit/concent-todoli...
5, enhance react
computed, watch, effect, setup and etc... both of them are designed for react honestly
see demo below:
stackblitz.com/edit/hook-setup
because concent is quick new, so very less people know it, hope u can try it and give me feedback.
by the way: my en is not good, wish u understand what I said_^
If destructured, won't be reactivity of
props
parameter lost? I think it can be the case as soon as your props get updated.Similar to the case where you destructure the a
reactive
object instead of usingtoRefs
?Normally. as far as I understand the whole concept, you must wrap with
toRefs
a value, which you want to spread or destructure in order to retain its reactivity.And in case of props, which you pass as parameter to
setup()
you can't use destructuring inside function signature, e.gsetup({name})
, because as soon as thename
prop will be updated, you end up with its old value due to lost of reactivity. Destructuring is supported only for properties ofcontext
, so I suppose this should work:setup(props, {attrs, emit})
.Great topic. Have you heard of pest control software? This is the best application that I have ever met on the phone. Because I have not yet met such a functional business application.
There are many movie apps like firmwarexbd, Hulu, but there are many other apps like bobby, Coto I would also like to create an app like that, it's very helpful Vue Composition API to create such apps. I try and submit feedback here.
I preferred to use telegram app to download such videos were all links are active and available to download free.
Apkdiot İle En Popüler Android Oyun Ve Uygulamaları Hile Apk Olarak Ücretsiz Apk İndir Ve Paylaş. En Popüler En İyi Oyunlar Ve Uygulamaların Apk Sürümleri Apkdiot.com Sitesinde.
Nulls Brawl
otobüs simulator ultimate apk
truck simulator ultimate apk
car parking apk
spotify premium apk
YouTube Premium APK
Netflix Premium APK
WhatsApp Plus Apk
GB WhatsApp APK
Understanding the video formats AVI and MPG has given me a lot of insight about how video industry works and this information can also be used to search for files on a computer.
There are many movies app like netflix, Hulu, but there are many other apps like bobby, Coto I would also like to create an app like that, it's very helpful Vue Composition API to create such app's. I try and submit feedback here.
"Very nice post. I just stumbled upon your blog and wished to say that I have truly enjoyed browsing your blog posts. In any case I will be subscribing to your feed and I hope you write again soon!
"
Some comments may only be visible to logged-in visitors. Sign in to view all comments.