一、 Vue 核心
1. Vue简介
1.1 官网
1.2 介绍
1.2.1 Vue 是什么?
- 一套用于构建用户界面的渐进式JavaScript框架
- 作者:尤雨溪
1.2.2 Vue的特点
-
采用组件化模式,提高代码复用率、且让代码更好维护
-
声明式编码,让编码人员无需直接操作DOM,提高开发效率
-
使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点
- 简单理解:虚拟DOM就是内存中的一个数据
- 简单理解:虚拟DOM就是内存中的一个数据
随记:
- Vue官网的 “资源列表”下拉框——AwesomeVue是Vue官方推荐你用什么库做什么功能
2. 初识Vue
3. 模板语法
Vue模板语法有2大类:插值语法和指令语法。
3.1 插值语法
<div id="root">
<h1>插值语法</h1>
<h3>你好鸭,{{name}}</h3>
</div>
3.2 指令语法
v-bind
可以给标签内的任何一个属性动态的绑定值。
<div id="root">
<h1>指令语法</h1>
<a v-bind:href="url">快去打游戏!</a><br>
<h1>v-bind的简写形式</h1>
<a :href="url">快去打游戏!</a>
</div>
3.3 插值语法VS指令语法
- 插值语法
- 功能:用于解析标签体内容
- 写法:{{xxx}},xxx是js表达式,且可以直接读取data中的所有属性
- 指令语法
- 功能:用于解析标签,包括:标签属性、标签体内容、绑定事件…
- 举例:v-bind:href=“xxx” 或简写为:href=“xxx”,xxx同样为js表达式,且可以直接读取到data中的所有属性
4.数据绑定
Vue中有两种数据绑定的方式:
-
单向绑定(
v-bind
)- 数据只能从data流向页面
-
双向绑定(
v-model
)- 数据不仅能从data流向页面,还可以从页面流向data
- 备注:
- 双向数据绑定一般都应用在表单类元素上,如
input
、select
等 v-model:value
可以简写为v-model
,因为v-model
默认收集的就是value
值
- 双向数据绑定一般都应用在表单类元素上,如
5.el与data的两种写法
5.1 el的两种写法
new vue
的时候配置el
属性- 先创建
vue
实例,随后再通过$mount()
指定el
的值
5.2 data的两种写
- 对象式
- 函数式
Q: 如何选择使用哪种写法?
A:目前哪种写方法都可以,以后学到组件时,data必须使用函数式i,否则会报错滴
一个重要的原则:由Vue管理的函数,一定不要写成箭头函数的形式,一旦写成箭头函数,this
就不再是vue实例
了
- 一点小小笔记
6. MVVM模型
- 随记
- 经常使用
vm
(ViewModel的缩写)这个变量名来表示Vue实例
- 经常使用
7. Vue中的数据代理
7.1 Object.defineProperty()
定义: Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回该对象
参数
- 第一个参数(必须):操作的对象
- 第二个参数(必须):要定义或修改的属性的名称或者Symbol
- 第三个参数(必须):属性描述符
- 基本配置项
value
:设置属性的值,默认是undefinewritable
:值是否可以被重写,默认是falseenumerable
:目标属性是否可以被枚举(遍历),默认是falseconfigurable
:是否允许删除或再次修改特性,默认是false
- 更高级一点的配置项:
get
:当有人读取属性值时,get
函数被调用set
:当有人修改属性值时,set
被调用
- 基本配置项
随记:
- 还记得
Object.keys()
和for in
的用法嘛
7.2 数据代理的定义
定义:通过一个对象代理对另一个对象中属性的操作(读/写)
- 一个最简单的数据代理的例子
通过obj2代理对obj中属性的操作
7.3 Vue中的数据代理
- Vue中的数据代理
通过vm对象(vue实例)来代理data
对象中属性的操作(读/写) - Vue中数据代理的好处
更加方便地操作data
中的数据 - 基本原理
- 通过
Object.defineProperty()把
data`对象中所有属性添加到vm上 - 为每一个添加到vm上的属性,都指定一个
getter
/setter
- 在
getter
/setter
内部去操作(读/写)data
中对应的属性
- 通过
- .随记
- vm中的data就是data,即vm._data=data
- vm(vue实例)和vue原型上的属性和方法都可以直接在模板上使用
- 浅浅看一下数据劫持
- vm中的data就是data,即vm._data=data
8. 事件处理
8.1 事件的基本使用
- 使用
v-on:xxx
或@xxx
绑定事件,其中xxx是事件名 - 事件的回调需要配置在
methods
对象中,最终会在vm上 methods
中配置的函数,不要使用箭头函数,否则this
就不是vm了methods
中配置的函数,都是被vue所管理的函数,this
的指向是vm或者组件实例对象@click="demo"
和@click="demo($event)"
效果一致,但后者可以传参
8.2 事件修饰符
Vue中的事件修饰符:
prevent
:阻止默认事件(常用)stop
:阻止事件冒泡(常用)once
:事件只触发一次(常用)capture
:使用事件的捕获模式self
:只有event.target
是当前操作的元素时才触发事件passive
:事件的默认行为是立即执行,无需等待事件回调执行完毕
- 随记
@scroll
和@wheel
的区别@scroll
是滚动套的滚动,@wheel
是鼠标滚轮的滚动- 在
scroll
中,当滚动条到底之后,再拖动滚动条往下是不会触发scroll
事件的 - 在
wheel
中,即使已经到底了,再操作鼠标滚轮往下,还是会触发wheel
事件 - 如果存在事件回调,
wheel
会先执行完回调函数,再来进行(响应)滚动条的滚动;scroll
优先响应滚动条的滚动
8.3 键盘事件
- Vue中常用的按键别名:
- 回车——>
enter
- 删除——>
delete
(捕获“删除”和“退格”键) - 退出——>
esc
- 空格——>
space
- 换行——>
rab
- 上——>
up
- 下——>
down
- 左——>
left
- 右——>
right
- 回车——>
- Vue未提供别名的按键,可以使用按键原始的key值去绑定,但要注意转为kebab-case(短横线命名)
- 系统修饰键(用法特殊):
ctrl
、alt
、shift
、meta
- 配合
keyup
使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才会触发 - 配合
keydown
使用:正常触发事件
- 配合
- 也可以使用
keycode
去指定具体的按键(不推荐) Vue.config.keycode.自定义键名 = 键码
,可以去定制键别名
8.4 一点技巧(用得不多)
一点小技巧:
- 事件修饰符可以连续写
9. 计算属性
9.1 计算属性的定义和理解
- 定义
要用的属性不存在,需要通过已有的属性进行计算的来 - 原理
底层借助了Object.defineProperty
方法提供的getter
和setter
get
函数什么时候执行- 初次读取属性值时会执行一次
- 当依赖的数据发生变化时会被再次调用
- 优势
与methods
相比,内部有缓存机制(复用)),效率更高,调式方便 - 备注
- 计算属性最终会出现在vm上(而不是出在
vm._data
上),直接读取使用即可 - 如果计算属性要被修改,那必须写
set
函数去响应修改,且set
中要引起计算时依赖的数据发生改变
- 计算属性最终会出现在vm上(而不是出在
一个小栗子:
9.2 计算属性的简写
Q
:什么时候用简写?
A
:属性值只读不改的时候
10. 监视属性
10.1 理解
- 监视的两种写法:
- new Vue时传入
watch
配置来监视指定的属性 - 通过vm对象的
$watch()
- new Vue时传入
- 当属性变化时,回调函数自动调用,在函数内部进行计算
- 监视的属性必须存在,才能进行监视(在
data
或者compued
里) immediate
属性- 使用
watch
时有一个特点,就是当值第一次绑定时,不会执行监听函数,只有值发生改变时才会执行。如果需要在最初绑定值的时候执行函数,就需要用到immediate
属性
- 使用
handler
属性watch
中需要具体执行的方法
10.2 深度监视
- 深度监视的错误写法
- numbers中属性a、b值的改变,不会导致numbers在内存中地址的改变
- numbers中属性a、b值的改变,不会导致numbers在内存中地址的改变
- 深度监视正确的打开方式
一个小总结:
- 深度监视
- Vue中的
watch
默认不监视对象内部值的改变(只监视一层) - 配置
deep:true
可以监视对象内部值的改变(可以监视多层)
- Vue中的
- 备注
- Vue自身可以监视多级结构(对象)中数据的改变,但Vue提供给程序员的
watch
默认无法监视多级结构中属性的改变 - 使用
watch
时根据数据的具体结构,决定是否采用深度监视
- Vue自身可以监视多级结构(对象)中数据的改变,但Vue提供给程序员的
10.3 监视的简写
Q
:社么时候可以简写
A
:当要监视的属性的配置项只有handler
的时候可以写成简写的形式。
10.4 watch VS computed
- 区别
computed
能完成的功能,watch
都可以完成watch
能完成的功能,computed
不一定能完成,例如:watch
可以进行异步操作
- 两个重要的小原则
- 所被Vue管理的函数,最好写成普通函数,这样
this
的指向才是vm或者组件实例对象 - 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数,这样
this
的指向才是vm或者组件实例对象
- 所被Vue管理的函数,最好写成普通函数,这样
11. 绑定样式
11.1 理解
- 在应用界面,某个(些)元素的样式是变化的
class
/style
绑定就是专门用来实现动态样式效果的技术
11.2 class绑定
:class='xxx'
,xxx可以是字符串、对象、数组:
-
表达式是字符串:
classA
适用于样式的类名不确定,需要动态指定
-
表达式是对象:
{classA:isA,classB:isB}
适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用
-
表达式是数组:
['classA','classB']
适用于:要绑定的样式个数不确定、名字也不确定
11.3 style绑定(用得不多)
:style ="{fontSize:xxx}"
,其中xxx是动态值,属性值(例如font-size要用小驼峰命名法,即fontSize):style ="[a,b]"
,其中a、b是样式对象
12. 条件渲染
12.1 v-if
- 写法:
.v-if="表达式"
.v-else-if="表达式"
.v-else="表达式"
- 适用于:切换频率较低的场景
- 特点:不展示的DOM元素直接被移除
- 注意:
v-if
可以和v-else-if
、v-else
一起使用,但要求结构不能被”打断”
12.2 v-show
- 写法:
v-show="表达式"
- 适用于:切换频率较高的场景
- 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉(display:none)
12.3 v-if VS v-show
使用v-if
时,元素可能无法获取到,而使用v-show
一定可以获取到
13. 列表渲染
13.1 基本列表
v-for
指令:
- 用于展示列表数据
- 语法:
v-for ="(item,index) in xxx" :key="yyy"
- 可遍历:数组、对象、字符串(用得很少)、指定次数(用得很少)
13.2 key的作用与原理
react
、vue
中的key有什么作用?(key的内部原理)
- 虚拟DOM中
key
的作用:key
是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】- 随后,Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较的规则如下
- 对比(比较)规则
- 【旧虚拟DOM】中找到了与【新虚拟DOM】相同的
key
:- 若虚拟DOM中内容没变,则直接使用之前的真实DOM
- 若虚拟DOM中的内容发生了改变,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
- 【旧虚拟DOM】中未找到与【新虚拟DOM】相同的
key
:- 创建新的真实DOM,随后渲染都页面
- 【旧虚拟DOM】中找到了与【新虚拟DOM】相同的
- 用
index
作为key
可能会引发的问题- 若对数据进行:逆序添加、逆序删除等破坏顺序的操作
- 会产生没有必要的真实DOM的更新——>界面效果没有问题,但效率低
- 如果结构中还包含输入类的DOM:
- 会产生错误的DOM更新——>界面有问题
- 若对数据进行:逆序添加、逆序删除等破坏顺序的操作
- 开发中如何选择
key
- 最好使用每条数据唯一的标识作为
key
,比如id、手机号、身份证号、学号等唯一值 - 如果不存在对数据进行逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,用于展示,使用index作为key是没有问题的
- 最好使用每条数据唯一的标识作为
13.3 列表过滤
13.4 列表排序
13.5 Vue检测数据改变的原理
13.5.1 Vue检测数据改变的原理_对象&模拟一个数据检测
- 模拟数据检测的一个错误的打开方式:
这么写的话,当有人访问(修改)data中name的值,就会调用get函数访问data.name,访问data.name就要再次调用get函数获取data.name的值,进而进入一个死循环
- 稍微正确一点的打开方式,但是无法进行深层次的数据监视
即,当对象中还有对象时,无法实现监视
存在的问题:无法进行深层次的数据检测
13.5.2 Vue.set()的使用
Vue.set(target,propertyNme/index,value)
- 参数:
target
(要修改的对象或数组):{Object|Array}
propertyName/index
(属性名或索引值):{string|number}
value
(属性的值是啥):{any}
- 返回值:设置的值
- 用法:
- 向响应式对象中添加一个property,并确保这个新property同样是响应式的,且触发视图更新
- 它必须用于向响应式对象上添加新property,因为Vue无法探测普通的新增property
- 注意操作的对象不能是Vue实例,也不能是Vue实例的根数据对象(例如data)
13.5.3 Vue检测数据改变的原理_数组
- 一个小问题:在代码中修改数据无法在页面中显示出来
13.5.4 小结
-
vue会监视data中所有层次的数据
-
如何监视对象中的数据?
通过setter
实现监视,Vue默认不做响应式处理- 对象中后追加的属性,Vue默认不做响应式处理
- 如果需要给后添加的属性做响应式,请使用该如下API:
Vue.set(target,propertyNme/index,value)
或vm.$set(target,propertyNme/index,value)
-
如何检测数组中的数据
通过包裹数组更新元素的方法实现,本质上就是做了两件事:- 调用原生对应的方法对数组进行更新
- 重新解析模板,进而更新页面
-
在Vue修改数组中的某个元素一定用到如下方法:
- 使用这些API:
push()
、pop()
、shift()
、unshift()
、splice()
、sort()
、reverse()
Vue.set()
或vm.$set()
- 只要调用了数组身上能引起数组本身的改变的七个函数,Vue才承认数组被修改了
- 使用这些API:
-
特别注意
Vue.set()
和vm.$set()
不能给am或vm的根数据对象添加属性
-
数据劫持
- 把data中的原始数据变成
getter
和setter
的形式,所有对数据的访问和修改都通过getter
和setter
来实现
- 把data中的原始数据变成
14. 收集表单数据
<input type="text"/>
- 则
v-model
收集的是value
值,用户输入的就是value
值
- 则
<input type="radio"/>
- 则
v-model
收集的是value
值,且要给标签配置value
值
- 则
<input type="checkbox"/>
- 没有配置input的value属性,那么收集的就是
checked
(勾选 or未勾选,是布尔值) - 配置input的value属性:
v-model
的初始值是非数组,那么收集的就是checked
(勾选 or未勾选,是布尔值)v-model
的初始值是数组,那么收集的就是value组成的数组
- 没有配置input的value属性,那么收集的就是
- 备注:
v-model
的三个修饰符:lazy
:失去焦点再收集数据number
:输入字符串转为有效的数字trim
:输入首尾空格过滤(去掉首尾的空格)
15. 过滤器
16. 内置指令
17. 自定义指令
18. Vue生命周期
二、Vue组件化编程
1.非单文件组件
1.1 基本使用
Vue中使用组件的三大步骤:
- 定义组件(创建组件)
- 使用
Vue.extend(options)
创建,其中options和new Vue(options)时传入的那个options几乎一样 - 区别:
el
不要写,为什么?——最终所有的组件都要经过一个vm管理,由vm中的el决定服务哪个容器data
必须写成函数。为什么?——避免组件被复用时,数据存在引用关系- 备注:使用template可以配置组件结构
- 使用
- 注册组件
- 局部注册
- 靠new Vue的时候传入components选项
- 全部注册
- 靠Vue.component(‘组件名’,组件)
- 局部注册
- 使用组件(写组件标签)
1.2 几个注意点
1.3 组件的嵌套
1.4 VueComponent
关于VueComponent:
- school组件本质是一个名为VueComponent的构造函数,且不是由程序员定义的,是
Vue.extend
生成的 - 我们只需要写或,Vue解析时会帮我们创建schol组件的实例对象
- 特别注意:
- 每次调用
Vue.extend
,返回的都是一个全新的VueComponent
- 每次调用
- 关于this指向
- 组件配置中:
- data函数、methods、watch和computed中的函,它们的this均是【VueComponent实例对象】
- new Vue(options) 配置中:
- data函数、methods、watch和computed中的函,它们的this均是【Vue实例对象】
- 组件配置中:
1.5 一个重要的内置关系
2. 单文件组件
三、使用Vue脚手架
四、Vue中的Ajax
4.1 解决开发环境Ajax跨域问题
4.2 Vue项目中常用的2个Ajax库
4.3 slot插槽
- 作用
让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于`父组件——>子组件 - 分类:
- 默认插槽
- 具名插槽
- 作用域插槽
4.3.1 默认插槽
一个小例子:
定义插槽的地方:
插槽的使用者:
4.3.2 具名插槽
4.3.3 作用域插槽
-
理解
数据在组件的自身(定义插槽的地方),但根据数据生成的结构需要由组件的使用者来决定
- 数据在子组件里面,但是作用域插槽可以把子组件的数据传给父组件
- 插槽(子组件)给插槽的使用者(父组件)传递数据(数据流逆着走)
- 作用域插槽也可以有名字(但是有点混乱,不推荐尼)
-
例子
- games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定
- games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定
五、vuex
六、vue-router
- 理解:
一个路由(route)就是以组映射关系(key-value),多个路由需要路由器(router)进行管理 - 前端路由
key是路径,value是组件
6.1 基本使用
- 安装
vue-router
,命令:npm i vue-router
- 应用插件:
Vue.use(VueRouter)
- 编写router配置项
- 实现切换(active-class可配置高亮样式)
<router-link active-class="active" to="/about">About</router-link>
- 指定展示的位置
<router-view></router-view>
6.2 几个注意点
- 路由组件通常放在pages文件夹,一般组件通常存放在components文件夹
- 通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载
- 每个组件都有自己的
$route
属性,里面存储着自己的路由信息 - 整个应用只有一个
router
,可以通过组件的$router
属性获取到
6.3 嵌套路由(多级路由)
-
配置路由规则,使用
children
配置项:
-
跳转(要写完整的路径)
<router-link to="/home/news">News<router-link>
一个小例子:
6.4 路由传参
6.4.1 query参数
-
传递参数
-
接收参数
$router.query.id
$router.query.title
6.4.2 命名路由
- 作用:可以简化路由的跳转
(当路由path过长的时候比较有用,路由path比价短的话,就…也可以不用了吧) - 如何使用
-
给路由命名
-
简化跳转
-
6.4.3 路由的params参数
-
配置路由,声明接收params参数
-
传递参数
注意
:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置
3. 接收参数
$router.params.id
$router.params.title
6.4.4 路由的props配置
作用:让路由组件更方便的接收到参数
6.4.5 router-link的replace属性
浏览器的历史记录有两种写法方式:push
和replace
,push
是追加历史记录,replace
是替换当前记录。
路由跳转默认为push
。
- 浏览器历史记录的默认操作模式:
push
- 不会破坏浏览器的历史记录
- 不会破坏浏览器的历史记录
- 浏览器历史记录的另一种操作模式——
replace
- 作用:控制路由跳转时操作浏览器历史记录的模式
- 当回退到前一条历史记录的时候,当前栈顶的记录就会被干掉
- 如何开启
replace
模式
<router-link replace ......>News<router-link>