# My first reactive component with Vue.js

> My experience moving from jQuery DOM manipulation to Vue.js's data-driven approach, and how I wrote my first reactive component.

- Published: 2016-04-03
- Category: Interface
- Tags: JavaScript, Vue.js
- Reading time: 3 min read
- Source: https://www.muhammetsafak.com.tr/en/blog/first-reactive-component-with-vue-js/
- Language: en-US
- Author: Muhammet Şafak

---
For a long time I had been writing JavaScript with [jQuery](/en/blog/sending-data-without-page-reload-jquery-ajax/). Form submissions, DOM updates, small interactions — all of it with `$('#element').html(...)`. It worked, but as things grew it produced a pile of code that got harder and harder to follow. A single button click would update the DOM in three different places, and if you forgot to update one of them the screen would be left in an inconsistent state.

I had been hearing about Vue.js for a few months. Last week, before kicking off a new project, I decided to take a closer look. In this post I share what I found: first impressions, first component.

## What is the reactive approach?

**Reactive programming** is based on the principle that the UI updates automatically when the data changes. With jQuery, you had a mental model of the data while you manually updated the DOM; with Vue, you don't update the DOM — Vue does. You only change the data.

That might sound like a small difference, but in practice it changes quite a lot.

## First step: installation

Vue 1.x is the current release. A CDN is enough to add it to a page via a script tag:

```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.20/vue.min.js"></script>
```

You can also install it via npm, but CDN is more practical for getting started.

## First component: a simple counter

The simplest example is a counter:

```html
<div id="uygulama">
    <p>Sayı: {{ sayi }}</p>
    <button v-on:click="artir">Artır</button>
    <button v-on:click="azalt">Azalt</button>
</div>

<script>
new Vue({
    el: '#uygulama',

    data: {
        sayi: 0
    },

    methods: {
        artir: function () {
            this.sayi++;
        },
        azalt: function () {
            this.sayi--;
        }
    }
});
</script>
```

When `sayi` inside `data` changes, the DOM element containing the `{{ sayi }}` expression is updated automatically. If I had written this with jQuery:

```javascript
// jQuery version
var sayi = 0;

$('#artir').click(function () {
    sayi++;
    $('#sayac').text('Sayı: ' + sayi);
});

$('#azalt').click(function () {
    sayi--;
    $('#sayac').text('Sayı: ' + sayi);
});
```

I have to update the DOM myself. With Vue, writing `this.sayi++` is enough; Vue handles the rest.

There is a hidden trap in the jQuery version too: the `sayi` variable lives in the global scope, or needs to be wrapped in a closure. As soon as you have more than one counter, that gets messy fast. In Vue, each component's `data` function brings its own closed scope; components never step on each other's data.

## Something more realistic: a list filter

The counter example was fine, but it doesn't teach much. Let's try a real UI piece — a searchable list:

```html
<div id="uygulama">
    <input v-model="arama" placeholder="Ara...">

    <ul>
        <li v-for="urun in filtreliUrunler">{{ urun.ad }}</li>
    </ul>

    <p v-if="filtreliUrunler.length === 0">Sonuç bulunamadı.</p>
</div>

<script>
new Vue({
    el: '#uygulama',

    data: {
        arama: '',
        urunler: [
            { ad: 'Klavye' },
            { ad: 'Mouse' },
            { ad: 'Monitör' },
            { ad: 'Kulaklık' }
        ]
    },

    computed: {
        filtreliUrunler: function () {
            var arama = this.arama.toLowerCase();
            return this.urunler.filter(function (urun) {
                return urun.ad.toLowerCase().indexOf(arama) !== -1;
            });
        }
    }
});
</script>
```

`v-model` binds the input value to `arama` two-way. The computed property `filtreliUrunler` is automatically recalculated whenever `arama` changes. `v-for` hands the list off to Vue to manage.

Writing this in jQuery isn't hard, of course, but you have to wire everything up yourself: listen for the input event, filter the list, clear the existing `li` elements, create new ones, append them to the DOM.

Computed properties make a meaningful difference here. A value in the `computed` block is read from cache as long as the data it depends on hasn't changed. That means `filtreliUrunler` isn't recalculated from scratch on every keystroke — it's recalculated when `arama` changes. For a small list this difference is imperceptible, but it matters as the list grows.

## My observations

Vue's learning curve is low. You can drop it into an existing HTML page with a `<script>` tag and start using it right away. That allows you to adopt it incrementally without having to rewrite the whole project from scratch — a significant plus for me.

Directives like `v-bind`, `v-on`, `v-if`, and `v-for` are clear and readable inside the HTML. You can glance at a template file and quickly understand what it's doing.

On the downside: how cross-component state management will work at scale is something I haven't fully figured out yet. The question of what to do when two separate components need the same data is still open. For now, it's very satisfying for small-to-medium-sized UI pieces.

In the coming weeks I'm planning to look into components and Vue Router.
