Vue is a popular JavaScript framework for web apps with easy binding between data in memory and the user interface. Now Weex allows us to code native mobile apps using the Vue framework!
Why do we use Vue and other data binding frameworks like Angular and React? What's so special about them? We use them to ensure that application data which is stored in memory stays in sync with the user interface and vice versa.
We also use these frameworks to enable us to build applications very quickly, and in a way that is optimized for performance.
In this tutorial I'll show you how to use the Vue framework, in particular how to understand its concepts of data binding and templates. Then, I'll go on to introduce the Weex platform, for coding native mobile apps using Vue!
Data Binding
Let's look at a simple example to understand how these frameworks can actually save us time. What we want is a simple input field that stays in sync with our application data. Our app itself can change the data programmatically, and the user can change it via user input, so we need to be watching both the UI and application data.
Writing code that would support this data binding would be verbose. We would need to create event listeners and proxy objects and observables to capture any changes in the application data. And these complexities just grow and grow as more types of data and inputs are added. Vue and other data binding frameworks prevent us having to write all of that binding code.
With Vue, if our user changes some input data, it will sync back to the application data like so:
Or if the application changes the data, it will update the user interface like this:
When we keep the user interface and the app data together in sync, it means our app does exactly what we expect it to do. Vue will manage all of this and allow other powerful data binding processes to occur.
Getting Set Up
Now that we know why we use these frameworks, let's set up a simple Vue application to run some examples. Create a new HTML file anywhere on your computer and paste the following code into it:
<!DOCTYPE html><html><head><title>Tuts+ Vue</title><script src="https://unpkg.com/vue/dist/vue.min.js"></script></head><body><div id="app"></div><script> var app = new Vue({ el: '#app' });</script></body></html>
This is a simple HTML file that links to the Vue JS library. It contains a div
element with the ID of app
. Inside the script tags we have a variable called app
that we use to point to our view—I'll explain this part later.
Then we create a new Vue instance, or "view". This constructor tells the framework which element will contain our application UI and keep it in sync with the application data.
Now double click on the HTML file to open it in the browser, and open the browser console window.
Text Interpolation
Text interpolation lets us embed expressions in our HTML code that will be interpreted when the page is rendered. The expressions are live, so if the data they depend on is changed, the page will be updated in real time. This is known as declarative rendering, which allows us to place expressions anywhere within an element's content. Let's review with a simple example.
JS
<script> var app = new Vue({ el: '#app', data: { message: "Hello world" } });</script>
Our JavaScript code now contains a data
object that will store all of our application data for this view. Within it, I've created the message
property with the string "Hello world"
.
Next, let's display this property in the HTML.
HTML
<div id="app"><pre style="font-family: 'helvetica'; "> {{ message }} {{ message.split('').reverse().join('') }} </pre></div>
The expressions are indicated with double braces syntax. Vue JS manages the dependencies of each expression and updates the page live if they change. In our case, we have two expressions, with the message
property as a dependency of each one. The first expression {{ message }}
just displays the message property. The second {{ message.split('').reverse().join('') }}
expression takes the message property, and then:
- Splits the string into an array:
[ "h","e","l","l","o"," ","w","o","r","l","d" ]
- Reverses the order of the array:
[ "d","l","r","o","w"," ","o","l","l","e","h" ]
- Joins the array together to get
"dlrow olleh"
, which is the same message but printed backwards.
Now open the browser and refresh the HTML page. Then open the browser's console window and assign app.message
a new value and see how the output is updated in the browser.
You can also use math in template expressions, or structured data in objects. Actually, as you might have guessed, Vue expressions are just JavaScript. Access to global variables is sandboxed, though, so you can access Math
, but not window
. This helps keep your apps safe—and your users too.
By using Vue with just a few lines of code, we can have advanced two-way data binding. This ensures that the user interface and the application data are in sync with relative ease.
Directives
Directives are another way of binding data in our views. We can use them to bind application data to attributes, events, input fields, and repeatable data. Let's go through each directive and discover how they work.
v-bind
: bind an attribute valuev-model
: bind app data to an input element like atextarea
v-on
: define an event handlerv-for
: bind to an array or object
v-bind
Directive
The v-bind
directive is used for attribute data binding. It allows us to bind application data to an attribute's value. Think of it like text interpolation but within an attribute. You can bind class
, id
, value
or any other attribute with the v-bind
directive.
For this example, I would like to bind our application data to the data-attr
attribute using the v-bind
directive v-bind:data-attr
.
JS
<script> var app = new Vue({ el: '#app', data: { number: 20, object: { type: "Full Name Object", names: ["Lawrence","Anothy","Turton"] } } });</script>
HTML
<div id="app"><div v-bind:data-attr=" object.type "> {{ object.type }}</div><div v-bind:data-attr=" object.names "> {{ object.names }}</div><div v-bind:data-attr=" number * 20 / 2 "> {{ number * 20 / 2 }}</div><div v-bind:data-attr=" [ object.type, object.names, number * 20 / 2 ] "> {{ [ object.type, object.names, number * 20 / 2 ] }}</div></div>
In the example above, we bound an attribute called data-attr
to a series of different data sources. First, we bound it to the type
and names
properties of object
. Then we bound it to a math expression, and then joined all the bindings together into a single array attribute.
Take a look at the output in the browser: you can click on the Elements tab to see the output of each attribute's value.
Again, you can change the application data in the console to see the data binding process.
Think of the v-bind
directive as allowing expressions in attribute values. This is incredibly powerful and easy to establish with the Vue library.
v-model
Directive
This directive is used specifically to keep the application data in sync with input fields, text areas, and selection elements. Here's an example:
JS
<script> var app = new Vue({ el: '#app', data: { message: "message string", selected:"", checkedNames: [] } });</script>
HTML
<div id="app"><input type="text" v-model="message"><textarea v-model="message"></textarea><hr><select v-model="selected"><option disabled value="">Select a name</option><option>Jack</option><option>John</option><option>Mike</option></select><span>Selected: {{ selected }}</span><hr><input type="checkbox" id="jack" value="Jack" v-model="checkedNames"><label for="jack">Jack</label><input type="checkbox" id="john" value="John" v-model="checkedNames"><label for="john">John</label><input type="checkbox" id="mike" value="Mike" v-model="checkedNames"><label for="mike">Mike</label><select v-model="checkedNames" multiple><option>Jack</option><option>John</option><option>Mike</option></select><br><span>Selected Names: {{ checkedNames }}</span></div>
For the first section of this page, we have a text input field and text area, both of which have the v-model
directive that keeps these input fields in sync with the message
property, using v-model="message"
. That way, if you change either one, the model will be updated and then the other input field will be updated. Go ahead and try it out!
In the next section we have a drop-down synced to the selected
property with v-model="selected"
. That way, if the selection is changed, our model will be updated.
Finally, we have a multiple selection. I've shown how to do this in two ways: with multiple checkboxes and with a multiple select input. As we can have multiple values, I've created the checkedNames
array that can store multiple values. The multiple select input and the checkboxes each have a v-model
directive targeting the checkNames
property. Give it a try, and they should stay in sync as you make selections.
The v-on
Directive
This directive allows us to attach events to HTML elements. This directive can be used on certain elements that can have input events attached to them like hovering, clicks, text input, key presses, and more. For this example, we'll create a simple button with a click event.
JS
<script> var app = new Vue({ el: '#app', data: { clicked: "" } });</script>
HTML
<div id="app"><button v-on:click=" [ alert('hello'), clicked = 'hello' ] ">Click me!</button> {{ clicked }} </div>
In the v-on
directive, after the colon, we specify the event we want to attach. In this example, when the click
event is fired, we'll run some expressions. First, we open an alert dialog box, and then we change the value of the clicked
property. Note that you can call functions in v-on
expressions.
v-for
Directive
This directive is one of the most powerful of them all. We can watch any object or array for changes and render repeatedly a part of our template code for each property or element found in that object or array. For example, to render an array of names as a list:
JS
<script> var app = new Vue({ el: '#app', data: { names: [ "Lawrence", "John", "Mike", "Justin" ] } });</script>
HTML
<div id="app"><ul><li v-for="name in names">{{ name }}</li></ul></div>
In this example, we first attach the v-for
directive onto the element that you want to repeat. The value of the directive specifies the object or array we want to iterate over (names
) as well as a variable that will contain the value for each iteration (name
). Now, within this repeated element, we can use the name
variable in expressions.
If we then modify the array, for example with a method like push
, sort
or reverse
, the template data will automatically be updated. Try running the example and modify the array in the console window.
Components
The data binding process happens in views. Components are just reusable views that we can repeat throughout our application. Each component must have some template data to be rendered as part of the user interface and some application data. You can optionally include some styling if you want.
Let's use the v-for
directive again to output list items. But this time, we'll make each item a component. We'll give this component a name so that we can target it within our template code: list-item
. Components can also have "registered properties", to which we can assign a value to be assigned when we create the component. In my case, the list-item
component will expect to receive a value for the name
property, defined with props:["name"]
.
Let's now create this component. Please add the following code into your script tags:
JS
Vue.component('list-item', { template: '<li>{{ name }}</li>', props: [ "name" ] });
Also make sure you have the following application data:
var app = new Vue({ el: '#app', data: { names: [ "Lawrence", "John", "Mike", "Justin" ] } });
HTML
<div id="app"><ul><list-item v-for="name in names" v-bind:name="name"></list-item></ul></div>
Here you can see the list-item
component will be repeated for each name found in the array. Each name will be assigned to the name variable which is defined in the v-for
directive. We're passing the name
property to the component using v-bind
.
Each instance is just a copy of the component. We can modify each copy or instance independently of one another. So think of components as the blueprint and the instances as copies made from the blueprint. Here is the end result:
Compilation and the Vue CLI
We've been working with a very simple HTML file and letting Vue interpret everything at run-time. However, Vue does come with a command-line tool. You may be asking yourself why. One reason is that pre-compiled page templates will perform better than templates that Vue interprets at run-time. Another reason is that, if we were to build a large-scale application and try to fit it into one HTML file, it would quickly become unmanageable.
So we need modularity to break down a large application into smaller pieces.
Installing the Vue CLI
To use the command line, you'll need to open up the console window for your operating system.
- For Mac, press Command-Space and then type terminal and hit Return.
- For Windows, search for the command prompt in the startup menu, make sure to right click and "open as administrator".
- For Linux, press Control-Alt-T.
Before proceeding, make sure you have the latest version of Node.js installed. Then we need to install Webpack, which will compress our project's file size, making it faster in our browser. Then we can install the Vue CLI and run the relevant commands for your platform:
Mac & Linux
sudo npm install -g webpack
sudo npm install -g vue-cli
Windows (make sure you run the console as administrator)
npm install -g webpack
npm install -g vue-cli
That's it! We're now ready to start setting up our advanced Webpack project. Firstly, navigate to the directory where we want to create our project, in my case the desktop, and then create the project. You can replace myapp with any project name you'd like.
vue init webpack
myapp
You will be led through a series of questions about your project, prompting you to fill in data like title and description and asking you whether to install third-party plugins. For this example, you can answer no to all of the optional extras. Once it's created, we need to install the dependencies, so navigate to the project directory, and we'll run the install command.
cd
myapp
npm install
Let NPM install all the dependency packages, and then we're ready to carry on.
Creating a Vue Project
Once the packages have been installed, we can then run the development server by typing npm run dev
. Your browser window should open, displaying the following page.
We won't go through the structure of the entire project, but when you open up the myapp directory you will see the src directory. It contains an App.vue file, a main.js file and, in the components directory, the Hello.vue file.
The Vue files are components. The main.js file configures the initial view and potentially other configurations as well. Let's take a look at the App.vue
and Hello.vue
files.
Here you can see each Vue component is broken down into three parts:
<template>
: the HTML markup that makes up part of the UI.<script>
: application data, filters, methods, computed properties, watchers, and methods.<style>
: the CSS or Sass styling of our components.
Compilation
Compiling all the components together will produce a large-scale application. This means when we're developing, we work on small modular pieces of code, called components, instead of the entire application. In Vue we have single-file components that contain the JavaScript, HTML, and CSS. It'll even take care of transpiling ES6 to ES5, Sass to CSS and Jade to HTML if you choose to use those languages.
You'll notice in the App.vue file, I've highlighted where it imports the Hello.vue component. Components can be nested inside other components!
When compiling, our project is built with the following process:
We're still using the same syntax as in the earlier examples. However, we are now working with smaller Vue files and compiling them together. We also have some more advanced features like the preprocessors and Jade, Sass, ES6 and Webpack compression.
Weex
Now that we understand the Vue library, let's take a quick look to see how we can take our web app and turn it into a native mobile app, installable on iOS or Android.
Weex is a hybrid framework, meaning it allows multiple technologies, just as a hybrid car can use both electric and petrol. In our case, we use JavaScript code from our web app, but we render to a native user interface. Also, from JavaScript we can access the device's native APIs to access hardware like the camera, sensors, and file system.
With Weex, instead of rendering our application to HTML, we use XML. Actually, HTML and XML are very similar, so the syntax will look familiar. This XML will then be converted to native components. Now our JavaScript will be able to talk to those native components just like it talks to the DOM in Vue with HTML. Not only that, but native components can be styled and positioned with CSS including animations, transitions and more, and they can be integrated to the native layer.
That's just a teaser of what Weex can do. In the next tutorials, I'll take you more in depth with Weex, and we'll see how to build some practical cross-platform native apps.
Pros
Vue has a simple syntax and is increasing in popularity very quickly. Weex allows us to build mobile apps using JavaScript and Vue, but still deliver a native app experience.
Cons
Vue itself is stable, but Weex is still in early development—it currently resides in the Apache incubator. But don't worry, Weex will be production ready soon, and it's backed by the tech giant Alibaba. So, if building on a developer preview concerns you, you might wait until Weex reaches full release.
Conclusion
You've now seen how data binding is a key reason for using Vue and similar frameworks. They save us development time and provide a standard way to build applications. You've also seen how to use text interpolation, directives, and events in Vue, and how these features work together to keep app data in sync with the user interface.
We started out with a basic project with only one view. But then we created a more advanced project that had smaller, more modular views called components. Components let us break our project down so it is easier to code and maintain. After, we saw how to use the Vue compiler to allow transpilation of ES6, Jade and Sass into the standard languages, while compressing file sizes to the minimum.
All of this knowledge will help you when you start coding with Weex. Weex will allow us to take our Vue web app and turn it into a mobile app. Weex is a bit different—we use XML with special components, instead of HTML—but we can still use other web technologies, like CSS and JavaScript. That means we don't have to change our application logic from web app to mobile app.
Stay tuned for my next post on Weex development, and in the meantime, check out some of our other posts on mobile app development with web technologies.
- Ionic 2Introduction to Ionic 2
- IonicHow to Create a Camera App With Ionic 2
- React NativePractical Animation Examples in React Native
- React NativeGet Started With React Native Layouts