一、原生API vs 函数库 vs 框架
原生API
浏览器/平台已实现的,可直接使用的原生函数
问题:代码繁琐
函数库(library)
基于原生API基础上,进一步封装的,更简化的一组函数的集合
框架(framework)
前人将多次成功项目的经验总结,形成的帮成品项目
优:后人继续开发即可,项目整体代码和做事的步骤极简化,不再需要大量重复手工劳动
缺:需要改变原有的做事方法,如Vue.js中根本没有查找方法,但是,数据也能出现在想出现的位置
二、概述
中文官网
Vue.js
一个渐进式(Progressive)的基于MVVM设计模式的JavaScript框架
- 什么是渐进式?
虽然提供了很多的组成部分,但不强迫必须全部使用 - vs AngularJS和React
要求严格的,必须打包全套使用
适用性
适用于以数据操作为主的项目(WEB、APP)。以数据增删改查操作为主,多数应用都是以数据操作为主的。
安装
兼容性
不支持IE8及以下版本
当前版本
5.0.8
如何使用
两种方法
1.直接下载,并使用script引入vue.js文件
- 在全局创建一钟新的类型Vue:构造函数和原型对象
- 2个版本
- 开发版,强调:有错误提示!
- 压缩版,强调:没有错误提示!
2.使用Vue-CLI脚手架工具
三、MVVM框架
旧的网页组成:3部分
HTML:提供网页的内容
CSS:为内容提供样式
JS:为内容提供行为/数据
问题: JS DOM操作,既要加工数据,又要承担大量琐碎的增删改查DOM树的任务。代码繁琐
解决: 重新划分上述3部分
重新划分
View
视图,指网页中的元素和样式,一般指HTML标签/CSS
- 其实,是.html网页中的一个需要动态加载内容的父元素: 如 div#app
- Html网页中的视图,也称为模板template。今后,只要看到模板template错误,就在html中找原因。
Model
模型,指程序中创建的或从远程获取的数据,一般用JS中的一个对象来保存。起内容会显示到View中。
- 以前,如何将Model中的数据显示到页面View中的指定位置?
- DOM/JQUERY操作: 手动查找元素,修改元素内容/属性/样式
- 现在
ViewModel
视图模型/控制器,替代之前的DOM/JQUERY操作,把模型中的数据和视图中的HTML元素“绑定”在一起:
<p>{{}}</p>
<ul><li v-for=""></li></ul>
<img v-bind:src="">
.....
------------------------
var vm = new Vue({
el: '#app',
data: {
}
})
- 什么是绑定: 不需要写一行代码,就可让页面元素内容和数据联动变化
- Vue类型,提供的就是这样一种强大的ViewModel对象,可自动同步数据和页面元素
ViewModel核心原理
- 响应系统(Reactivity System): 内存中数据变,页面自动改,每个内存中的数据都被添加了访问器属性,受到一对儿
get/set()
方法的保护,每次修改内存中数据时,都会自动调用当前数据的set
方法,其中,除了修改内存中的数据外,还会通知观察者
观察者自动触发重新加载方法,生成新的虚拟DOM树,然后自动更新到真实的DOM树 - 虚拟DOM (Virtaul DOM): 用js面向对象模拟的,保存当前视图内所有DOM节点对象基本描述属性和节点间关系的树结构。用js对象,描述每个节点,及其父子关系,形成虚拟DOM对象树结构,修改内存中数据,触发重新加载操作,重新加载,用修改后的数据生成新虚拟DOM树,框架的加载功能会遍历并比对新虚拟树和旧虚拟树中每个节点的差别,并记录下来,最后,加载操作,将所有记录的不同点,局部修改到真实DOM树上。
- 为什么快:
- 局部更新真实DOM树,避免大范围重排重绘。
- 无需人工执行增删改查操作干预,自动化程度高
如何使用Vue框架?
- 首先,创建Vue类型的ViewModel对象vm:
- 要想享受Vue框架提供的便利,必须创建Vue类型的对象。
var vm = new Vue({ … });
- 其次: 在new Vue中,定义模型,并将vm对象与页面中某个父元素绑定起来。
组合在一起: - Html中(View):
< div id=”app”>
<xxx>显示数据的元素</xxx>
</div>
Js中: var vm=new Vue({ //ViewModel
data:{ //Model
数据属性: 值
… : …
}
el: “#app”, //指定将数据模型data,整体绑定给页面元素#app
})
- 强调: 虽然el: 后可跟任意选择器,但一个vm对象,只能绑定到一个DOM父元素上。
- 即使: el: “选择器”可以找到多个元素,也只能绑定到第一个符合条件的DOM元素上。
- 所以,通常都用#id选择器就够了
四、{{ }}语法
- {{ }}:双括号语法,也叫大胡子语法(Mustache),
官方名字: Interpolation 补缺,插值的意思 - 什么是: 用于选择特定的Model数据绑定到View视图中
今后只要希望Model数据发生了改变,所有用到该数据的{{}}都会自动更新。 - 如何: {{表达式}}其中的表达式可以是:
- 注意:不能出现逻辑结构(if/for等)
- (1)Model变量名,如
{{userName}}
- (2)算术/比较/逻辑/三目运算,如
{{ sex===0 ? '女' : '男' }}
,可用“过滤器”代替 - (3)方法调用,如
{{ getSum() }}
,可用“计算属性”代替 - (4)属性访问,如
{{book.price}}
- (5)数组下标访问,如
{{ list[2] }}
- 问题
- 问题1: 不能根据数组/集合中的记录条数,动态绑定列表
- 问题2: 不能使用{{}}语法动态绑定属性值!
- 解决
五、指令(directive)
- 什么是: Vue.js提供的,专门增强html功能的特殊属性
- 为什么: html本身是静态的,写死的,没有任何动态生成内容的能力
- 何时: 只要希望根据内存中的数据,动态生成html元素或属性时,都用指令。
- 包括: 看手册/指令
如何: v-* 凡是 v-*开头的,都是增强型的html属性
(1)v-bind:专门绑定属性值!
- 何时: 只要绑定属性
- 如何:
<any v-bind:属性=”数据变量”
- 强调: 不用写{{}}
- 简写:
v-bind
可省略, 仅: :属性=”数据变量”
(2)v-for:根据数组/集合内容,反复生成多个相同的html元素
- 何时: 只要根据数组/集合内容,反复生成多个相同的html内容时
- 如何:
<any v-for="(变量名, 下标名) in 数组/对象/字符串">
- 强调:
v-for
要写在要重复生成的元素上,而不是父元素上。 - 简写: 如果不关心下标,只关心元素值,可简写为:
<any v-for="变量名 in 数组/对象/字符串/数字">
- in,可自动取出数组/集合中每个元素的值和下标保存到右边的变量中
//in 可用of替换,完全相同
如果in后是数字, 则in会从1开始迭代递增到目标数字
- in,可自动取出数组/集合中每个元素的值和下标保存到右边的变量中
(3)v-if:根据一个bool数据作为条件,控制是否创建该元素到DOM树(控制显示隐藏)
- 何时: 根据条件,控制一个元素的显示和隐藏时
- 如何:
<any v-if="布尔">
- 强调: 不是用display:none隐藏,而是彻底删除不显示的元素
(4)v-else:与v-if组合应用
<any v-if="布尔"></any> <any v-else></any>
(5)v-else-if:与v-if组合应用
<any v-if="布尔"></any>
<any v-else-if="布尔"></any>
<any v-else></any>
- 强调: v-if v-else if v-else 元素必须是紧邻的兄弟元素,中间不能阻隔任何其他元素
<!--坑!!!父元素div,不能换成p元素,因为html中规定p元素不允许嵌套块元素!!!-->
(6)v-show:用法类似于v-if 只不过,总是创建该元素到DOM树,但使用display:block/none控制显示隐藏
- vs
v-if
: 通过创建/删除元素来控制显示隐藏。 - 何时:
- 如果隐藏后,还需要重新显示回来,就用
v-show
,不用反复创建DOM元素,效率高。 - 如果隐藏后,不会再显示回来,就用
v-if
,删除元素,减小DOM树的内容
- 如果隐藏后,还需要重新显示回来,就用
(7)v-on:为当前元素绑定指定事件的处理函数
- 问题:
- 真正项目中:
var vm=new Vue()
,会造成全局变量污染,所以通常不写var vm
, 直接new Vue()
那么,就不可能在Vue以外的事件处理函数中,使用vm变量来操作vm对象的内容
- 真正项目中:
- 解决:
- 利用面向对象思想,在
new Vue()
对象内部,添加方法。对象自己的方法,访问自己的属性,不需要对象变量名,一切都用this
代替即可! - 如何添加方法:
- 强调: 方法名不能用js中的关键词,比如delete,不能用,因为delete是js中专门删除对象属性的关键词!
- 如何让页面上的元素的事件属性,找到当前vm对象的方法?
- 必须用
v-on:事件名=”方法名()”
- 简写: 如果没有参数,可省略()
- 语法糖:
v-on:事件名=
可简写为@click=
- 利用面向对象思想,在
new Vue({
methods: {
方法名: function(){ this指向当前vm对象 }//因为methods中的方法和data中的属性一样,都会被提升到vm对象上
//可简写为: 方法名(){ … }
}
})
- Html中:
<button @click="add">+</button>
- 问题: 如果换成a当按钮,
href=”…”
属性,默认会擅自改变地址栏或跳转其他页面 - 解决: 阻止默认行为
- 问题: methods中的方法,本质不是直接的事件处理函数,不能自动获得事件对象
- 解决: 2种方法:
- 使用Vue对象内置变量
$event
-
- Html中绑定时,手工传入Vue内置对象
$event
:
<a href="#" @click="sub($event)">-</a>
- Html中绑定时,手工传入Vue内置对象
-
- Js中,为methods中的方法定义参数e
$event
,是Vue对象内,将DOM事件对象e封装后的产物,是现成的内置变量,可直接使用js中: methods:{ sub(e){ … } }
- 何时: 只要想在Vue的处理函数中使用事件对象,必须在html绑定中调用方法时,传入
$event
。 - 强调: html中实参$event名不能变,但js中形参名可变 $event可和其他参数一同传入,且没有顺序限制。
- 使用事件修饰符:
- 问题: 使用
$event
,html和js都要改,少改一处,就错! - 解决: 其实, 可以更简化:
- 事件修饰符: 自动实现原DOM事件对象操作的特殊属性
- 何时: 只要希望修改事件的行为时,都用事件修饰符,不用
$event
- 包括: 手册/v-on/修饰符:
.stop
代替stopPropagation()
.prevent
代替preventDefault()
; - 如何: js中,不要加
e
,更不要调用e
的方法了
Html中:@click.修饰符=”… ”
- 强调: 多个修饰符可同时修饰一个事件: 比如:
@click.stop.prevent=
且顺序无关 - 但是: 如果想获得鼠标位置,则必须使用$event!所以!两种方法都要会!
- 问题: 使用
- 使用Vue对象内置变量
- 问题: 如果换成a当按钮,
(8)v-html:使用模型数据替换当前元素的innerHTML
何时: 专门加载一段html代码片段。
(9)v-text:使用模型数据替换当前元素的innerText
何时: 专门加载一段文本内容
(10)v-cloak:(哈利波特的隐身斗篷) 强调: 不是clock!!!
- 问题: 首次记载页面时,如果加载稍微延迟,用户就可能看到{{}}语法!
- 必须点击一下network中,再按住f5反复刷新1.html,结果会看到明显的{{}}
解决: 没准备好时,穿隐身斗篷,准备好了再脱掉隐身斗篷 - 什么是
v-cloak
: 让当前元素默认隐藏,直至内容准备就绪,才自动显示出来 - 何时: 防止用户短时间内看到{{}}
- 如何: 2步: 必须配合css使用
- 写在元素开始标签中即可,不用给值!!!
- 在CSS中必须添加:
[v-cloak] { display: none; }
- 强调: VUE官方本身,没有提供
v-cloak
的隐藏样式,所以,必须我们自己写。 - VUE只负责自动移除
v-cloak
- 原理: 开始时由我们手动加上
display:none
, 准备就绪后,vue自动删除v-cloak
属性,也就删除了display:none
属性,元素显示出来
(11) v-pre:保留当前元素中的{{}}语法,不进行绑定渲染
何时: 如果元素内容中,有{{}}原文,但不想作为绑定语法解析时,可用v-pre,保留{{}}为原文,不再编译。
(12)v-once:当前元素的{{}}语法对应的数据只绑定一次,以后即使模型数据改变,也不再随着改变
- 何时: 如果数据,只在加载时,绑定一次即可,后续不再改变时
- 底层原理:只在首次加载时,一次性将模型数据显示在当前元素 。不会将当前元素注册到监听队列中
- 正常: watcher中,有一个队列,维护着每个数据变量和页面之间元素的对应关系。每次数据模型发生改变后,都会通知watcher,watcher会遍历受该数据变量影响的元素,并逐个修改他们。
- 优化: 减少被监视的元素个数,可以优化页面绑定的效率。