在公司里帮项目组里开发后台系统的前端项目也有一段时间了。 vue这种数据驱动,组件化的框架和react很像,
从一开始的快速上手基本的开发,到后来开始自定义组件,对element UI的组件二次封装以满足项目需求,期间也是踩了不少坑。
由于将来很长一段时间可能再也不会接触前端了,趁着现在对vue还很熟练的时候,赶紧将这期间的收获记录下来。

按照我的理解,vue的特点在于,高层次的抽象模型,组件化,数据驱动与响应式。
<!--more-->

注意:本文中所有涉及到{ {的,实际上不包括中间的空格,因为hexo会无脑把这个语法当成hexo的一种特殊语法

vue是什么及特点

vue是什么

简单的来说,vue是一套用于前端开发的框架。
学习一门技术首先应该对该技术有着一个清晰正确的认识和思路,否则犹如浮沙之上建高楼。下面就来谈谈我对vue这个框架的理解。

vue它的惊艳之处在于,对上,它提供了一套非常优秀的与传统前端截然不同的前端开发模型,对下,它屏蔽了传统前端开发的各种丑陋的技术。
在实现复杂的页面需求时,vue帮你从传统前端的各种HACK般的奇淫技巧解脱出来,vue提供的抽象开发模型拥有强大的 表达能力,能够如丝顺滑般的完成各种复杂的需求。

总而言之,vue之于传统前端,类似C语言之于汇编语言,就像C语言提供了一个强大的表达能力强的语言模型一样,vue同样提供了一个强悍的表达前端的框架模型,这是抽象的威力。
因此,学习vue的80%的重心,都在学习这个强悍的vue模型上。

vue的特点

从我个人对vue的理解,它的几个重要特点有:

  1. 抽象的组件。这是vue框架模型中的一个基础,vue的一切都是基于vue组件的。你在vue组件上可以使用vue提供的各种特性,vue会将其转换成浏览器能够识别的结果通过浏览器渲染出来。
  2. 数据驱动。这是vue的理念之一,数据才是项目的核心,也是状态的最终保存者。而视图,只不过是一种能够由数据延迟计算出来的最终结果而已,它本身不存储状态。
  3. 响应式。既然渲染结果只是数据的衍生产物,那么当数据改变时,渲染结果自然而然的也要改变。这种机制就是响应式。
  4. 组件化。vue本身提供的 抽象特性 。从我个人的理解来看,自定义组件在vue中的地位,类似于函数在C,java之类的语言之中的地位。

它还有几个其它的的特点:

  1. 易用和功能兼顾。在我传统的思维里,易用的东西一般会牺牲一部分功能,而功能强大的东西会需要很大的成本学习,鱼和熊掌不可兼得。
    然而vue用实际行动狠狠给了我一耳光,只要模型设计的正交完美,完全能够兼顾易用性和功能性。
  2. 与传统前端的良好兼容。
    我目前所做的项目中,由于需求的复杂化项目需要从easy UI迭代到vue,原本我做好了大刀阔斧大规模重构的准备,不过,经过查阅文档和几个小demo实验我发现,这玩意居然能够和传统前端并存!
    结果是非常令人开心的,我逐步的,慢慢的将项目从easy UI迭代到vue版本,一个页面一个页面的替换,对项目的影响降低到了最小。

组件定义

下面的例子定义了一个简单的组件,x-my-component。
由于是需要兼容easy UI的后台系统,该项目并不能使用到webpack + babel + es6等技术,因此我在vue上的经验大都是使用原生的js编写的,

<div id="x-my-component"><div>{ { message }}</div>
</div><script>
Vue.component('x-my-component', {template: '#x-my-component',data: function () {return {message: 'Hello Vue!'};}
});
</script>
  1. 可以看见一个组件分为两部分:视图部分,和数据部分。
  2. 视图部分使用html定义,但是vue会对一些特别的语法赋予vue自己的意义。如 { { message }} 表示将数据message绑定到视图的这个地方来。
  3. 这里是使用原生js编写的,因此数据部分和视图部分通过id选择器关联起来,定义了一个x-my-component全局组件。
  4. 从这里就可以初步感受到数据驱动。组件的状态都是存放的数据中的,而视图只负责渲染,本身不保存状态。
    当数据不变时,渲染结果一定不变;当数据改变时,渲染结果就要发生改变。

由于vue是组件化的,组件可以层层嵌套。不过,最终的根节点得是app节点,这样才能渲染出结果。它的定义方式不太相同:

<div id="app"><x-my-component></x-my-component>
</div>
<script>
var app = new Vue({el: '#app',
});
</script>
  1. 从这里可以看出,自定义的全局组件在vue的其它组件中可以直接使用,就像使用一个已经存在的html标签一样。

 数据绑定

从数据驱动的观点,我们很容易分析出数据流向:
数据源 --> vue对象 --> DOM

文本绑定,html绑定及xss攻击

<div id="x-my-component"><span v-bind:title="message">{ { message }}{ { message.split('').reverse().join('') }}</span><span :title="message"> </span><div v-html="rawHtml"></div>
</div>
<script>
Vue.component('x-my-component', {template: '#x-my-component',data: function () {return {message: 'Hello Vue!',rawHtml: '<s>deleted!</s>'};}
});
</script>
  1. 将数据绑定到一般的内容上,用简单的 { {}} 的语法就可以了。
  2. 将数据绑定到属性上,需要用特殊的 v-bind 语法。上面将 message 数据绑定到了title属性上。
    由于这个语法太常用了, v-bind:title 可直接缩写为 :title
  3. -v-html 语法,绑定原始的html数据。
  4. 能绑定的不仅仅是属性键值,还可以是 单个表达式 。注意 只能 是单个表达式。
    这些表达式只能访问全局变量的一个白名单,如Math和Date, 不能访问用户自定义的全局变量

在传统的前端编程中,需要仔细预防的一点是xss攻击。xss攻击的原理是:

  1. 用户输入的数据直接被插入到了DOM中。
  2. 用户输入的数据中含有html或js代码,那么它会直接作为DOM的一部分,被渲染或被执行出来。
  3. 利用这一点,就能够创造一个指向攻击者页面的一张图片或者链接,从而盗取用户的cookies或sid,或者诱导用户点击钓鱼网址。

因此,为预防xss,任何用户给定的数据展现到页面上都需要仔细的处理。但是如果使用vue,就不必太操心这个问题。
因为,vue提供了一个更高层次的前端模型,所有的业务代码都需要通过vue处理。我们只需要看vue对xss的处理情况就可以了。
从上面我们可以看到,数据到视图渲染中必须使用vue的插值语法:

  1. 普通的文本插值。vue会过滤xss攻击,因此可以安全使用。
  2. 使用v-html语法将html插入渲染后的DOM中。这当然会造成xss攻击,因此,使用v-html语法时要非常的小心。

条件与循环

<div id="x-my-component"><p v-if="seen">现在你看到我了</p><ol><li v-for="todo in todos">{ { todo.text }}</li></ol>
</div>
<script>
Vue.component('x-my-component', {template: '#x-my-component',data: function () {return {seen: true,todos: ["A", "B", "C"]};}
});
</script>
  • v-if 绑定的数据,控制此元素是否显示。
  • v-for 绑定的特殊语法,用于控制循环, v-for 的元素会被重复。如上所示,todos是一个数组。

响应式

上面的例子中可以数据绑定的语法,实际上,将数据绑定到视图上的操作并不少见,这些操作,和后端技术常用的模样引擎类似,如python的Jinja2, java的freemarker。
但是,vue的数据绑定的还有一大不同点点是 响应式
由于视图渲染是从数据计算出来的产物,类似一个传入数据传出渲染结果的纯函数,因此,当数据改变时,渲染结果也会改变,所得到的结果是页面展示的界面也会发送改变。

数据绑定还不能完全走通一个vue组件的数据流程,从上面的数据绑定我们可以发现一个事实:
数据由vue对象流向视图进而渲染出来。

那么,反过来呢?如果让数据从页面流向vue对象?这就是下面要说到的事件处理。

事件处理

事件处理的数据流向是这样的:
用户操作页面产生数据 --> 页面 --> vue对象

<div id="x-my-component"><p>{ { message }}</p><button v-on:click="reverseMessage">逆转消息</button><button @click="reverseMessage">逆转消息</button><input v-model="message">
</div>
<script>
Vue.component('x-my-component', {template: '#x-my-component',data: function () {return {message: 'Hello Vue.js!'};},methods: {reverseMessage: function () {this.message = this.message.split('').reverse().join('');}}
});
</script>
  1. 通过 v-on 语法,绑定事件。按钮的数据传入到vue对象中。
    这个语法太常用了,所以 v-on:click 可缩写成 @click
  2. 通过 v-model 语法,将表单的数据传入到vue对象中。v-model的数据流动是双向的,相当于:value数据绑定和@input事件绑定的语法糖。

能够与用户交互的组件都能够产生数据。当用户操作组件时,组件的相应事件被触发,进而执行绑定到事件的相应函数。
在函数内部你可以做任何处理逻辑,比如说改变vue对象记录的状态,也就是数据。

那么,这样,一个完整的数据流程就跑通了:

  1. 用户操作vue组件。
  2. 相应的事件被触发,从而导致绑定事件的函数被触发。
  3. 函数执行业务代码,改变vue组件的状态,也就是前面说到的数据绑定中的数据。
  4. 数据被改变,绑定了该数据的视图也会发送改变,视图被重新渲染。
  5. 页面发生相应改变,用户观察到了自己操作的反馈结果。

再谈响应式

virtual DOM

我们知道,数据被绑定到视图上,视图本身不存储状态,当数据不变时,渲染结果不变;当数据改变时,视图也需要重新渲染。

好了,现在头脑里可能会有一个简单的思路了:

  1. 当数据改变时,触发数据的setter,setter除了更改数据变动外,还需要执行数据更新逻辑。
  2. 重新执行渲染函数,从新的数据中计算出新的渲染结果。
  3. 将渲染结果插入浏览器DOM树中。

但是,我们仔细考察下第三步。浏览器的DOM树改变后,浏览器才会真正的重新渲染这个DOM,计算各种css,各种布局,层层调用各种绘图函数重新绘制GUI等等。。。
总而言之,这个步骤是非常非常耗时的。

那么,一个优化的手段是,尽可能让真正的DOM改变的最少,这样浏览器只需要渲染最少的结果就能达到效果,提升性能。
因此,vurtual DOM就出现了。如下:

  1. 当数据改变时,触发数据的setter,setter除了更改数据变动外,还需要执行数据更新逻辑。
  2. 重新执行渲染函数,从新的数据中计算出新的渲染结果。
  3. 渲染结果被放在virtual DOM中,vue将新的DOM和就的DOM进行diff。
  4. 将diff后的差异结果更新到真正的浏览器DOM树中。

可以看到,整个流程中的一大重点是diff算法。关于DOM的diff算法,我没有接触过。。。。。。。
之前研究过文本diff算法是基于LCS算法的动态规划优化,之后有兴趣可以研究下DOM的diff算法。

数据更新检测的坑

从上面我们知道,当直接设置一个vue属性的值时,会触发getter函数。
实际上,getter函数是js的一个机制。在修改数组或对象时,也有类似的机制保证vue能检测到数据的更新以触发渲染。

然而,有几种情况,由于js的限制无法检测到,实际编程中要特别注意,否则就会感觉碰到了一个玄学bug。。。

  1. 数组。

    1. 利用索引来直接设置数组元素。如 this.todos[index] = "B"。解决方案是:Vue.set(this.todos, index, "B"),通过vue的函数设置。
    2. 直接修改数组的长度。如 this.todos.length = 10。替代方案建议使用不可变数据结构。
  2. 对象。vue无法检测到对象属性的添加或删除。添加的话,可以使用Vue.set,删除的话,可以使用不可变数据结构。

最后

此篇博文梳理了vue的基本特性,但是对于vue最重量级的功能----组件化,没有涉及到。对于组件化的相关梳理留到下篇博文梳理。

注:该文于2018-04-09撰写于我的github静态页博客,现同步到我的segmentfault来。

vue总结系列--数据驱动和响应式相关推荐

  1. Vue.js 框架源码与进阶 - Vue.js 源码剖析 - 响应式原理

    文章目录 一.准备工作 1.1 Vue 源码的获取 1.2 源目录结构 1.3 了解 Flow 1.4 调试设置 1.5 Vue 的不同构建版本 1.6 寻找入口文件 1.7 从入口开始 二.Vue ...

  2. 细说 Vue.js 3.2 关于响应式部分的优化

    大家好,我是若川.上一篇写的是:初学者也能看懂的 Vue3 源码中那些实用的基础工具函数.今天再分享一篇 Vue 3.2 的文章. 学习源码整体架构系列.年度总结.JS基础系列 背景 Vue 3 正式 ...

  3. vue新增属性是否会响应式更新?

    原文地址 在开发过程中,我们时常会遇到这样一种情况:当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的. 根据官 ...

  4. Vue深入学习3—数据响应式原理

    1.数据响应式原理 1.1.MVVM是什么? 简单来说,就是数据变了,视图也会跟着变,首先你得定义一个带有{{ }}的模板Model,当数据中的值变化了,视图View就会跟着变化:视图模型View-m ...

  5. vue 数组转集合_思想实验:如何在Vue中使localStorage具有响应式?

    响应式是Vue的最大特色之一.如果你不知道幕后情况,它也是最神秘的地方之一.例如,为什么它不能用于对象和数组,而不能用于诸如 localStorage 之类的其他东西? 让我们回答这个问题,在解决这个 ...

  6. vue set方法_Vue 数据响应式

    数据响应式是指当数据改变后,会通知到使用该数据的代码.例如,视图渲染中使用了数据,数据改变后,视图也会自动更新. new Vue内部对data的代理和监听 data的bug 由于使用了Object.d ...

  7. vue是怎么实现数据响应式的?

    数据响应式原理核心就是采用了 defineReactive,defineReactive里的Object.defineProperty对每个属性进行监听对数据进行拦截,把这些属性全部转成getter/ ...

  8. 浅谈vue 之双向绑定和响应式(vue的响应式)

    初识vue小伙伴通常都会被他的双向绑定所感叹,神奇?方便?而且在不少的面试中也会被面试官问到,上来就是:请问vue双向绑定的原来是什么?我们就来研究研究这是个什么东西: v-model 官方其实已经说 ...

  9. vue --- 2.0数据的响应式的一种实现

    初识: 实际上是通过Object.defineProperty()方法来实现的 talk is cheap, show your code let obj = {}; Object.definePro ...

最新文章

  1. react实现全选、取消全选和个别选择
  2. [二叉树]已知后序/中序遍历,求先序遍历
  3. 使用Storm实现WordCount
  4. Eclipse Color Theme
  5. python爬虫笔记(三):提取(二)
  6. FPGA硬件学习基础知识点总结(1)
  7. exception日志 php_PHP 错误与异常的日志记录
  8. oracle未找到时区,解决ORA-01882:未找到时区区域%s
  9. MATLAB编程与应用系列-第3章 矩阵运算(4)
  10. leancloud 怎么绑定域名_云引擎支持绑定加速域名 | LeanCloud 八月变化
  11. EPS中编写第一个程序
  12. 转载:Rootkit总结
  13. 【MATLAB编程实例练习】-(34)直角三角形边长问题
  14. JAVA新生入学报到管理系统计算机毕业设计Mybatis+系统+数据库+调试部署
  15. 操作系统之线程和进程
  16. 【云原生 | Docker 基础篇】03、Docker 阿里云镜像加速器
  17. 万万没想到!TCP/IP 协议会有这么多漏洞
  18. Log4j-自动发送日志邮件
  19. 学习u3d的几个工具和文档
  20. mocha ReferenceError: describe is not defined 问题解决

热门文章

  1. Redis:Redis的简单使用
  2. 聪明的投资者 by 格雷厄姆
  3. Node脚手架编写初学者教程
  4. 7个标准--选安全靠谱的聚合支付公司!
  5. 数字图像处理实验之对比度拉伸、直方图均衡化和规定化
  6. 2023年无线蓝牙耳机排行榜,十款无线蓝牙耳机品牌推荐
  7. 王者荣耀s18服务器维护中,王者荣耀:S18开启仅20天,三大数值怪引发众怒,天美也束手无策...
  8. 图神经网络之图卷积网络——GCN
  9. 引导滤波matlab代码实现,引导图滤波(Guided Image Filtering)原理以及OpenCV实现
  10. 2020年3月23日阿里笔试题