{"id":4246,"date":"2021-04-01T08:21:28","date_gmt":"2021-04-01T08:21:28","guid":{"rendered":"http:\/\/www.nikola-breznjak.com\/blog\/?p=4246"},"modified":"2021-04-01T08:21:28","modified_gmt":"2021-04-01T08:21:28","slug":"getting-started-vue-js-3-building-giphy-search-application","status":"publish","type":"post","link":"https:\/\/nikola-breznjak.com\/blog\/javascript\/getting-started-vue-js-3-building-giphy-search-application\/","title":{"rendered":"Getting started with Vue.js 3 by building a Giphy search application"},"content":{"rendered":"<h2>TL;DR<\/h2>\n<p>In this post, you&#8217;ll learn how to use <a href=\"https:\/\/github.com\/vuejs\/vue-cli\">Vue CLI<\/a> to build a <strong>Vue.js 3<\/strong> application for searching <a href=\"http:\/\/giphy.com\/\">Giphy&#8217;s GIFs<\/a> by using <a href=\"https:\/\/developers.giphy.com\/docs\/api#quick-start-guide\">their API<\/a>.<\/p>\n<h2>Introduction &#8211; The War is Over<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/CseGOCb.png\" alt=\"\" \/><\/p>\n<p>Let&#8217;s be honest; even those of us that actually don&#8217;t <a href=\"https:\/\/dev.to\/jaredcwhite\/the-shocking-immaturity-of-javascript-c70\">hate<\/a> the JavaScript ecosystem can understand the frustration with the fact that new JS frameworks are popping up all the time.<\/p>\n<p>This was especially true some 2-3 years ago. However, it seems that the craziness has settled down a bit and that the war is seemingly over. For now. These top four (top 5 lists are overrated \ud83d\ude09) frameworks established themselves:<\/p>\n<ul>\n<li><a href=\"https:\/\/angular.io\/\">Angular<\/a> (71k)<\/li>\n<li><a href=\"https:\/\/reactjs.org\/\">React<\/a> (165k)<\/li>\n<li><a href=\"https:\/\/svelte.dev\/\">Svelte<\/a> (45k)<\/li>\n<li><a href=\"https:\/\/vuejs.org\/\">Vue.js<\/a> (181k)<\/li>\n<\/ul>\n<p>I added the number of Github `&#42;&#8217;s (at the time of this writing), but I don&#8217;t want you to read into that too much \ud83e\udd17<\/p>\n<h2>Analysis paralysis will, well, paralyze you!<\/h2>\n<p>You could argue that there are other options like Ember, Mithril, or good &#8216;ol jQuery even! However, <a href=\"https:\/\/twitter.com\/JoubranJad\/status\/1136030060975017984\">this tweet<\/a> says it all:<\/p>\n<blockquote><p>\n  Developers are fighting over which frontend framework is better.. it&#8217;s not like users know or care. They mostly care about the User Experience. UX should be our focus on the frontend.\n<\/p><\/blockquote>\n<p>Personally, I stuck to the Angular bandwagon ever since version 1.0, but that started losing it&#8217;s <em>ooomph<\/em> after version 2.<\/p>\n<p>I believe that Vue.js (due to its progressive and flexible nature) is a perfect fit for the teams that have to rewrite old codebases <strong>one step at a time<\/strong>. However, you can also use it as a full-blown framework if you wish.<\/p>\n<p>Personally, React&#8217;s JSX just <em>seems wrong<\/em>, and some people, smarter than me, swear by that being TheRightWay\u2122, and I guess we&#8217;re not here to discuss tastes&#8230;<\/p>\n<p>General&#8217; framework war&#8217; kind of questions I tend to answer in the following way:<\/p>\n<blockquote><p>\n  Please just stop with the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Analysis_paralysis\">analysis paralysis<\/a> already.<\/p>\n<p>  Do your research, pick a framework (any framework for that matter) that the community is using, use it, and see how far it gets you.<\/p>\n<p>  All these talks about X being slow or Y being better just make no sense until you try it yourself for your use case and preference.<\/p>\n<p>  Besides, nowadays the speed will not be a deciding factor among the top JS frameworks.\n<\/p><\/blockquote>\n<p>With all this out of the way, fasten your seatbelts, take a venti (or trenta) sized cup of coffee, and let&#8217;s go do something practical! \ud83d\udcaa<\/p>\n<blockquote><p>\n  If you care about the hardcore metrics \u23f1\ufe0f and want to check out some detailed comparisons between popular frontend frameworks, here <a href=\"https:\/\/www.codeinwp.com\/blog\/angular-vs-vue-vs-react\/\">are<\/a> a <a href=\"https:\/\/athemes.com\/guides\/angular-vs-react-vs-vue\/\">few<\/a> blog <a href=\"https:\/\/academind.com\/tutorials\/angular-vs-react-vs-vue-my-thoughts\/\">posts<\/a>.\n<\/p><\/blockquote>\n<h2>The Demo App<\/h2>\n<p>As said in the intro, we&#8217;ll build an application for searching (and showing) <a href=\"http:\/\/giphy.com\/\">Giphy<\/a> GIFs by using their <a href=\"https:\/\/developers.giphy.com\/docs\/api#quick-start-guide\">API<\/a>.<\/p>\n<p>You can fork the complete source code on <a href=\"https:\/\/github.com\/Hitman666\/GiphySearch_Vue3\">Github<\/a>.<\/p>\n<blockquote><p>\n  I&#8217;m using Vue.js 3, and I&#8217;ll be referring to it as just Vue.js in the rest of this post.\n<\/p><\/blockquote>\n<h2>Prerequisites<\/h2>\n<p>Make sure that you have the following tools installed:<\/p>\n<ul>\n<li>Node.js &#8211; here&#8217;s a free but outdated <a href=\"https:\/\/leanpub.com\/meantodo\">step by step guide\/book<\/a> for both Windows and Mac. Or, really, just go to the <a href=\"https:\/\/nodejs.org\/\">main website<\/a> and download the executable for your machine<\/li>\n<li>Git &#8211; here&#8217;s a fun <a href=\"https:\/\/dev.to\/hitman666\/learn-git-fast-as-if-your-job-depends-on-it-dgj\">getting started<\/a> tutorial in case you&#8217;re new to it<\/li>\n<\/ul>\n<h2>Vue CLI<\/h2>\n<p>As their <a href=\"https:\/\/cli.vuejs.org\/guide\/\">docs say<\/a>:<\/p>\n<blockquote><p>\n  Vue CLI aims to be the standard tooling baseline for the Vue ecosystem. It ensures the various build tools work smoothly together with sensible defaults so you can focus on writing your app instead of spending days wrangling with configurations. At the same time, it still offers the flexibility to tweak the config of each tool without the need for ejecting.\n<\/p><\/blockquote>\n<p>To install Vue CLI, run the following command (in your Terminal):<\/p>\n<p><code>npm install -g @vue\/cli<\/code><\/p>\n<p>You can confirm that the installation went well if you run <code>vue<\/code> and get an output with usage information.<\/p>\n<blockquote><p>\n  \u26a0\ufe0f Just for reference (in case you follow this tutorial at a later stage and something is not the same as I output it here), my version (get the output by running <code>vue --version<\/code> in your Terminal) as of this writing is <code>@vue\/cli 4.5.12<\/code>.\n<\/p><\/blockquote>\n<h2>Start a new app with Vue CLI<\/h2>\n<p>We&#8217;ll call our app, originally \ud83d\ude48, <code>giphy-search<\/code>. So, to start a new app using Vue CLI, run:<\/p>\n<p><code>vue create giphy-search<\/code><\/p>\n<p>Make sure you select the option <code>\u276f Default (Vue 3 Preview) ([Vue 3] babel, eslint)<\/code> and press <code>ENTER<\/code>.<\/p>\n<p>You should get an output similar to this:<\/p>\n<pre><code>Vue CLI v4.5.12\n\u2728  Creating project in \/Users\/nikola\/DEV\/BLOG\/giphy-search.\n\ud83d\uddc3  Initializing git repository...\n\u2699\ufe0f  Installing CLI plugins. This might take a while...\n\ud83d\ude80  Invoking generators...\n\ud83d\udce6  Installing additional dependencies...\n\ud83d\udcc4  Generating README.md...\n\ud83c\udf89  Successfully created project giphy-search.\n<\/code><\/pre>\n<p>After this command finishes, let&#8217;s <code>cd<\/code> into the project and <code>run<\/code> it:<\/p>\n<pre><code>cd giphy-search\nnpm run serve\n<\/code><\/pre>\n<p>You should get this output:<\/p>\n<pre><code>DONE  Compiled successfully in 3178ms\n\nApp running at:\n  - Local:   http:\/\/localhost:8080\/\n  - Network: http:\/\/192.168.8.189:8080\/\n\nNote that the development build is not optimized.\nTo create a production build, run npm run build.\n<\/code><\/pre>\n<p>You should see the following page in your browser if you open http:\/\/localhost:8080.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/xbePr2wl.jpg\" alt=\"\" \/><\/p>\n<h2>Folder structure<\/h2>\n<p>Now, let&#8217;s open this project in the editor of your choice (I&#8217;m using <a href=\"https:\/\/code.visualstudio.com\/\">Visual Studio Code<\/a>), and you should see something like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/mbfO9D7l.jpg\" alt=\"\" \/><\/p>\n<p>This is an introduction tutorial, to get you running fast, so I won&#8217;t be going into any specific details and will be only focusing on the <code>src<\/code> folder.<\/p>\n<h2>Add content<\/h2>\n<p>OK, so let&#8217;s add something to our app.<\/p>\n<p>But, where to start? \ud83e\udd14<\/p>\n<p>Well, one of the first things I do when I come to a project for the first time is to look at the generated output. Then I try to find the strings corresponding to that output within the source code.<\/p>\n<p>So, if you search for the string <code>Welcome to Your Vue.js App<\/code>, you&#8217;ll see the string is within the <code>App.vue<\/code> file. This file contains the following code:<\/p>\n<pre><code>&lt;template&gt;\n  &lt;img alt=\"Vue logo\" src=\".\/assets\/logo.png\"&gt;\n  &lt;HelloWorld msg=\"Welcome to Your Vue.js App\"\/&gt;\n&lt;\/template&gt;\n\n&lt;script&gt;\nimport HelloWorld from '.\/components\/HelloWorld.vue'\n\nexport default {\n  name: 'App',\n  components: {\n    HelloWorld\n  }\n}\n&lt;\/script&gt;\n\n&lt;style&gt;\n#app {\n  font-family: Avenir, Helvetica, Arial, sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-align: center;\n  color: #2c3e50;\n  margin-top: 60px;\n}\n&lt;\/style&gt;\n<\/code><\/pre>\n<p>Without knowing much about Vue.js, you can see where you would change the <code>Welcome to Your Vue.js App<\/code> text. So, let&#8217;s change that to <code>Welcome to GiphySearch<\/code>. While you do that, also remove the contents of the <code>style<\/code> tag.<\/p>\n<p>In the App.vue file, we have a <code>template<\/code> tag that contains a standard HTML <code>img<\/code> tag and an <code>HelloWorld<\/code> tag, which is a so-called component. Here&#8217;s the <a href=\"https:\/\/v3.vuejs.org\/guide\/component-basics.html\">link to the documentation<\/a> where you can learn more about components.<\/p>\n<h2>Add an input and a button<\/h2>\n<p>Our basic application should have one input field and one button.<\/p>\n<p>To do this, adjust the <code>template<\/code> in the <code>HelloWorld.vue<\/code> file to contain only this:<\/p>\n<pre><code>&lt;div class=\"hello\"&gt;\n    &lt;h1&gt;{{ msg }}&lt;\/h1&gt;\n\n    &lt;input name=\"search\" \/&gt;\n    &lt;button&gt;Search&lt;\/button&gt;\n&lt;\/div&gt;\n<\/code><\/pre>\n<h2>Actions<\/h2>\n<p>Having a simple search input field and a button doesn&#8217;t do much. We want to click the button, and we want to output something to the console just to verify it&#8217;s working correctly.<\/p>\n<p>So, this is how you define a function that will handle a button click in Vue.js:<\/p>\n<p><code>&lt;button @click=\"performSearch\"&gt;Search&lt;\/button&gt;<\/code><\/p>\n<p>But, if you open your DevTools now and click the <code>Search<\/code> button, you&#8217;ll get an error like:<\/p>\n<pre><code>runtime-core.esm-bundler.js?5c40:38 [Vue warn]: Unhandled error during execution of native event handler\n  at &lt;HelloWorld msg=\"Welcome to GiphySearch\" &gt;\n  at &lt;App&gt;\nwarn @ runtime-core.esm-bundler.js?5c40:38\nlogError @ runtime-core.esm-bundler.js?5c40:211\nhandleError @ runtime-core.esm-bundler.js?5c40:203\ncallWithErrorHandling @ runtime-core.esm-bundler.js?5c40:157\ncallWithAsyncErrorHandling @ runtime-core.esm-bundler.js?5c40:163\ninvoker @ runtime-dom.esm-bundler.js?830f:327\nruntime-core.esm-bundler.js?5c40:217 Uncaught TypeError: _ctx.performSearch is not a function\n    at Object.onClick._cache.&lt;computed&gt;._cache.&lt;computed&gt; (HelloWorld.vue?fdab:6)\n    at callWithErrorHandling (runtime-core.esm-bundler.js?5c40:154)\n    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js?5c40:163)\n    at HTMLButtonElement.invoker (runtime-dom.esm-bundler.js?830f:327)\n<\/code><\/pre>\n<p>That&#8217;s because we haven&#8217;t defined the <code>performSearch<\/code> function anywhere.<\/p>\n<p>Let&#8217;s do that now. In the <code>HelloWorld.vue<\/code> file, add the following function definition inside the <code>script<\/code> tag, <code>methods<\/code> object property:<\/p>\n<pre><code>&lt;script&gt;\nexport default {\n    name: 'HelloWorld',\n    props: {\n        msg: String\n    },\n    methods: {\n        performSearch() {\n            console.log('clicked');\n        }\n    }\n};\n&lt;\/script&gt;\n<\/code><\/pre>\n<p>We defined the <code>performSearch<\/code> function, which doesn&#8217;t accept any parameters and it doesn&#8217;t return anything. It just outputs <code>clicked<\/code> in the console.<\/p>\n<h2>Gather input<\/h2>\n<p>What if we would like to output (to the console) the string that someone typed in the input field?<\/p>\n<p>Well, first we need to add a new attribute to the input field:<\/p>\n<p><code>&lt;input name=\"title\" v-model=\"searchTerm\"&gt;<\/code><\/p>\n<p>The <code>v-model<\/code> is a directive that instructs Vue.js to bind the input to the new <code>searchTerm<\/code> variable.<\/p>\n<p>Finally, change the <code>performSearch<\/code> function to this:<\/p>\n<pre><code>performSearch: function() {\n    console.log(this.searchTerm);\n}\n<\/code><\/pre>\n<blockquote><p>\n  Technically, you could write this a bit differently, passing the <code>searchTerm<\/code> variable into the <code>performSearch<\/code> function as a parameter:<\/p>\n<pre><code>performSearch: function(searchTerm) {\n   console.log(searchTerm);\n}\n\n&lt;button @click=\"performSearch(searchTerm)\"&gt;Search&lt;\/button&gt;\n\nI'd love to hear from you in the comments which approach is better in your opinion.\n<\/code><\/pre>\n<\/blockquote>\n<h2>Giphy search API<\/h2>\n<p>Finally, we come to the cool part \ud83e\udd76, and that is to fetch some data from the Giphy API and show it in our app.<\/p>\n<p>How do we get this API? Well, if you do a simple Google search for <code>giphy api<\/code> and open the <a href=\"https:\/\/developers.giphy.com\/\">first link<\/a>, you&#8217;ll get the documentation for their API.<\/p>\n<p>You need to follow <a href=\"https:\/\/developers.giphy.com\/docs\/api#quick-start-guide\">these instructions<\/a> to create an account (and an app) to get an API key. You don&#8217;t need an SDK solution at this point (you may want to go that route if you&#8217;re going to make a mobile app that shows these images).<\/p>\n<p>After you obtain your API key through their dashboard, you&#8217;re going to be able to make <code>search<\/code> (they offer a bunch more) API requests through their <a href=\"https:\/\/developers.giphy.com\/explorer\">API explorer<\/a>.<\/p>\n<p>An API URL (obviously, with the fake API key) may look like this: https:\/\/api.giphy.com\/v1\/gifs\/search?api_key=AbC&amp;q=cats&amp;limit=10&amp;offset=0&amp;rating=g&amp;lang=en<\/p>\n<p>Great, now we see what kind of a request we need to create to search Giphy&#8217;s GIF database for a certain term.<\/p>\n<p>If you open this link in the browser, you&#8217;ll see that the service returns something like:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/WaR9pdjl.png\" alt=\"\" \/><\/p>\n<p>In the next section, we&#8217;ll cover retrieving this data within our app.<\/p>\n<blockquote><p>\n  \u26a0\ufe0f Since Giphy&#8217;s rules now require you to <a href=\"https:\/\/developers.giphy.com\/docs\/api#quick-start-guide\">add attribution<\/a>, make sure you add it. I added the image in the footer with a link to their docs.\n<\/p><\/blockquote>\n<h2>Vue.js HTTP requests<\/h2>\n<p>We have several options for making HTTP requests in Vue.js, and some may see this flexibility as a pro, and some may see it as a con. Either way, for more options, check out <a href=\"https:\/\/www.techiediaries.com\/vuejs-ajax-http\/\">this post<\/a>.<\/p>\n<p>I chose to go with <a href=\"https:\/\/github.com\/axios\/axios\">Axios<\/a>, as it&#8217;s a very popular JavaScript library for making HTTP requests. It&#8217;s an HTTP client that makes use of the modern Promises API by default (instead of the <em>not so nice<\/em> JavaScript callbacks \ud83d\ude42) and runs on both the client and the server (i.e., Node.js).<\/p>\n<p>In your Terminal enter the following command to install Axios via npm:<\/p>\n<p><code>npm install axios --save<\/code><\/p>\n<p>Import Axios in the <code>HelloWorld.vue<\/code> file just after the <code>script<\/code> tag:<\/p>\n<p><code>import axios from \"axios\";<\/code><\/p>\n<p>The <code>performSearch<\/code> function should now look like this:<\/p>\n<pre><code>let API_KEY = 'getYourOwn';\nlet link = `https:\/\/api.giphy.com\/v1\/gifs\/search?api_key=${API_KEY}&amp;limit=25&amp;offset=0&amp;rating=g&amp;lang=en&amp;q=`;\nlet apiLink = link + this.searchTerm;\n\naxios\n    .get(apiLink)\n    .then((response) =&gt; {\n        console.log(response);\n    })\n    .catch((error) =&gt; {\n        console.log(error);\n    });\n<\/code><\/pre>\n<p>Just for reference, to put it all in one listing, the contents of the <code>HelloWorld.vue<\/code> file should be:<\/p>\n<pre><code>&lt;template&gt;\n    &lt;div class=\"hello\"&gt;\n        &lt;h1&gt;{{ msg }}&lt;\/h1&gt;\n\n        &lt;input name=\"search\" v-model=\"searchTerm\" \/&gt;\n        &lt;button @click=\"performSearch()\"&gt;Search&lt;\/button&gt;\n    &lt;\/div&gt;\n    &lt;a href=\"https:\/\/developers.giphy.com\/docs\/api#quick-start-guide\"&gt;\n        &lt;img src=\"giphy.png\" alt=\"\" class=\"giphyAttribution\" \/&gt;\n    &lt;\/a&gt;\n&lt;\/template&gt;\n\n\n\n<script>\nimport axios from 'axios';\n\nexport default {\n    name: 'HelloWorld',\n    props: {\n        msg: String\n    },\n    methods: {\n        performSearch() {\n            let API_KEY = 'getYourOwn';\n            let link = `https:\/\/api.giphy.com\/v1\/gifs\/search?api_key=${API_KEY}&limit=25&offset=0&rating=g&lang=en&q=`;\n            let apiLink = link + this.searchTerm;\n\n            axios\n                .get(apiLink)\n                .then((response) => {\n                    console.log(response);\n                })\n                .catch((error) => {\n                    console.log(error);\n                });\n        }\n    }\n};\n<\/script>\n\n\n<\/code><\/pre>\n<p>If you run the app and enter something in the input box, and then click the search button, you&#8217;ll see something like this in your console log:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/aX3TKbLl.png\" alt=\"\" \/><\/p>\n<p>You can see that we&#8217;re getting an object that in its <code>data<\/code> property has another <code>data<\/code> property (so meta \ud83d\ude0e) that&#8217;s an array with 25 objects, which holds the information about the images we&#8217;ll show in our app.<\/p>\n<p>Well, after a tongue twister in the previous sentence, this is all great, but we don&#8217;t want to be logging our objects to the console; we want to show them in our app! \ud83d\ude42<\/p>\n<p>To show the GIF, you can choose any of the properties under the <code>images<\/code> object, and use the <code>url<\/code> property. I used <code>fixed_height_small<\/code> in my example.<\/p>\n<p>We don&#8217;t want to just show one image but all of the images. We can use the <code>v-for<\/code> directive for that:<\/p>\n<p><code>&lt;img v-for=\"g in giphies\" :key=\"g.id\" :src=\"g.images.fixed_height_small.url\" \/&gt;<\/code><\/p>\n<p>For reference, here&#8217;s the full listing of <code>HelloWorld.vue<\/code> file:<\/p>\n<pre><code>&lt;template&gt;\n    &lt;div class=\"hello\"&gt;\n        &lt;h1&gt;{{ msg }}&lt;\/h1&gt;\n\n        &lt;input name=\"search\" v-model=\"searchTerm\" \/&gt;\n        &lt;button @click=\"performSearch()\"&gt;Search&lt;\/button&gt;\n\n        &lt;img v-for=\"g in giphies\" :key=\"g.id\" :src=\"g.images.fixed_height_small.url\" \/&gt;\n    &lt;\/div&gt;\n    &lt;a href=\"https:\/\/developers.giphy.com\/docs\/api#quick-start-guide\"&gt;\n        &lt;img src=\"giphy.png\" alt=\"\" class=\"giphyAttribution\" \/&gt;\n    &lt;\/a&gt;\n&lt;\/template&gt;\n\n\n\n<script>\nimport axios from 'axios';\n\nexport default {\n    name: 'HelloWorld',\n    props: {\n        msg: String\n    },\n    data() {\n        return {\n            searchTerm: 'cats',\n            giphies: []\n        };\n    },\n    methods: {\n        performSearch() {\n            let API_KEY = 'getYourOwn';\n            let link = `https:\/\/api.giphy.com\/v1\/gifs\/search?api_key=${API_KEY}&limit=5&offset=0&rating=g&lang=en&q=`;\n            let apiLink = link + this.searchTerm;\n\n            axios\n                .get(apiLink)\n                .then((response) => {\n                    this.giphies = response.data.data;\n                })\n                .catch((error) => {\n                    console.error(error);\n                });\n        }\n    }\n};\n<\/script>\n\n\n<\/code><\/pre>\n<h2>B e a utiful<\/h2>\n<p>At this point, if we take a look at the app and search, for example, for &#8216;cat coding&#8217; we&#8217;ll get this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/dTHVYt5l.png\" alt=\"\" \/><\/p>\n<p>Although the result doesn&#8217;t look sleek (ha!, far from it \ud83d\ude33), our code does exactly what it&#8217;s supposed to do. If you want it to look nicer, feel free to add more CSS.<\/p>\n<blockquote><p>\n  <a href=\"https:\/\/bulma.io\/\">Bulma<\/a> is a cool framework that I used in the <a href=\"https:\/\/dev.to\/hitman666\/jwt-authentication-in-an-angular-application-with-a-go-backend--13cg\">JWT authentication in an Angular application with a Go backend<\/a> post in case you&#8217;re interested in taking a look.\n<\/p><\/blockquote>\n<h2>Conclusion<\/h2>\n<p>In this tutorial, you learned how to get started with using Vue.js 3 by building an application for searching Giphy&#8217;s GIFs by using their API.<\/p>\n<p>Please leave any comments and feedback in the discussion section below, and thank you for reading!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TL;DR In this post, you&#8217;ll learn how to use Vue CLI to build a Vue.js 3 application for searching Giphy&#8217;s GIFs by using their API. Introduction &#8211; The&hellip;<\/p>\n","protected":false},"author":1,"featured_media":4247,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,58],"tags":[],"class_list":["post-4246","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-javascript","category-vue-js"],"_links":{"self":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/4246","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/comments?post=4246"}],"version-history":[{"count":1,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/4246\/revisions"}],"predecessor-version":[{"id":4248,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/4246\/revisions\/4248"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/media\/4247"}],"wp:attachment":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/media?parent=4246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/categories?post=4246"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/tags?post=4246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}