MY VUE ON MVVM

muyiwa akin-ogundeji
6 min readNov 22, 2015

--

Since switching from providing Desktop and LAN support as well as Business Technology Solutions to SMBs/SMEs to fullstack Javascript web development I’ve encountered many concepts and paradigms crucial to good web development practice.

A central paradigm for developing scalable and maintainable JS web apps is the adoption of some form of architectural pattern for the development of the UI. The most prevalent family of patterns is the MVC/MV* family.

The fundamental concept is that there is a Model which represents either the problem domain or a data access layer separate from the UI. A View exists which provides visual representation of the present state of the underlying Model to the user, while the Controller exists to coordinate user actions, Model modifications in response to the user actions and View rendering to reflect the changes in the Model’s state.

While MVC is all well and good, I’ve come to particularly treasure the MVVM adaptation of the MV* architecture.

While there are different definitions and interpretations of what MVVM is, in this article I’d like to share my understanding of MVVM and how it can be used to build rich web applications using Vue.js.

MVVM stands for Model-View-View Model. The key difference is the existence of the VM which is a construct which provides linkage/interface between the Model and the View.

In MVVM, the Model simply represents the data access layer of the application. It holds the data/information which is to be presented to the user for manipulation or interaction. The Model has no behavior or logic defined on it in any way apart from data validation. The Model also has no means to access a backend or 3rd Party API to generate or save data — it simply serves as a container to hold the information/data which the VM retrieves and uses.

A sample Model using Vue.js follows:

var model = {
cities: [‘lagos’, ‘new york’, ‘amsterdam’, ‘frankfurt’, ‘shanghai’]
};

Note that in Vue.js, Models are POJOs.

The View is used to render the information contained in the Model to the user. In MVVM, the View doesn’t know about the Model and vice-versa. The View knows about the VM and is therefore known as an ‘active’ View. All user action e.g. user input Is intercepted by the View and passed to the VM for processing. The View doesn’t maintain any state rather it simply represents ‘state’ as defined by the VM.

The VM is the link between the Model and the View. All logic required for manipulating the data contained in the Model is defined on the VM and all logic which the View uses to handle user interaction or format the data from the Model are provided to it from the VM. Unlike other MV* implementations, all Business Logic which the app requires to function are defined on the VM and not the Model.

How does this all work? Glad you asked me, lets dig in.

GROKKING the View Model:

In MVVM, the Model simply holds data which the VM provides to the View. Using Vue.js, a Model is always a POJO. The Model has properties which the VM can populate with the result of Ajax/API calls or other methods of acquiring data. In the world of Vue, a Model is supplied to the VM as a property of it’s ‘options’ object when the VM is created e.g.

var vm = new Vue({
data: {
cities: [‘lagos’, ‘new york’, ‘amsterdam’, ‘frankfurt’, ‘shanghai’]
}
});

The VM must be bound to a DOM element through which the ‘View’ is rendered. This DOM element is identified by the ‘id’ of the element e.g.

<div id=”app”></div>var vm = new Vue({
el: ‘#app’,
data: {
cities: [‘lagos’, ‘new york’, ‘amsterdam’, ‘frankfurt’, ‘shanghai’]
}
});

The preceding example binds the VM to the ‘div’ with id of ‘app’. If this example is run, it’ll show nothing because the View as defined by ‘app’ has nothing to use to render the content of the VM i.e. the ‘cities’ array of the ‘data Model’ of the VM.

This is where ‘directives’ and ‘data-bindings’ come to play. Data-bindings are used to synchronize data properties on the VM with the appropriate element on the View, and Directives are used to provide the View with logic which is used to conditionally render the content of the VM or intercept user action and pass the action to the VM.

Thus a ‘proper’ View would look as follows:

<div id=”app”>
<ul>
<li v-for=”item in cities”>{{item}}</li>
</ul>
</div>

‘v-for’ is a directive which tells the View to create an ‘li’ DOM element for each item of the ‘cities’ collection/list (i.e. array) of the VM.

