在公司里帮项目组里开发后台系统的前端项目也有一段时间了。 vue这种数据驱动,组件化的框架和react很像,
从一开始的快速上手基本的开发,到后来开始自定义组件,对element UI的组件二次封装以知足项目需求,期间也是踩了很多坑。
因为未来很长一段时间可能不再会接触前端了,趁着如今对vue还很熟练的时候,赶忙将这期间的收获记录下来。css
按照个人理解,vue的特色在于,高层次的抽象模型,组件化,数据驱动与响应式。
<!--more-->html
注意:本文中全部涉及到{ {
的,实际上不包括中间的空格,由于hexo会无脑把这个语法当成hexo的一种特殊语法 前端
简单的来讲,vue是一套用于前端开发的框架。
学习一门技术首先应该对该技术有着一个清晰正确的认识和思路,不然犹如浮沙之上建高楼。下面就来谈谈我对vue这个框架的理解。vue
vue它的惊艳之处在于,对上,它提供了一套很是优秀的与传统前端大相径庭的前端开发模型,对下,它屏蔽了传统前端开发的各类丑陋的技术。
在实现复杂的页面需求时,vue帮你从传统前端的各类HACK般的奇淫技巧解脱出来,vue提供的抽象开发模型拥有强大的 表达能力,可以如丝顺滑般的完成各类复杂的需求。java
总而言之,vue之于传统前端,相似C语言之于汇编语言,就像C语言提供了一个强大的表达能力强的语言模型同样,vue一样提供了一个强悍的表达前端的框架模型,这是抽象的威力。
所以,学习vue的80%的重心,都在学习这个强悍的vue模型上。python
从我我的对vue的理解,它的几个重要特色有:react
它还有几个其它的的特色:webpack
下面的例子定义了一个简单的组件,x-my-component。
因为是须要兼容easy UI的后台系统,该项目并不能使用到webpack + babel + es6等技术,所以我在vue上的经验大都是使用原生的js编写的,git
<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>
{ { message }}
表示将数据message绑定到视图的这个地方来。x-my-component
全局组件。因为vue是组件化的,组件能够层层嵌套。不过,最终的根节点得是app节点,这样才能渲染出结果。它的定义方式不太相同:es6
<div id="app"> <x-my-component></x-my-component> </div> <script> var app = new Vue({ el: '#app', }); </script>
从数据驱动的观点,咱们很容易分析出数据流向:
数据源 --> vue对象 --> DOM
<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>
{ {}}
的语法就能够了。v-bind
语法。上面将 message
数据绑定到了title属性上。v-bind:title
可直接缩写为 :title
。-v-html
语法,绑定原始的html数据。在传统的前端编程中,须要仔细预防的一点是xss攻击。xss攻击的原理是:
所以,为预防xss,任何用户给定的数据展示到页面上都须要仔细的处理。可是若是使用vue,就没必要太操心这个问题。
由于,vue提供了一个更高层次的前端模型,全部的业务代码都须要经过vue处理。咱们只须要看vue对xss的处理状况就能够了。
从上面咱们能够看到,数据到视图渲染中必须使用vue的插值语法:
<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>
v-on
语法,绑定事件。按钮的数据传入到vue对象中。v-on:click
可缩写成 @click
。v-model
语法,将表单的数据传入到vue对象中。v-model的数据流动是双向的,至关于:value数据绑定和@input事件绑定的语法糖。可以与用户交互的组件都可以产生数据。当用户操做组件时,组件的相应事件被触发,进而执行绑定到事件的相应函数。
在函数内部你能够作任何处理逻辑,好比说改变vue对象记录的状态,也就是数据。
那么,这样,一个完整的数据流程就跑通了:
咱们知道,数据被绑定到视图上,视图自己不存储状态,当数据不变时,渲染结果不变;当数据改变时,视图也须要从新渲染。
好了,如今头脑里可能会有一个简单的思路了:
可是,咱们仔细考察下第三步。浏览器的DOM树改变后,浏览器才会真正的从新渲染这个DOM,计算各类css,各类布局,层层调用各类绘图函数从新绘制GUI等等。。。
总而言之,这个步骤是很是很是耗时的。
那么,一个优化的手段是,尽量让真正的DOM改变的最少,这样浏览器只须要渲染最少的结果就能达到效果,提高性能。
所以,vurtual DOM就出现了。以下:
能够看到,整个流程中的一大重点是diff算法。关于DOM的diff算法,我没有接触过。。。。。。。
以前研究过文本diff算法是基于LCS算法的动态规划优化,以后有兴趣能够研究下DOM的diff算法。
从上面咱们知道,当直接设置一个vue属性的值时,会触发getter函数。
实际上,getter函数是js的一个机制。在修改数组或对象时,也有相似的机制保证vue能检测到数据的更新以触发渲染。
然而,有几种状况,因为js的限制没法检测到,实际编程中要特别注意,不然就会感受碰到了一个玄学bug。。。
数组。
this.todos[index] = "B"
。解决方案是:Vue.set(this.todos, index, "B")
,经过vue的函数设置。this.todos.length = 10
。替代方案建议使用不可变数据结构。Vue.set
,删除的话,可使用不可变数据结构。此篇博文梳理了vue的基本特性,可是对于vue最重量级的功能----组件化,没有涉及到。对于组件化的相关梳理留到下篇博文梳理。
注:该文于2018-04-09撰写于个人github静态页博客,现同步到个人segmentfault来。