JavaScript教程10 - Vue.js

Vue.js

MVVM

什么是MVVM?MVVM是Model-View-ViewModel的缩写。

当我们用Node.js有了一整套后端开发模型后,我们对前端开发也会有新的认识。由于前端开发混合了HTML、CSS和JavaScript,而且页面众多,所以,代码的组织和维护难度其实更加复杂,这就是MVVM出现的原因。

用JavaScript在浏览器中操作HTML,经历了若干发展阶段:

第一阶段,直接用JavaScript操作DOM节点,使用浏览器提供的原生API:

var dom = document.getElementById('name');
dom.innerHTML = 'Homer';
dom.style.color = 'red';

第二阶段,由于原生API不好用,还要考虑浏览器兼容性,jQuery横空出世,以简洁的API迅速俘获了前端开发者的芳心:

$('#name').text('Homer').css('color', 'red');

第三阶段,MVC模式,需要服务器端配合,JavaScript可以在前端修改服务器渲染后的数据。

现在,随着前端页面越来越复杂,用户对于交互性要求也越来越高,想要写出Gmail这样的页面,仅仅用jQuery是远远不够的。MVVM模型应运而生。

MVVM最早由微软提出来,它借鉴了桌面应用程序的MVC思想,在前端页面中,

  • 把Model用纯JavaScript对象表示,
  • View负责显示,两者做到了最大限度的分离。
  • 把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。

执行上面的代码,我们惊讶地发现,改变JavaScript对象的状态,会导致DOM结构作出对应的变化!这让我们的关注点从如何操作DOM变成了如何更新JavaScript对象的状态,而操作JavaScript对象比DOM简单多了!

这就是MVVM的设计思想:关注Model的变化,让MVVM框架去自动更新DOM的状态,从而把开发者从操作DOM的繁琐步骤中解脱出来!

安装Vue

安装Vue有很多方法,可以用npm或者webpack。但是我们现在的目标是尽快用起来,所以最简单的方法是直接在HTML代码中像引用jQuery一样引用Vue。可以直接使用CDN的地址,例如:

<script src="https://unpkg.com/vue@2.0.1/dist/vue.js"></script>

也可以把vue.js文件下载下来,放到项目的/static/js文件夹中,使用本地路径:

<script src="/static/js/vue.js"></script>

这里需要注意,vue.js是未压缩的用于开发的版本,它会在浏览器console中输出很多有用的信息,帮助我们调试代码。当开发完毕,需要真正发布到服务器时,应该使用压缩过的vue.min.js,它会移除所有调试信息,并且文件体积更小

编写MVVM

如果打开浏览器console,因为我们用代码window.vm = vm,把VM变量绑定到了window对象上,所以,可以直接修改VM的Model:

window.vm.name = 'Bob'

执行上述代码,可以观察到页面立刻发生了变化,原来的Hello, Robot!自动变成了Hello, Bob!。Vue作为MVVM框架会自动监听Model的任何变化,在Model数据变化时,更新View的显示。这种Model到View的绑定我们称为单向绑定。

单向绑定

在Vue中,可以直接写{{ name }}绑定某个属性。如果属性关联的是对象,还可以用多个.引用,例如,{{ address.zipcode }}。

另一种单向绑定的方法是使用Vue的指令v-text,写法如下:

<p>Hello, <span v-text="name"></span>!</p>

这种写法是把指令写在HTML节点的属性上,它会被Vue解析,该节点的文本内容会被绑定为Model的指定属性,注意不能再写双花括号{{ }}。

双向绑定

单向绑定非常简单,就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新。

有单向绑定,就有双向绑定。如果用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。

什么情况下用户可以更新View呢?填写表单就是一个最直接的例子。当用户填写表单时,View的状态就被更新了,如果此时MVVM框架可以自动更新Model的状态,那就相当于我们把Model和View做了双向绑定。

双向绑定最大的好处是我们不再需要用jQuery去查询表单的状态,而是直接获得了用JavaScript对象表示的Model。

  • 处理事件

当用户提交表单时,传统的做法是响应onsubmit事件,用jQuery获取表单内容,检查输入是否有效,最后提交表单,或者用AJAX提交表单。

现在,获取表单内容已经不需要了,因为双向绑定直接让我们获得了表单内容,并且获得了合适的数据类型。

响应onsubmit事件也可以放到VM中。我们在元素上使用指令:

<form id="vm" v-on:submit.prevent="register">

其中,v-on:submit="register"指令就会自动监听表单的submit事件,并调用register方法处理该事件。使用.prevent表示阻止事件冒泡,这样,浏览器不再处理的submit事件。