‘{{item}}’ is a data binding which provides the value of the current ‘item’ from the ‘cities’ list being acted upon to the appropriate DOM element of the View in this case the ‘li’.

In a data-driven application, there’s no direct manipulation of the DOM by the VM, rather any modifications to the Model state are reflected in the VM and this is rendered by the View in response to user action. Thus the View also has event handler bindings (directives) which intercept events which happen on the View and pass them to methods defined on the VM for handling e.g.

<div id=”app”>
<ul>
<li v-for=”item in cities” v-on:click=”onClick(item)”>{{item}} </li>
</ul>
</div>

The event handler is defined within the ‘methods’ property of the VM e.g.

var vm = new Vue({
el: ‘#app’,
data: {
cities: [‘lagos’, ‘new york’, ‘amsterdam’, ‘frankfurt’, ‘shanghai’]
},
methods: {
onClick: function (item) {
return console.log(item +’ was clicked!’);
}
}
});

To recap the MVVM architecture is built around 3 elements:

1. Models: Simple constructs which hold data used by the VM and the app. Models have no logic apart from data validation logic and they don’t access services to retrieve or save data. In Vue.js, Models are POJOs.

2. Views: These render the data contained within the VM. Views are active and are their basic structure is defined by ‘templates’ which are either custom script tags, custom DOM tags or plain HTML. In order to format the data provided by the VM and to respond to user actions, View templates are enhanced with data-bindings and directives. These two combine to ensure that the View is always in sync with the state of the VM and remove the need for any direct DOM manipulations.

3. VMs: These hold all the Business Logic required to manipulate the data used by the app, they also have properties which are bound to various DOM elements in their View templates to allow for data-binding, furthermore VMs have ‘methods’ which handle DOM events intercepted by directives embedded within the View template.

The MVVM architecture in general and Vue.js in particular is well suited to building rich web apps around the concept of ‘Components’. Components are small, self-contained and often reusable constructs which bring together a Model, View and VM for a single well defined purpose e.g. a user login form as shown below:

Template:

<div id=”app”>
<form v-on:keyup.enter.prevent.stop=”handleForm”>
<input type=”text” v-model=”username” placeholder=”Username”>
<input type = password v-model=”password”>
<input type=”button” value=”Submit”>
</form>
</div>

Note:

1. The ‘v-on:keyup.enter’ directive intercepts the ‘submit’ event on the form and calls the ‘handleForm’ method on the VM. Note the ‘.prevent ‘ and ‘.stop’ modifiers which allow us to prevent default action as well as stop the event from propagating further. This allows the event handler to simply contain logic for handling the event and not dealing with these common needs.

2. input[type=”text”] has a ‘v-model’ directive which 2-way binds it’s value to the value of a ‘username’ property on the VM. This 2-way binding allows the user input to be directly passed to the VM without much coding. The same concept holds for the ‘password’ input.

VM:

var vm = new Vue({
el: “#app”,
data: {
username: ‘’,
password: ‘’
},
methods: {
handleForm: function () {
if(this.username.trim() && this.password.trim()) {
console.log( ‘The username is: ‘ + this.username +’ and password is: ‘+ this.password);
return this.username = this.password = ‘’;
}
return null;
}
}
});

In the VM the ‘handleForm’ method simple checks that the values of the ‘username’ and ‘password’ property of the VM is truthy, if so it logs the values and then resets the input fields for subsequent use.

To demonstrate the power or Vue.js reactive data-binding implementation, we make a small modification to the template thus…

<div id=”app”>
<form v-on:keyup.enter.prevent.stop=”handleForm”>
<input type=”text” v-model=”username” placeholder=”Username”>
<input type = password v-model=”password”>
<input type=”button” value=”Submit”>
</form>
<pre>{{$data | json}}</pre>
</div>

The <pre> element will allow us to see the contents of the VM data object using the special ‘$data’ variable.

An MVVM implementation can be used to develop rich and robust web apps when combined with the proper tools and supporting plugins such as a ‘router’, an a utility to handle ‘HTTP’ requests.

I hope you’ll consider the MVVM architecture and Vue.js for your next project. Thank you for reading.

--

--