MVVM
MVVM模式包含三个部分:
M 模型model
V 视图 view
VM 视图模型 view-model
特点:实现了数据双向绑定
数据由模型进入视图,通过数据绑定实现的
数据由视图进入模型,通过事件监听实现的
MVVM模式的由来
早期js被设计的很简单,主要解决一些简单的交互问题。主要的问题就是浏览器兼容性,所以jQuery就出现了,解决了兼容性问题,简化了开发。
随着技术的发展,富客户端应用,单页面应用程序的出现,前端逻辑更加的复杂,因此如何维护好前端的代码,成了主要的问题。所以MVC一类的框架就出现了,让我们将逻辑分成模型,视图和控制器,变得更容易开发和维护。
但是在MVC模式中,开发项目非常的慢,因此MVVM模式就出现了,提供了数据双向绑定技术,极大的提高了开发效率。
1 获取 vue
GitHub:https://github.com/vuejs/vue
在ES5开发中,获取vue.js文件,可以通过bower工具
bower install vue
可以通过npm来安装bower指令
npm install -g bower
在ES6开发中,要获取vue模块
npm install vue
2 体验 vue
vue是基于MVVM模式实现的,因此也包含三个部分
模型:js中的数据对象
视图:页面中的模板视图
视图模型:就是vue实例化对象
实例化vue类的时候,要传递参数对象
通过el属性与页面中的模板绑定上
通过data属性与模型数据绑定上
3 vue 实例化对象
模型中的数据会添加给实例化对象自身,并设置了特性。
并且在_data以及$data属性中,对模型数据做了备份。
当模型中的数据改变,视图会同步更新,这个过程就是vue实例化对象实现的(数据的绑定技术)。
4 数据绑定的实现
vue中,模型中的数据被设置了特性,因此ES5中属性的特性是vue数据绑定技术实现的关键。
vue中数据的绑定是通过ES5中属性的特性实现的。
因此不支持ES5中特性技术的浏览器,是不能使用vue的。
vue是一个运行在高级浏览器下的框架。
5 webpack编译
在nodejs中,使用commonjs规范
在ES6中,使用ES Module规范
ES6文件拓展名可以是.es,也可以是.js等。具体使用哪种方式,要看使用的编辑器支持哪种 。
resolve配置
在resolve配置中,通过alias配置模块入口文件
alias配置有两点作用:
1 可以更改入口文件
2 简化路径的书写
不更改入口文件的话会报这个错误:
原因:在ES6中开发下载vue模块后,正常我们使用的是
目录下面的
文件
但是我们查看package.json文件中vue模块给的默认接口是
这个文件,所以可以通过alias修改入口文件。
在resolve中还可以通过extensions配置文件的默认拓展名
是一个数组,每一个成员代表一个默认拓展名。
6 数据丢失
当修改数据时,如果视图没有更新,那么就说数据丢失了。
注意:数据丢失不是什么好的特性,是框架的bug。
数据绑定的实现原理:
基于ES5中属性的特性实现的, 因此设置了特性的数据是不会丢失的。
所以没有设置特性的数据就丢失了。常见的数据丢失有四类:
第一类:数组中的值类型:用新数组替换原来的数组
第二类:数组中的新成员:用新数组替换原来的数组
第三类:对象中的新属性:用新对象替换原来的对象
第四类:未初始化的:将数据初始化。
$set
作者为了解决数据丢失的问题,提供了一个更加保险的方法:$set.
第一个参数表示数据对象
可以是vue实例化对象,也可以是其它对象
第二个参数表示属性名称
第三个参数表示属性值
7 计算属性数据
定义在data中的模型数据是固定不变的,想在获取数据的时候,动态改变数据,可以使用计算属性数据技术。
静态的数据定义在data属性中:定义的是什么数据,获取的就是什么数据
计算属性数据定义在comptued属性中:定义的是方法,获取的时候,会将执行的结果返回(是计算的)
computed与data的用法是一样的,添加给vue实例化对象自身,并设置了特性,定义的时候都是一个对象
key表示数据名称
value是一个函数
参数和this都指向vue实例化对象,因此通过参数或者this可以获取vue中的其它数据。
注意:必须有返回值,就是获取的数据。
当多次使用计算属性数据的时候,该方法只会执行一次。只有当内部使用的数据发生改变的时候,计算数据数据的方法才会执行一次。
不论是data中定义的数据还是computed中定义的数据都会添加给vue实例化对象自身并设置特性。
为了在模板中,使用模型中的数据,可以使用插值语法:{{}}
插值语法提供了一个真正的js环境,可以直接书写js表达式。
注意:插值语法中的js表达式无法复用,想复用可以放在计算属性数据中(多定义监听器,性能)。
如果逻辑复杂:建议计算属性数据
如果逻辑简单:建议js表达式。
属性上不能使用插值语法,可以通过v-bind指令动态设置
9 属性绑定
不能在元素的属性中使用插值语法。想动态设置属性,要使用属性绑定的技术。
指令:指令就是对DOM元素的拓展,使其具有一定的行为特征(功能)。
指令的属性值都是js环境,可以直接使用js表达式,
属性绑定的语法:v-bind:key=”value”
语法糖:语法糖就是对某个操作的简化,来提高开发效率。
v-bind指令的语法糖是冒号语法糖
v-bind:key=”value” 可以写成 :key=”value”
10 插值指令
v-text:该指令用来设置元素的内容
与插值语法相比:
1 避免插值符号闪烁。
2 只能渲染元素的全部内容,还可以用字符串拼接形式来解决这个问题。
注意:v-text指令与插值语法一样,都不能渲染标签。
v-html:该指令用来渲染带有html标签的文本。
与插值符号相比:
1 避免插值符号闪烁。
2 只能渲染元素的全部内容,还可以用字符串拼接形式来解决这个问题。
3 可以渲染标签。
注意:渲染的内容一定要确保是安全的。否则会导致xss注入的问题。
(xss注入:例如在标签文本中,存在可以执行的脚本文件)
v-once:该指令用来让内容单次渲染。
该指令不需要设置属性值。
该指令会让其所在的元素及其所有子元素上的所有插值与指令只执行一次。
11 插值过滤器
想对插值语法中的数据进行修改,可以使用js表达式,但是如果逻辑很复杂,会导致模板很臃肿。
为了解决臃肿的问题,vue提供了插值过滤器技术。
插值过滤器技术有三个优势:
1 避免模板臃肿的问题。
2 可以复用。
3 可以跨组件使用。
在vue2.0中,作者弱化了过滤器,移除了内置的过滤器。
注意:在2.0中,作者建议用插值表达式以及计算属性数据的形式代替插值过滤器。
例如:vue1.x版本中内置了许多过滤器:
使用也很方便:
页面显示:
12 自定义过滤器
在vue中自定义过滤器有两种方式
全局定义的过滤器可以在任何实例化对象(组件)中使用。
通过Vue.filter(name, fn)
name表示过滤器名称:建议驼峰式命名
fn(data, ...args)表示过滤函数:
data表示处理的数据。
args表示使用过滤器时候传递的参数。
必须有返回值,就是处理的结果
第二种:局部定义:
局部定义的过滤器只能在当前实例化对象(组件)中使用。
在vue实例化对象(组件)中,通过filters属性定义。
filters: { name: fn }
name表示过滤器名称:建议驼峰式命名
fn(data, ...args)表示过滤函数:
data表示处理的数据。
args表示使用过滤器时候传递的参数。
必须有返回值,就是处理的结果
全局定义过滤器的时候,要注意:1 filter方法不能解构。2 要在vue实例化对象之前定义。
使用过滤器
可以在插值语法以及指令中使用插值过滤器。
语法: {{data | 过滤器(参数1, 参数2) | 过滤器2}}
前一个过滤器的输出将作为后一个过滤器的输入
全局定义过滤器:
局部定义过滤器:
13 数据双向绑定
vue实现了数据双向绑定,vue为了简化双向绑定,提供了v-model指令。
属性值就是绑定的数据
注意:
1 只能绑定数据,不能使用表达式
2 绑定的数据必须在模型中定义。如;data等。
例如:表单元素可以与用户交互,因此可以使用v-model指令。
数据双向绑定有两个方向:
数据由模型进入视图:通过数据绑定实现的。为value绑定模型数据
数据由视图进入模型:通过事件监听实现的。监听input事件,更新数据
v-model指令简化了这两个过程,因此也可以看成是语法糖
v-model可以绑定data中的数据,也可以绑定computed中的,绑定计算属性数据时,一定要设置取值器和赋值器方法。
14 v-cloak
用来解决插值符号闪烁的问题。
只需要两步:
第一步 为容器元素设置v-cloak指令(属性)
注意:
1 style标签要定义在容器元素的前面
2 v-cloak只能给容器元素内部的元素使用(包括容器元素)
实现原理:因为style标签要定义在容器元素的前面,此时再加载vue文件前,css代码先生效了
15 单选框
对单选框实现数据双向绑定,也是用v-model指令。
特点:
1 一组单选框绑定同一份数据。
2 选框的值通过value属性定义。
3 此时checked属性失效了。
4 一组单选框的默认值就是绑定数据的值。
data中定义的intrest属性值为"pingpang",此时checked属性就失效了
页面展示:
16 多选框
将input元素的type属性设置为checkbox就可以得到多选框,通过checked属性设置其选中状态。
对多选框实现数据双向绑定,也是用v-model指令。
特点:
1 一组多选框绑定不同的数据,为了访问方面,将其放在同一个命名空间下。
2 选框的值默认是布尔值,通过v-bind:true-value以及v-bind:false-value可以自定义其值:
:true-value:定义选中时候的值 :false-value:定义未选中时候的值。
3 checked属性失效了
4 一组多选框的默认值就是绑定数据的值,如果自定义了:true-value以及:false-value属性,就是自定义数据值。
17 下拉框
通过select元素定义下拉框,通过option元素定义选项,
通过为select元素添加v-model指令实现数据双向绑定。
单选下拉框绑定的是字符串。
多(复)选下拉框绑定的是数组。
通过为select元素设置multiple属性,实现单选下拉框与多选下拉框的切换。
选项的值默认是内容值,设置了value就是value值。
页面显示:
18 数据监听器
vue实现了数据双向绑定,当模型中的数据改变,会被视图监听到。进而同步到视图中。
如果想在js中,监听模型中数据的改变,可以使用监听器技术
在实例化对象中的watch属性中,定义监听器,是一个对象
key 被监听的数据名称
value 当数据改变的时候,执行的回调函数。
第一个参数表示新的值,
第二个参数表示旧的值。
this指向vue实例
注意:watch不仅仅可以监听模型中的数据,实例化对象中,设置了特性的数据都可以监听,例如:路由数据等。
状态监听就是当数据改变的时候,平滑的将其过渡到某个值。
在监听器中,监听数据的变化。
在vue实例对象中定义watch监听器:
事件绑定:vue为了绑定DOM事件,提供了v-on指令。
语法:v-on:click=”fn()”
v-on指令的语法糖是@ ,也可以写成 @click=”fn()”
fn代表事件回调函数,定义在vue实例的methods属性中。
methods中定义的方法跟data中的定义的数据一样,添加实例化对象自身了。
methods中定义的方法,内部的this指向vue实例化对象。
methods中定义的方法不仅仅可以在事件中使用,所有可以获取实例化对象的地方,都可以通过实例化对象来使用该方法。
参数集合
()表示参数集合,可有可无。
如果没有定义参数集合,默认有一个参数,就是事件对象
如果添加了参数集合,默认没有参数,此时使用什么数据可以在参数集合中传递。
想使用事件对象,要传递$event。
vue中事件绑定技术,没有使用事件委托技术,是直接绑定给元素的。因此事件对象是源生的事件对象。
方法定义在vue实例的methods属性中:
21 事件修饰符
使用jQuery的时候,想判断事件绑定的元素与事件触发的元素是同一个元素的功能,要获取事件对象,再通过判断事件对象的e.target是否等于
e.currentTarget,来确定结果,很麻烦。
vue简化了这些流程,让我们在绑定事件的时候就实现这些功能。通过事件修饰符实现。
语法: v-on:click.修饰符=”fn”
“.修饰符”就表示事件修饰符,可以通过多个“.”来同时应用多个修饰符。
stop:实现阻止冒泡的修饰符。
prevent:实现阻止默认行为的修饰符。
once:表示单次触发的修饰符。
self:表示绑定事件的元素与触发事件的元素是同一个元素。
这些修饰符还可以混合使用。
鼠标键修饰符
left:点击鼠标左键
right:点击鼠标右键
middle:点击鼠标中间件
辅助键修饰符
ctrl:点击ctrl辅助键
shift:点击shift辅助键
alt:点击alt辅助键
meta:点击window|command辅助键
键盘事件修饰符
键盘事件:keydown,keyup,keypress(输入有效键)
当绑定键盘事件的时候,可以使用键盘事件修饰符。
有效修饰符:esc, tab, space, enter, delete(delete|backspace),up, down, left, right, 以及所有字母键
22 类的绑定
在vue中,为元素绑定类有三种方式:
:class="{}"
key 表示一组类的名称(可以包含空格,切割成多个类)
value 表示是否保留这组类
:class="[]"
每一个成员代表一组类(可以包含空格,切割成多个类)
:class="str"
类名之间用空格隔开。
类的样式在css文件或者scss文件中定义出来
23 样式的绑定
与绑定类一样,绑定样式也有三种方式
:style="{}" 绑定样式对象
key 表示样式名称,建议使用驼峰式命名
value 表示样式属性值
:style="[]" 绑定多组样式对象
每一个成员是一个对象,代表一组样式
key 表示样式名称,建议使用驼峰式命名
value 表示样式属性值
:style="str" 做样式字符串拼接。
24 条件模板指令
模板指令就是控制元素创建和删除的指令。
条件模板指令
vue模拟了js中的if条件语句,提供了条件模板指令v-if
if条件语句:if () {} else if () {} else {}
所以vue也为v-if指令提供了组合指令:v-if,v-else-if, v-else。
v-if指令的属性值是布尔值
true 表示创建这个元素
false 表示删除这个元素
是真正的创建和删除,不是显示和隐藏
用来显示或者隐藏元素的指令,属性值是布尔值
true 显示元素
false 隐藏元素
通过控制样式“display: none”实现的。
与v-if相比,有两点不同:
1 原理不同:
v-if是真正的创建和删除。 v-show是通过样式实现的显示和隐藏。
2 组合指令:
v-if有组合指令(v-else-if,v-else)。v-show没有组合指令
由于v-show是通过修改样式实现的,因此性能更高。
vue模拟js中的for in循环语句实现了v-for循环模板指令:
有两种用法:
第一种:v-for=”item in data”
第二种:v-for=”(item, index) in data”
v-for和in都是关键字
data表示循环的数据,可以是数字,对象和数组
如果是数字:item 表示数值(从1计数)。 index 表示索引值(从0计数)
如果是对象:item 表示value(属性值)。 index 表示key(属性名称)
如果是数组:item 表示成员值。 index 表示索引值
使用v-for指令的时候,要设置key属性,要求属性值时候唯一的。
可以设置成员值item中的唯一属性,如id等。还可以设置索引值index。建议用成员中的唯一属性。
注意:
1 在vue cli中,必须设置key属性
2 循环中的变量item和index只在循环中生效,循环结束后被销毁。
当想渲染多个兄弟元素的时候,那么就要将指令放在父元素上,这样会导致引入其它的元素。
为了避免引入其它的元素,vue建议使用模板元素。
在html中定义模板元素有两种语法:
第一种:通过script模板标签定义
第二种:html5提供了tempalte模板元素。
vue建议使用template模板元素。
模板元素跟普通的元素一样,可以包含子元素,可以添加属性,可以设置指令等等,但就是不会渲染到页面中,我们将循环指令添加给模板元素,就不会引入其它的元素了。
注意:使用模板元素template,不能设置key属性。
利用以上知识点实现一个邮箱注册登录页面:代码地址点这里
28 过渡
v-show指令和v-if指令,这些指令可以显示隐藏元素或者创建删除元素。
vue允许我们在显示隐藏元素以及创建删除元素过程中,添加过渡效果。
transition元素(组件)是由vue提供的。可以为内部的元素添加过渡效果。
通过name属性设置过渡名称,之后就会根据该名称创建六个类,
例如 name=”aaa”
表示显示的过程(由隐藏的状态变成显示的状态)
.aaa-enter .aaa-enter-to .aaa-enter-active
表示隐藏的过程(由显示状态变成隐藏的状态)
.aaa-leave .aaa-leave-to .aaa-leave-active
基于这六个类,实现css过渡或者动画(借助于css3实现的)
js中定义切换的方法:
css中基于六个类,实现过渡:
入场过渡
通过为transition组件添加appear属性,实现入场过渡:当元素加载的时候,执行动画。
过渡事件
css3过渡和动画有事件,可以通过DOM监听到。
过渡事件:webkitTransitionStart,webkitTransitionEnd
动画事件:webkitAnimationStart,webkitAnimationEnd.
vue实现的过渡也可以监听动画开始与结束的事件:
显示过程:
before-enter:处于隐藏状态;
after-enter:处于显示状态;
enter:显示过程
隐藏过程
before-leave:处于显示状态;
after-leave:处于隐藏状态;
leave:隐藏过程
可以通过v-on指令或者是@语法糖来监听这些事件。
多元素过渡
可以在transition中,定义多个元素,实现多个元素之间的过渡。
内部的元素必须设置key属性,属性值是唯一的。
通过mode属性定义切换模式:
in-out 新元素先执行,再执行当前的元素
out-in 当前的元素先执行,再执行新元素。
29 列表过渡
通过v-for指令渲染列表。
使用v-for指令创建列表元素的时候,如果需要过渡,要使用transition-group组件。
与transition组件的区别是:
transition-group会渲染成一个真实的元素,默认是span,通过tag属性可以自定义渲染的结果。
使用列表过渡的时候,每一个元素都要添加一个值是唯一的并且稳定的key属性。
transition与transition-group的区别:
transition 控制一个元素
transition-group 控制多个元素
vue实例中定义方法:
css中直接为元素添加过渡效果就可:
30 自定义指令
指令是对DOM元素的拓展,使其具有一定的行为特征(功能)。
上面中书写过的指令有:
v-bind(动态设置属性)
v-text,v-html,v-once(插值指令)
v-model(数据双向绑定)
v-cloak(解决插值符号闪烁)
v-on(绑定DOM事件)
v-show(显隐元素)
v-if, v-else-if, v-else(条件指令)
v-for(循环指令)
自定义指令只需要两步:
第一步,在模板中使用:指令都是以v-为前缀,字母小写,横线分割单词。
第二步,在js中定义指令。有两种定义方式:
第一种:全局定义:Vue.directive(name, fn | {})
全局定义的指令可以在所有vue实例化对象(组件)中使用
directive方法不能解构,要在vue实例化对象之前定义。
第二种:局部定义:directives: { name: fn | {} }
局部定义的指令只能在当前vue实例化对象(组件)中使用
name表示指令的名称:省略v-前置,使用驼峰式命名
{}表示指令对象,可以定义一些方法
bind :将指令绑定给元素时候执行的方法;
update:指令的属性值发生改变的时候执行的方法
unbind:指令从元素上解除绑定时候执行的方法;
inserted:指令所在的元素从页面中删除时候,执行的方法;
componentUpdated:指令所在的组件更新的时候执行的方法。
fn表示指令函数,处理方法。
不论是指令对象中的方法,还是指令函数,都有四个参数:
第一个参数表示指令所在的元素。
第二个参数 表示指令对象,包含指令的一些信息
例如:指令名称,属性值表达式,当前的属性值,上一个属性值等等
第四个参数表示上一个虚拟DOM对象
注意:当多次使用指令的时候,一个指令的属性值改变,所有指令相关的回调函数都会执行。
为了提高性能,可以在回调函数中判断当前的值与上一个值是否相同,不同再执行。
当绑定(bind)时的逻辑和更新(update)时的逻辑是一样的,建议使用指令函数,因为书写方便
当绑定(bind)时的逻辑和更新(update)时的逻辑是不一样的,建议使用指令对象
例如:自定义一个vue内置的v-html指令:
全局定义(指令对象):
全局定义(指令函数):
局部定义指令实现vue内置的v-once和v-show指令:
vue实例对象中定义:
注:自定义的指令通常带有命名空间前缀。
例如: 例如自定义指令实现一个注册账号密码错误时出现提示文案的页面:
自定义全局指令:
页面显示: