简明 Vue.js 教程(1)

Vue.js 是一个用于构建交互式 Web 界面的 JavaScript 开发库,通过简洁的 API 提供高效的数据绑定机制和灵活的组件系统。类似于 AngularJS 等优秀前端框架,Vue.js 提供了 MVVM 数据绑定以及一个可组合的组件系统。从技术上讲,Vue.js 着眼于在 MVVM 模式中的视图模型层(VM),通过双向数据绑定连接视图和模型,实际的 DOM 操作和输出格式被抽象为指令和过滤器。相比其它的 MVVM 框架,Vue.js 更容易上手。

本系列的主要目的是以示例为导向,通过一个个例子学习 Vue.js 的开发。我们会假设你已经熟悉前端页面开发的相关知识,并且可能会有一点 jQuery 的基础。

下面开始我们的学习!

Vue.js 不支持 IE8 及其以下版本,因为 Vue.js 使用了 IE8 不能实现的 ECMAScript 5 特性。 Vue.js 支持所有兼容 ECMAScript 5 的浏览器

我们有很多种方法将 Vue.js 引入我们的页面。对于简单的页面,通常可以选择直接导入 Vue.js 文件;对于大型应用,我们可以考虑使用诸如 Webpack 或 Browserify 等 CommonJS 模块打包器配合使用。在开始学习的时候,直接导入 JS 文件是一个不错的选择:这样可以明显降低我们的学习曲线。

我们可以在 Vue.js 的安装页面找到下载链接。在学习的时候使用开发版本,可以看到完整的警告信息。下面,我们编写第一个页面:

<!DOCTYPE html>
<html>
    <head>
        <title>Brief Vue.js</title>
    </head>
    <body>
        <h1>{{ message }}</h1>
        <script src="http://cdn.bootcss.com/vue/1.0.22/vue.js"></script>
        <script>
            Vue.config.debug = true;
            new Vue({
                el: 'body',
                data: {
                    message: 'Hello, world!'
                }
            });
        </script>
    </body>
</html>

这段代码的执行结果如这个页面所示

下面我们来仔细研究下这段代码。

代码很简单,<body>标签中只有一个<h1>元素。注意这个<h1>的内容是“{{message}}”,但运行起来却显示的是“Hello, world!”。很明显,是 Vue.js 帮我们进行了替换。这是 Vue.js 的一个最主要的特性之一:数据绑定。数据绑定的含义是,我们可以将两个数据捆绑在一起,当其中一个发生改变时,另外一个可以跟着发生改变。如何告诉 Vue.js 进行数据绑定呢?来看 JS 部分的代码:

Vue.config.debug = true;
new Vue({
    el: 'body',
    data: {
        message: 'Hello, world!'
    }
});

第一行,我们开启了 Vue.js 提供的调试功能。该功能会在浏览器控制台输出一系列调试信息,以便我们定位错误。
后面的代码也比较简单:使用new运算符创建一个Vue对象;创建时可以传入一个选项对象。在上面的例子中,这个选项对象有两个参数:

  • el:Vue.js 需要处理的根元素,即从该元素开始,其所有子元素都会被 Vue.js 进行处理。这里的el: 'body'说明,从<body>开始,<body>标签中的所有元素都会被 Vue.js 处理。el的类型是一个字符串,可以是标签名字,也可以使用元素 id,其语法类似 CSS 的选择器。
  • data:Vue.js 所需处理的数据。这些数据可以被绑定到el指定的元素中,用于替换{{ }}符号的内容。在这个例子,HTML 中的{{ message }}的内容就会被data中的message字符串替换。data的类型是一个对象,所以你可以指定任意多、任意类型的数据。

代码已经介绍完了,结合前面所说,“Vue.js 着眼于在 MVVM 模式中的视图模型层(VM)”,来看看究竟是什么意思。我们创建的 Vue 对象中的data属性,对应着模型部分,也就是整个页面的模型;视图则是el指定的部分。例子中的数据绑定,将模型与视图绑定在一起,模型发生了变化(例如,有了初始值),视图会跟着发生变化。

Vue.js 提供的是双向数据绑定。前面是模型变化导致视图变化,这是一个方向;所谓“双向”,视图发生变化的时候,模型也会跟着发生变化。看下面的例子:

<!DOCTYPE html>
<html>
    <head>
        <title>Brief Vue.js</title>
    </head>
    <body>
        <h1>{{ message }}</h1>
        <input type="text" v-model="message" value="Hello, world!" />
        <script src="http://cdn.bootcss.com/vue/1.0.22/vue.js"></script>
        <script>
            Vue.config.debug = true;
            new Vue({
                el: 'body',
                data: {
                    message: ''
                }
            });
        </script>
    </body>
</html>

最明显的一点,在创建 Vue 对象时,我们去掉了data属性。这就是说,模型数据是来自视图的。我们在<input>标签中添加了v-model="message"属性,这意味着<input>标签变成了模型,其名字就是 message。那么,前面 HTML 中的<h1>{{ message }}</h1>即与其绑定。值得注意的是,这次,我们是在视图中声明的模型,同时说明,当视图发生变化时,模型也会相应变化(这一点是通过与<h1>{{ message }}</h1>的改变证明的)。代码执行结果如下,修改输入框的文字,观察运行效果