因为我们指定了事件处理函数是register,所以需要在创建VM时添加一个register函数:

var vm = new Vue({
    el: '#vm',
    data: {
        ...
    },
    methods: {
        register: function () {
            // 显示JSON格式的Model:
            alert(JSON.stringify(this.$data));
            // TODO: AJAX POST...
        }
    }
});

在register()函数内部,我们可以用AJAX把JSON格式的Model发送给服务器,就完成了用户注册的功能

同步DOM结构

除了简单的单向绑定和双向绑定,MVVM还有一个重要的用途,就是让Model和DOM的结构保持同步。

使用MVVM时,当我们更新Model时,DOM结构会随着Model的变化而自动更新。当todos数组增加或删除元素时,相应的DOM节点会增加

  • 或者删除
  • 节点。
  • 在Vue中,可以使用v-for指令来实现:

    <ol>
        <li v-for="t in todos">
            <dl>
                <dt>{{ t.name }}</dt>
                <dd>{{ t.description }}</dd>
            </dl>
        </li>
    </ol>
    

    需要注意的是,Vue之所以能够监听Model状态的变化,是因为JavaScript语言本身提供了Proxy或者Object.observe()机制来监听对象状态的变化。

    但是,对于数组元素的赋值,却没有办法直接监听,因此,如果我们直接对数组元素赋值:

    vm.todos[0] = {
        name: 'New name',
        description: 'New description'
    };
    

    会导致Vue无法更新View。

    正确的方法是不要对数组元素赋值,而是更新:

    vm.todos[0].name = 'New name';
    vm.todos[0].description = 'New description';
    

    或者,通过splice()方法,删除某个元素后,再添加一个元素,达到“赋值”的效果:

    var index = 0;
    var newElement = {...};
    vm.todos.splice(index, 1, newElement);
    

    Vue可以监听数组的splice、push、unshift等方法调用,所以,上述代码可以正确更新View。

    集成API

    在上一节中,我们用Vue实现了一个简单的TODO应用。通过对Model的更新,DOM结构可以同步更新。

    现在,如果要把这个简单的TODO应用变成一个用户能使用的Web应用,我们需要解决几个问题:

    • 用户的TODO数据应该从后台读取;
    • 对TODO的增删改必须同步到服务器后端;
    • 用户在View上必须能够修改TODO。

    第1个和第2个问题都是和API相关的。只要我们实现了合适的API接口,就可以在MVVM内部更新Model的同时,通过API把数据更新反映到服务器端,这样,用户数据就保存到了服务器端,下次打开页面时就可以读取TODO列表。

    在api.js文件中,我们用数组在服务器端模拟一个数据库,然后实现以下4个API:

    • GET /api/todos:返回所有TODO列表;
    • POST /api/todos:创建一个新的TODO,并返回创建后的对象;
    • PUT /api/todos/:id:更新一个TODO,并返回更新后的对象;
    • DELETE /api/todos/:id:删除一个TODO。

    和上一节的TODO数据结构相比,我们需要增加一个id属性,来唯一标识一个TODO。

    准备好API后,在Vue中,我们如何把Model的更新同步到服务器端?

    • 有两个方法,一是直接用jQuery的AJAX调用REST API,不过这种方式比较麻烦。
    • 第二个方法是使用vue-resource这个针对Vue的扩展,它可以给VM对象加上一个 r e s o u r c e 属 性 , 通 过 resource属性,通过 resourceresource来方便地操作API。

    使用vue-resource只需要在导入vue.js后,加一行

    <script src="https://cdn.jsdelivr.net/vue.resource/1.0.3/vue-resource.min.js"></script>
    

    在线电子表格

    利用MVVM,很多非常复杂的前端页面编写起来就非常容易了。这得益于我们把注意力放在Model的结构上,而不怎么关心DOM的操作。

    MVVM的适用范围

    从几个例子我们可以看到,MVVM最大的优势是编写前端逻辑非常复杂的页面,尤其是需要大量DOM操作的逻辑,利用MVVM可以极大地简化前端页面的逻辑。

    但是MVVM不是万能的,它的目的是为了解决复杂的前端逻辑。对于以展示逻辑为主的页面,例如,新闻,博客、文档等,不能使用MVVM展示数据,因为这些页面需要被搜索引擎索引,而搜索引擎无法获取使用MVVM并通过API加载的数据。

    所以,需要SEO(Search Engine Optimization)的页面,不能使用MVVM展示数据。不需要SEO的页面,如果前端逻辑复杂,就适合使用MVVM展示数据,例如,工具类页面,复杂的表单页面,用户登录后才能操作的页面等等。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值