{"id":21519,"date":"2017-05-08T14:34:24","date_gmt":"2017-05-08T14:34:24","guid":{"rendered":"http:\/\/getting_started_with_vue_js_the_progressive_javascript_framework"},"modified":"2024-08-21T18:00:43","modified_gmt":"2024-08-22T01:00:43","slug":"getting_started_with_vue_js_the_progressive_javascript_framework","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework","title":{"rendered":"Getting Started With Vue JS: The Progressive JavaScript Framework"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>Vue.js is a progressive frontend framework which is the latest workflow and productivity trend. Its simplicity and approachability is what makes Vue.js outstanding among the pool of frontend frameworks. You may not be using Vue.js right now because you already know other JS frameworks and don\u2019t want to learn another. But it\u2019s important to keep in mind that a good framework is built to improve on the weaknesses of the existing ones. This is exactly what Vue.js has done.<\/p>\n<h2>The Challenge<\/h2>\n<p>The most difficult aspect of building a product with a front-end framework is focusing on the complexity of the tool rather than the complexity of the actual problem being solved. It\u2019s perhaps more frustrating when the tool is complex but the problem is a simple one (e.g. complex webpack config for a todo app). The term <strong>progressive<\/strong>, is used by Vue.js to describe how this challenge can be mitigated. Building a basic demo or small app? Vue.js is simple enough to handle that. How about a complex enterprise app? Vue.js is capable of produce cutting-edge solutions, as well.<\/p>\n<p>Vue.js is approachable, easy to learn and fast. In this article, we\u2019re going to get started with Vue.js by building a gallery app. A gallery app is simple, yet vast enough, to show you all the basic concepts in Vue.js that are applicable to any other framework you might have used<\/p>\n<p>To get up and running quickly with image uploads and delivery to\/from the cloud, we will utilize <a href=\"https:\/\/cloudinary.com\">Cloudinary<\/a> which is a natural choice. Cloudinary is a tool we have put together to assure you peace of mind when it comes to internet media. Ranging from upload to delivery, and most importantly, transformations that suit your needs, Cloudinary employs cutting edge engineering solutions to make this a painless reality.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-res.cloudinary.com\/image\/upload\/w_700\/Vue_Gallery.png\" alt=\"Final Example\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"700\" height=\"491\"\/><\/p>\n<h2>Preparing for Vue.js<\/h2>\n<p>To showcase how simple Vue.js is, we are going to build our demo using <a href=\"https:\/\/codepen.io\/pro\/projects\">Codepen Project<\/a> by importing a Vue.js script tag. No tooling for bundles or transpiling. Let\u2019s just write JavaScript.<\/p>\n<p><a href=\"https:\/\/codepen.io\/project\/editor\">Create a new<\/a> Codepen project using the Vue.js template shown on the sidebar:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-res.cloudinary.com\/image\/upload\/w_200\/Codepen_Vue.png\" alt=\"Codepen sidebar\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"200\" height=\"479\"\/><\/p>\n<p>This generates a new project with very few components and an entry point. We will clear most of the boilerplate code to make room for our gallery app logics:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-comment\">&lt;!-- index.html --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n  \n  <span class=\"hljs-comment\">&lt;!-- Meta --&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">charset<\/span>=<span class=\"hljs-string\">\"UTF-8\"<\/span> \/&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Vue.JS Grid<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n  \n  <span class=\"hljs-comment\">&lt;!-- Styles --&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/fonts.googleapis.com\/css?family=Montserrat\"<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"stylesheet\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"stylesheet\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/twitter-bootstrap\/4.0.0-alpha.6\/css\/bootstrap.min.css\"<\/span> \/&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"stylesheet\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"styles\/index.processed.css\"<\/span>&gt;<\/span>\n  \n  <span class=\"hljs-comment\">&lt;!-- Scripts --&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/unpkg.com\/vue@2.1.10\/dist\/vue.js\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n  \n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"demo\"<\/span>&gt;<\/span>\n    \n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  \n  <span class=\"hljs-comment\">&lt;!-- Scripts --&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"\/scripts\/components.js\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"\/scripts\/index.js\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ index.js<\/span>\n\n<span class=\"hljs-comment\">\/\/ Init Vue!<\/span>\n<span class=\"hljs-keyword\">var<\/span> app = <span class=\"hljs-keyword\">new<\/span> Vue({\n  <span class=\"hljs-attr\">el<\/span>: <span class=\"hljs-string\">'#demo'<\/span>,\n  <span class=\"hljs-attr\">methods<\/span>: {\n    \n  },\n  <span class=\"hljs-attr\">data<\/span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> {\n     <span class=\"hljs-attr\">thumbs<\/span>: &#91;]\n    }\n  }\n})\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<h3>The Vue Instance<\/h3>\n<p>Vue is initialized using the <code>Vue<\/code> instance and passing all information about the app as object. The properties of this object is what defines how your app behaves and what data is bound to your app. Now, let\u2019s look at the three most popular properties:<\/p>\n<ul>\n<li>The <code>el<\/code> property tells Vue where to mount the app instance in your HTML. That\u2019s why we have the div tag with a <code>demo<\/code> id.<\/li>\n<li>\n<code>data<\/code> is a function that returns an object of data, which can be bound to the view as well as available in all the Vue methods via <code>this<\/code>. Two-way binding in Vue is achieved via the data object properties.<\/li>\n<li>\n<code>methods<\/code> object is used to define methods that can be invoked from the view, as well as the Vue instance. This is the best place to put your event logic.<\/li>\n<\/ul>\n<p>We will dig into details and see how these properties can be applied together to build a rich app.<\/p>\n<h2>Data Binding<\/h2>\n<p>To see how data can be bound to the view, let\u2019s return an object in the <code>data<\/code> function with a property of the object bound to the view:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"demo\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\"<\/span> <span class=\"hljs-attr\">v-model<\/span>=<span class=\"hljs-string\">\"greeting\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-control\"<\/span> \/&gt;<\/span>\n    {{greeting}}\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">var<\/span> app = <span class=\"hljs-keyword\">new<\/span> Vue({\n  <span class=\"hljs-attr\">el<\/span>: <span class=\"hljs-string\">'#demo'<\/span>,\n  <span class=\"hljs-attr\">methods<\/span>: {\n    \n  },\n  <span class=\"hljs-attr\">data<\/span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> {\n     <span class=\"hljs-attr\">greeting<\/span>: <span class=\"hljs-string\">''<\/span>,\n    }\n  }\n})\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This is a typical two-way data binding example. A data property, <code>greeting<\/code>, is bound to an input box (using <code>v-model<\/code>) and to a paragraph (using interpolation). When the value in the input box changes, the content of the paragraph will be updated with respect to the box.<\/p>\n<p>Let\u2019s try something a bit more advanced:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"demo\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">header<\/span>&gt;<\/span>Awesome Gallery<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">header<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\"<\/span> <span class=\"hljs-attr\">v-model<\/span>=<span class=\"hljs-string\">\"greeting\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-control\"<\/span> \/&gt;<\/span>\n    {{greeting}}\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"row\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"col-md-4\"<\/span> <span class=\"hljs-attr\">v-for<\/span>=<span class=\"hljs-string\">\"thumb in thumbs\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"thumb\"<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">v-bind:src<\/span>=<span class=\"hljs-string\">\"thumb.url\"<\/span> \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ Init Vue!<\/span>\n<span class=\"hljs-keyword\">var<\/span> app = <span class=\"hljs-keyword\">new<\/span> Vue({\n  ...\n  data: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> {\n     <span class=\"hljs-attr\">greeting<\/span>: <span class=\"hljs-string\">''<\/span>,\n     <span class=\"hljs-attr\">thumbs<\/span>: &#91;\n       {\n         <span class=\"hljs-attr\">publidId<\/span>: <span class=\"hljs-string\">'views'<\/span>,\n         <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">'https:\/\/res.cloudinary.com\/christekh\/image\/upload\/v1493072225\/views.jpg'<\/span>\n       },\n       {\n         <span class=\"hljs-attr\">publidId<\/span>: <span class=\"hljs-string\">'dream-bikes'<\/span>,\n         <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">'https:\/\/res.cloudinary.com\/christekh\/image\/upload\/v1493072159\/dream-bikes.jpg'<\/span>\n       },\n       {\n         <span class=\"hljs-attr\">publidId<\/span>: <span class=\"hljs-string\">'workstation'<\/span>,\n         <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">'https:\/\/res.cloudinary.com\/christekh\/image\/upload\/v1493072107\/workstation.jpg'<\/span>\n       },\n       {\n         <span class=\"hljs-attr\">publidId<\/span>: <span class=\"hljs-string\">'reflection'<\/span>,\n         <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">'https:\/\/res.cloudinary.com\/christekh\/image\/upload\/v1493072042\/reflection.jpg'<\/span>\n       },\n       {\n         <span class=\"hljs-attr\">publidId<\/span>: <span class=\"hljs-string\">'electricity'<\/span>,\n         <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">'https:\/\/res.cloudinary.com\/christekh\/image\/upload\/v1493072006\/electricity.jpg'<\/span>\n       },\n       {\n         <span class=\"hljs-attr\">publidId<\/span>: <span class=\"hljs-string\">'cute-cat'<\/span>,\n         <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">'https:\/\/res.cloudinary.com\/christekh\/image\/upload\/v1493071918\/cute-cat.jpg'<\/span>\n       }\n     ]\n    }\n  }\n})\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In an attempt to replicate a real life app, we have extended the previous example to include an array of images stored in my <a href=\"https:\/\/cloudinary.com\/signup\">Cloudinary server<\/a>. This time we can\u2019t just bind the array to the view. Rather, we iterate over each of the array items and bind them to the view. This iteration is achievable with the help of Vue\u2019s built in template <code>v-for<\/code> directive.<\/p>\n<p>Another new and important addition is the <code>v-bind<\/code> directive. Vue won\u2019t allow you to interpolate in attributes, therefore, the <code>v-bind<\/code> directive is made responsible for attribute bindings.<\/p>\n<h2>Methods and Event Handling<\/h2>\n<p>Static information makes apps less interesting; we can do better. Rather than having the input box greet us, let\u2019s make it more useful (I am not saying greetings are useless :D). We can use the input to add more image URLs to our array by using a clickable button to initiate the process:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"row\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">divclass=\"col-md-9\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\"<\/span> <span class=\"hljs-attr\">v-model<\/span>=<span class=\"hljs-string\">\"thumb.url\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-control\"<\/span> \/&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"col-md-3\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"btn btn-primary\"<\/span> <span class=\"hljs-attr\">v-on:click<\/span>=<span class=\"hljs-string\">\"addThumb\"<\/span>&gt;<\/span>Add thumb<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We updated the model from <code>greeting<\/code> string to <code>thumb<\/code> object with a <code>url<\/code> property to match the <code>url<\/code> property in the thumbs array\u2019s objects.<\/p>\n<p><code>v-on<\/code> is used to bind events in Vue. Therefore, we use that to bind a click event (<code>v-on:click<\/code>) to the button. This event should be handled by <code>addThumb<\/code> method.<\/p>\n<p>Let\u2019s see the <code>thumb<\/code> property and the <code>addThumb<\/code> method:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\n<span class=\"hljs-comment\">\/\/ Init Vue!<\/span>\n<span class=\"hljs-keyword\">var<\/span> app = <span class=\"hljs-keyword\">new<\/span> Vue({\n  <span class=\"hljs-attr\">el<\/span>: <span class=\"hljs-string\">'#demo'<\/span>,\n  <span class=\"hljs-attr\">methods<\/span>: {\n    <span class=\"hljs-attr\">addThumb<\/span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n      <span class=\"hljs-keyword\">this<\/span>.thumbs.unshift(<span class=\"hljs-keyword\">this<\/span>.thumb)\n    }\n  },\n  <span class=\"hljs-attr\">data<\/span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> {\n     <span class=\"hljs-attr\">thumb<\/span>: {\n       <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">''<\/span>\n     },\n     <span class=\"hljs-attr\">thumbs<\/span>: &#91;\n       ... \n      ]\n    }\n  }\n})\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Just as data properties live in the data function, methods live in the method object and are accessible from the template as we just saw.<\/p>\n<h2>Component Composition<\/h2>\n<p>Vue is a component-based and architected framework, which means that you can build reusable self-contained UI widgets and share them across your apps or even in external projects. For example, let\u2019s add a global component to display each of the thumbs:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">\/\/ components.js\nVue.component('thumb-item', {\n  template: `\n\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"thumb\"<\/span>&gt;<\/span>\n\t    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">v-bind:src<\/span>=<span class=\"hljs-string\">\"thumb.url\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\t`,\n  props: &#91;'thumb']\n})\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Vue enables you to register the component using the <code>component<\/code> property in the Vue instance object argument. It also enables you to create a global component available everywhere in your app. We went with the latter option.<\/p>\n<p>The <code>component<\/code> static method takes the name of the component and an object that describes the component. <code>template<\/code>, as you might have guessed, is the HTML we want rendered. <code>props<\/code>, on the other hand, is an array of properties we are expecting from whatever parent in which component is contained.<\/p>\n<p>Let\u2019s use this component in our existing app. Change:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"row\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">divclass=\"col-md-4\"<\/span> <span class=\"hljs-attr\">v-for<\/span>=<span class=\"hljs-string\">\"thumb in thumbs\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"thumb\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">v-bind:src<\/span>=<span class=\"hljs-string\">\"thumb.url\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>to:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"row\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">divclass=\"col-md-4\"<\/span> <span class=\"hljs-attr\">v-for<\/span>=<span class=\"hljs-string\">\"thumb in thumbs\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">thumb-item<\/span> <span class=\"hljs-attr\">v-bind:thumb<\/span>=<span class=\"hljs-string\">\"thumb\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">thumb-item<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>The component is identified in the template using the component\u2019s name.<\/p>\n<h2>Lifecycle Hooks<\/h2>\n<p>Another important topic to discuss in a Vue introduction is Vue\u2019s lifecycle hook. Vue maintains a state for its components \u2013 from mounting your component to un-mounting. A lot of other phases are encountered in between. Lifecycle hooks help you tap in and perform operations at a given stage of your component life.<\/p>\n<p>A good example is making a HTTP request when the component is created so we can render data from the request to the view or whatever suites your context:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/axios\/0.15.3\/axios.min.js\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">var<\/span> app = <span class=\"hljs-keyword\">new<\/span> Vue({\n  <span class=\"hljs-attr\">el<\/span>: <span class=\"hljs-string\">'#demo'<\/span>,\n  <span class=\"hljs-attr\">methods<\/span>: {\n    <span class=\"hljs-attr\">addThumb<\/span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n      <span class=\"hljs-keyword\">this<\/span>.thumbs.unshift(<span class=\"hljs-keyword\">this<\/span>.thumb)\n    }\n  },\n  <span class=\"hljs-attr\">created<\/span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    axios.get(<span class=\"hljs-string\">'https:\/\/res.cloudinary.com\/christekh\/image\/list\/gs-vue.json'<\/span>).then(<span class=\"hljs-function\">(<span class=\"hljs-params\">res<\/span>) =&gt;<\/span> {\n      <span class=\"hljs-keyword\">this<\/span>.thumbs = res.data.resources.map(<span class=\"hljs-function\"><span class=\"hljs-params\">t<\/span> =&gt;<\/span> {\n        <span class=\"hljs-keyword\">return<\/span> {\n          <span class=\"hljs-attr\">publicId<\/span>: t.public_id,\n          <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">`https:\/\/res.cloudinary.com\/christekh\/image\/upload\/v<span class=\"hljs-subst\">${t.version}<\/span>\/<span class=\"hljs-subst\">${t.public_id}<\/span>.jpg`<\/span>\n        }\n      })\n    })\n  },\n  <span class=\"hljs-attr\">data<\/span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> {\n     <span class=\"hljs-attr\">thumb<\/span>: {\n       <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">''<\/span>\n     },\n     <span class=\"hljs-attr\">thumbs<\/span>: &#91;]\n    }\n  }\n})\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>The <code>created<\/code> lifecycle hook method is called when a component is created. This makes it a good place to fetch data. Therefore, we use <a href=\"https:\/\/github.com\/mzabriskie\/axios\">axios<\/a> to make a request to a list of images tagged <code>gs-vue<\/code> on my Cloudinary server.<\/p>\n<blockquote>\n<p><strong>NOTE<\/strong>\nFor security reasons, Cloudinary will not allow you to make requests like this from the client. The best method is to use the admin API via a backend SDK and then send the resource list to the client.<\/p>\n<p>However, to enable access to list resources from client, you need to <a href=\"https:\/\/cloudinary.com\/documentation\/image_transformations#client_side_resource_lists\">enable client resource listing<\/a>. This is not recommended in a production environment, but is fine for demo purposes.<\/p>\n<\/blockquote>\n<h2>Aside: Image Upload with Cloudinary<\/h2>\n<p>Cloudinary is a cloud-based media management tool. You can now worry less about image uploads, quality delivery, transformation and manipulation. Instead, you are able to focus on building your app while Cloudinary takes care of your media files.<\/p>\n<p>The example in this article has been delivering images from a Cloudinary server. Let\u2019s try to make the app more flexible by allowing users to upload more images to the existing ones:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"row\"<\/span>&gt;<\/span>\n   <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">divclass=\"col-md-12\"<\/span>&gt;<\/span>\n     <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"file\"<\/span> <span class=\"hljs-attr\">v-model<\/span>=<span class=\"hljs-string\">\"thumb.url\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-control\"<\/span> <span class=\"hljs-attr\">v-on:change<\/span>=<span class=\"hljs-string\">\"upload($event.target.files)\"<\/span> <span class=\"hljs-attr\">accept<\/span>=<span class=\"hljs-string\">\"image\/*\"<\/span> \/&gt;<\/span>\n   <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>First, we update the input text box to file input. Rather than using a button, we just attach a change event to the file input. Then whenever we add a file, it\u2019s automatically handled by the <code>upload<\/code> method. We only  want users to upload images, so we add a client validation by setting the <code>accept<\/code> attribute to <code>image\/*<\/code>.<\/p>\n<p>The <code>upload<\/code> handler is added to the methods object:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">data: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> {\n     <span class=\"hljs-attr\">cloudinary<\/span>: {\n       <span class=\"hljs-attr\">uploadPreset<\/span>: <span class=\"hljs-string\">'&lt;UPLOAD-PRESET&gt;'<\/span>,\n       <span class=\"hljs-attr\">apiKey<\/span>: <span class=\"hljs-string\">'&lt;API-KEY&gt;'<\/span>,\n       <span class=\"hljs-attr\">cloudName<\/span>: <span class=\"hljs-string\">'&lt;CLOUD-NAME&gt;'<\/span>\n     }, \n     <span class=\"hljs-attr\">thumb<\/span>: {\n       <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">''<\/span>\n     },\n     <span class=\"hljs-attr\">thumbs<\/span>: &#91;]\n    }\n  },\n  <span class=\"hljs-attr\">computed<\/span>: {\n    <span class=\"hljs-attr\">clUrl<\/span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  \t<span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`https:\/\/api.cloudinary.com\/v1_1\/<span class=\"hljs-subst\">${<span class=\"hljs-keyword\">this<\/span>.cloudinary.cloudName}<\/span>\/image\/upload`<\/span>  \n    },                \n  },\n<span class=\"hljs-attr\">methods<\/span>: {\n    <span class=\"hljs-attr\">upload<\/span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\">file<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> formData = <span class=\"hljs-keyword\">new<\/span> FormData()\n      formData.append(<span class=\"hljs-string\">'file'<\/span>, file&#91;<span class=\"hljs-number\">0<\/span>]);\n      formData.append(<span class=\"hljs-string\">'upload_preset'<\/span>, <span class=\"hljs-keyword\">this<\/span>.cloudinary.uploadPreset);\n      formData.append(<span class=\"hljs-string\">'tags'<\/span>, <span class=\"hljs-string\">'gs-vue,gs-vue-uploaded'<\/span>);\n      <span class=\"hljs-comment\">\/\/ For debug purpose only<\/span>\n      <span class=\"hljs-comment\">\/\/ Inspects the content of formData<\/span>\n      <span class=\"hljs-keyword\">for<\/span>(<span class=\"hljs-keyword\">var<\/span> pair <span class=\"hljs-keyword\">of<\/span> formData.entries()) {\n        <span class=\"hljs-built_in\">console<\/span>.log(pair&#91;<span class=\"hljs-number\">0<\/span>]+<span class=\"hljs-string\">', '<\/span>+pair&#91;<span class=\"hljs-number\">1<\/span>]);\n      }\n      axios.post(<span class=\"hljs-keyword\">this<\/span>.clUrl, formData).then(<span class=\"hljs-function\"><span class=\"hljs-params\">res<\/span> =&gt;<\/span> {\n        <span class=\"hljs-keyword\">this<\/span>.thumbs.unshift({\n          <span class=\"hljs-attr\">url<\/span>: res.data.secure_url\n        })\n      })\n    }\n  },\n }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>The <code>cloudinary<\/code> property holds an object with some Cloudinary credential:<\/p>\n<ul>\n<li>The API key and cloud name are available on the Cloudinary dashboard.<\/li>\n<li>Client uploads require upload preset to be set. <a href=\"https:\/\/cloudinary.com\/users\/login?RelayState=%2Fconsole%2Fsettings%2Fupload\">Setting up an upload preset<\/a> gives you a preset ID, which you need to provide during every upload.<\/li>\n<\/ul>\n<p>One other Vue instance property that we haven\u2019t discussed is <code>computed<\/code> property. This is basically a getter and is handy when a using a method as a getter is an overkill. We just have one computed property \u2013 <code>clUrl<\/code>.<\/p>\n<p>The <code>upload<\/code> function creates a <code>FormData<\/code> instance, appends all the attributes of this upload and sends to Cloudinary API using <code>axios<\/code>. These attributes include the file, tags and the upload preset.<\/p>\n<h2>Conclusion<\/h2>\n<p>What\u2019s most interesting about Vue.js is how simple it is to go from nothing to uploading an image to a server. The need for another supporting JavaScript library was minimal, not even a <a href=\"https:\/\/cloudinary.com\/blog\/automating_file_upload_and_sharing\">file upload<\/a> library; just Vue.js library. We are just using <code>axios<\/code> to simplify what native <code>fetch<\/code> could have done.<\/p>\n<p>We also saw how simple it is to upload images to Cloudinary for free. But Cloudinary enables even more. You can manipulate and transform these images just by tweaking URL parameters. You can learn about the awesome <a href=\"https:\/\/cloudinary.com\/products\/image_video_technology_platform\">features of Cloudinary<\/a> and <a href=\"https:\/\/cloudinary.com\/users\/register_free\">sign up for a free account<\/a> that enables you to do  uploads\/transformations and so much more.<\/p>\n<table>\n<tr>\n<td style = \"padding: 5px;\">\n<img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary\/image\/upload\/c_thumb,w_100\/christian_nwamba.jpg\" alt=\"Christian Nwamba\" title=\"Christian Nwamba\"><\/img><\/td>\n<td style = \"padding: 10px;\"><i><a href=\"https:\/\/twitter.com\/codebeast\" target=\"_new\">Christian Nwamba<\/a>  (CodeBeast), is a JavaScript Preacher, Community Builder and Developer Evangelist.  In his next life, Chris hopes to remain a computer programmer.<\/i><\/td>\n<\/tr>\n<\/table>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":21520,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[25,134,177,315],"class_list":["post-21519","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-asset-management","tag-guest-post","tag-javascript","tag-vue"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Getting Started with Vue JS: The Progressive JavaScript Framework<\/title>\n<meta name=\"description\" content=\"Vue.js is a progressive frontend framework powerful enough to handle projects from simple to complex with ease.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Getting Started With Vue JS: The Progressive JavaScript Framework\" \/>\n<meta property=\"og:description\" content=\"Vue.js is a progressive frontend framework powerful enough to handle projects from simple to complex with ease.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-05-08T14:34:24+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-08-22T01:00:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1645224181\/website-2021\/blog\/Vue-JS_2000x1100\/Vue-JS_2000x1100-png?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"1540\" \/>\n\t<meta property=\"og:image:height\" content=\"847\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Getting Started With Vue JS: The Progressive JavaScript Framework\",\"datePublished\":\"2017-05-08T14:34:24+00:00\",\"dateModified\":\"2024-08-22T01:00:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework\"},\"wordCount\":9,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1645224181\/website-2021\/blog\/Vue-JS_2000x1100\/Vue-JS_2000x1100.png?_i=AA\",\"keywords\":[\"Asset Management\",\"Guest Post\",\"Javascript\",\"Vue\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2017\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework\",\"url\":\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework\",\"name\":\"Getting Started with Vue JS: The Progressive JavaScript Framework\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1645224181\/website-2021\/blog\/Vue-JS_2000x1100\/Vue-JS_2000x1100.png?_i=AA\",\"datePublished\":\"2017-05-08T14:34:24+00:00\",\"dateModified\":\"2024-08-22T01:00:43+00:00\",\"description\":\"Vue.js is a progressive frontend framework powerful enough to handle projects from simple to complex with ease.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1645224181\/website-2021\/blog\/Vue-JS_2000x1100\/Vue-JS_2000x1100.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1645224181\/website-2021\/blog\/Vue-JS_2000x1100\/Vue-JS_2000x1100.png?_i=AA\",\"width\":1540,\"height\":847},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Getting Started With Vue JS: The Progressive JavaScript Framework\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Getting Started with Vue JS: The Progressive JavaScript Framework","description":"Vue.js is a progressive frontend framework powerful enough to handle projects from simple to complex with ease.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework","og_locale":"en_US","og_type":"article","og_title":"Getting Started With Vue JS: The Progressive JavaScript Framework","og_description":"Vue.js is a progressive frontend framework powerful enough to handle projects from simple to complex with ease.","og_url":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework","og_site_name":"Cloudinary Blog","article_published_time":"2017-05-08T14:34:24+00:00","article_modified_time":"2024-08-22T01:00:43+00:00","og_image":[{"width":1540,"height":847,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1645224181\/website-2021\/blog\/Vue-JS_2000x1100\/Vue-JS_2000x1100-png?_i=AA","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework"},"author":{"name":"","@id":""},"headline":"Getting Started With Vue JS: The Progressive JavaScript Framework","datePublished":"2017-05-08T14:34:24+00:00","dateModified":"2024-08-22T01:00:43+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework"},"wordCount":9,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1645224181\/website-2021\/blog\/Vue-JS_2000x1100\/Vue-JS_2000x1100.png?_i=AA","keywords":["Asset Management","Guest Post","Javascript","Vue"],"inLanguage":"en-US","copyrightYear":"2017","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework","url":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework","name":"Getting Started with Vue JS: The Progressive JavaScript Framework","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1645224181\/website-2021\/blog\/Vue-JS_2000x1100\/Vue-JS_2000x1100.png?_i=AA","datePublished":"2017-05-08T14:34:24+00:00","dateModified":"2024-08-22T01:00:43+00:00","description":"Vue.js is a progressive frontend framework powerful enough to handle projects from simple to complex with ease.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1645224181\/website-2021\/blog\/Vue-JS_2000x1100\/Vue-JS_2000x1100.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1645224181\/website-2021\/blog\/Vue-JS_2000x1100\/Vue-JS_2000x1100.png?_i=AA","width":1540,"height":847},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/getting_started_with_vue_js_the_progressive_javascript_framework#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Getting Started With Vue JS: The Progressive JavaScript Framework"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1645224181\/website-2021\/blog\/Vue-JS_2000x1100\/Vue-JS_2000x1100.png?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21519","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=21519"}],"version-history":[{"count":5,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21519\/revisions"}],"predecessor-version":[{"id":35376,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21519\/revisions\/35376"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/21520"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=21519"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=21519"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=21519"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}