双向数据绑定让我们获得了一种能力,即可以将视图完全交给模型驱动。在很多编程模型中,这都是显而易见的,但却是 web 前端一直欠缺的。通过 Vue.js,我们可以弥补这一缺失的部分。

下面我们将尝试一些真正有趣的事情。

考虑我们希望实现这么一个功能:界面上有一个输入框,当我们输入文字之后,按下回车,输入的内容将生成一个新的列表项,追加在页面下方,同时,输入框清空。这个功能并不复杂,先不管 Vue.js,用 jQuery 试试该怎么实现:

<!DOCTYPE html>
<html>
    <head>
        <title>Breif Vue.js</title>
    </head>
    <body>
        <input id="message-input" type="text" />
        <ul id="result-list"></ul>
 
        <script src="http://cdn.bootcss.com/jquery/2.2.3/jquery.min.js"></script>
        <script>
            $(function () {
                var $messageInput = $("#message-input");
                $messageInput.keydown(function(e) {
                    if (e.keyCode == 13) {
                        $("#result-list").append("<li>" + $messageInput.val() + "</li>");
                        $messageInput.val("");
                    }
                });
            });
        </script>
    </body>
</html>

jQuery 中没有回车事件,所以我们只能使用keydown事件来检测用户按下的是不是回车键。回车键的代码是 13,因此在keydown回调函数中,首先要判断e.keyCode是不是 13,如果是的话,则取出<input>标签的值,创建一个<li>标签,追加到<ul>

再来看 Vue.js 是如何实现的:

<!DOCTYPE html>
<html>
    <head>
        <title>Breif Vue.js</title>
    </head>
    <body>
        <input type="text" v-model="item" @keyup.enter="add" />
        <ul v-for="aItem in items">
            <li>{{ aItem }}</li>
        </ul>

        <script src="http://cdn.bootcss.com/vue/1.0.22/vue.js"></script>
        <script>
            Vue.config.debug = true;
            new Vue({
                el: 'body',
                data: {
                    item: '',
                    items: []
                },
                methods: {
                    add: function () {
                        this.items.push(this.item);
                        this.item = "";
                    }
                }
            });
        </script>
    </body>
</html>

代码运行结果如这个页面所示

<input>标签除了v-model,还有一个新的属性:@keyup.enter@v-on的简写,因此,@keyup.enter也可以写作v-on:keyup.enter。这是 Vue.js 的事件处理函数的写法,表示设置keyup事件的回调函数为addkeyup是一个事件的名字,后面.enter是按键修饰符,表示当按下的按键是enter时,才去回调这个函数。这就是实现了前面 jQuery 的按键判断。回调函数add是在Vue对象的methods属性定义。add函数取出输入的item的值存入items数组,然后清空item的值。

<ul>标签也有新的属性:v-for。顾名思义,这是用来循环遍历一个集合的。v-for="item in items"中,items是一个数组,即每次取出items中的一个元素,命名为item。下面的<li>{{ item }}</li>则是类似模板的语句,将上面v-for取出的item输出。items数据模型在后面的data属性中定义。整个应用其实定义了两个数据模型:item使用v-model定义,items使用data定义。注意,由于 Vue.js 是双向数据绑定,因此,当add函数向items添加了新的数据时,在v-for的作用下,Vue.js 会自动为我们生成新的<li>标签。

这个例子虽然简单,但是它清晰地表现了 jQuery 和 Vue.js 开发的重要区别:jQuery 是传统的 DOM 操作,当发生了感兴趣的事件时,你需要告诉 jQuery 如何操作 DOM,比如如何添加新的<li>标签;Vue.js 则是一切以数据为中心,我们关心的只是数据,我们操作的也只是数据,我们只对数据进行修改,一旦数据发生改变,Vue.js 自动更新界面的显示,不需要我们告诉 Vue.js 如何操作 DOM。

让我们把这个例子弄得再复杂一些:我们需要新增加的每一行都要有一个按钮,点击之后可以删除该行。基于前面的阐述,这个界面的实现应该没有问题。但是,如何实现删除呢?思路很简单:考虑到 Vue.js 从来都是双向数据绑定,因此,只需要将this.items中的对应项删除即可。但是,怎么由按钮找到当前项?v-for其实提供了额外的内置变量,以满足类似的需求。这里,我们需要使用v-for提供的$index变量。相应代码如下:

<!DOCTYPE html>
<html>
    <head>
        <title>Breif Vue.js</title>
    </head>
    <body>
        <input type="text" v-model="item" @keyup.enter="add" />
        <ul v-for="aItem in items">
            <li>{{ aItem }} <button @click="remove($index)">X</button></li>
        </ul>
 
        <script src="http://cdn.bootcss.com/vue/1.0.22/vue.js"></script>
        <script>
            Vue.config.debug = true;
            new Vue({
                el: 'body',
                data: {
                    item: '',
                    items: []
                },
                methods: {
                    add: function () {
                        this.items.push(this.item);
                        this.item = "";
                    },
                    remove: function (index) {
                        this.items.splice(index, 1);
                    }
                }
            });
        </script>
    </body>
</html>

注意,在<button>标签中,我们使用了@click事件处理函数。与前面的函数名不同,@click的参数使用的是一个 JavaScript 语句。Vue.js 允许这种写法,但是限制为只能是一条语句。这个语句的参数$index代表当前循环的索引,正如前面所说,这是由v-for提供的。代码运行结果如这个页面所示

One Response

  1. hezf 2016年5月28日

Leave a Reply