Vue
Vue 学习
1 | # 运行单独的Vue页面 |
Vue简介
Vue是什么?
一套用于构建用户界面的
渐进式
JavaScript框架渐进式:Vue可以自底向上逐层的
应用
简单应用:只需一个轻量小巧的核心库 (100+ kb)
复杂应用:可以引入各式各样的 Vue 插件
谁开发的?
- 尤雨溪
Vue的特点
- 采用
组件化
模式,提高代码复用率,且让代码更好维护 声明式
编码,让编码人员无需直接操作DOM,提高开发效率- 使用
虚拟DOM
+ 优秀的DIff算法
,尽量复用DOM节点
- 采用
学习Vue之前要掌握的JavaScript基础知识
- ES6语法规范
- ES6模块化
- 包管理 (npm等)
- 原型、原型链
- 数组常用方法
- axios
- promise
- ……
Vue官网使用指南
https://www.bilibili.com/video/BV1Zy4y1K7SH/?p=3
Vue 环境搭建
直接用 <script> 引入
- 开发版本: 包含完整的警告和调试模式。=>
vue.js
- 生产版本: 删除了警告,压缩。 =>
vue.min.js
- 开发版本: 包含完整的警告和调试模式。=>
npm + Vue-cli
开始 Hello World 案例
1 |
|
模板语法
Vue模板语法有2大类
插值语法
功能:用于解析标签体内容。 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
指令语法
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件.....)。 举例:v-bind:href="xxx" 或 简写为 :href="xxx",xxx同样要写js表达式, 且可以直接读取到data中的所有属性。 备注:Vue中有很多的指令,且形式都是:v-????,此处我们只是拿v-bind举个例子。
数据绑定
Vue中有2种数据绑定的方式:
单向绑定(v-bind)
数据只能从data流向页面。
双向绑定(v-model)
数据不仅能从data流向页面,还可以从页面流向data。
备注:
- 双向绑定一般都应用在表单类元素上(如:input、select等)
v-model:value
可以简写为v-model
,因为 v-model 默认收集的就是value值。v-model
只能应用在表单类元素(输入类元素)上
1 | 单向数据绑定:<input type="text" :value="name"><br/> |
el与data的两种写法
el的2种写法
new Vue时候配置el属性。
1
2
3
4
5
6const v = new Vue({
el:'#root', // 第一种写法
data:{
name:'细粒丁'
}
})先创建Vue实例,随后再通过
vm.$mount('#root')
指定el的值。1
2
3
4
5
6const v = new Vue({
data:{
name:'细粒丁'
}
})
v.$mount('#root') // 第二种写法
data的2种写法
对象式
1
2
3
4
5
6
7new Vue({
el:'#root',
//data的第一种写法:对象式
data:{
name:'细粒丁'
}
})函数式
1
2
3
4
5
6
7
8
9new Vue({
el:'#root',
data(){
console.log('@@@',this) //此处的this是Vue实例对象
return{
name:'细粒丁'
}
}
})如何选择:目前哪种写法都可以
组件时,data必须使用函数式,否则会报错。
一个重要的原则
- 由Vue管理的函数,一定
不要
写箭头函数
,一旦写了箭头函数,this 就不再是Vue实例了。
理解MVVM
MVVM模型
1. M:模型(Model) :data中的数据
2. V:视图(View) :模板代码
3. VM:视图模型(ViewModel):Vue实例
观察发现:
1.data中所有的属性,最后都出现在了vm身上。
2.vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。
Object.defineProperty
1 | let number = 18 |
数据代理
数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)
1 | let obj = {x:100} |
Vue 中的数据代理
Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
Vue中数据代理的好处:
更加方便的操作data中的数据
基本原理:
- 通过
Object.defineProperty()
把data
对象中所有属性添加到vm上 - 为每一个添加到vm上的属性,都指定一个getter/setter
- 在 getter/setter 内部去操作(读/写)data 中对应的属性
- 通过
事件处理
事件的基本使用:
- 使用
v-on:xxx
或@xxx
绑定事件,其中xxx是事件名;- 事件的回调需要配置在methods对象中,最终会在vm上;
- methods中配置的函数,
不要
用箭头函数
!否则this就不是vm了;- methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
@click="demo"
和@click="demo($event)"
效果一致,但后者可以传参;
1 | <button @click="showInfo1">点我提示信息1(不传参)</button> |
事件修饰符
Vue中的事件修饰符:
prevent
:阻止默认事件 (常用) - 如<a>
标签的跳转stop
:阻止事件冒泡 (常用) - 子元素不触发父元素事件once
:事件只触发一次 (常用)capture
:使用事件的捕获模式 - 父元素不触发子元素事件
注:捕获是从父传到子,冒泡是从子传到父,先捕获 后冒泡self
:只有event.target
是当前操作的元素时才触发事件;passive
:事件的默认行为立即执行,无需等待事件回调执行完毕;
1 | <!-- 阻止默认事件(常用, 执行完 showInfo 后不跳转 --> |
键盘事件
Vue中常用的按键别名:
回车 => enter 删除 => delete (捕获“删除”和“退格”键) 退出 => esc 空格 => space 换行 => tab (特殊,必须配合keydown去使用) 上 => up 下 => down 左 => left 右 => right
Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为
kebab-case
(短横线命名)系统修饰键(用法特殊):
ctrl
、alt
、shift
、meta(win键)
(1). 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。 (2). 配合keydown使用:正常触发事件。
也可以使用keyCode去指定具体的按键(不推荐)
Vue.config.keyCodes.自定义键名 = 键码
,可以去定制按键别名
1 | <input type="text" placeholder="按下ctrl+y触发showInfo" @keyup.ctrl.y="showInfo"> |
计算属性
- 定义:要用的属性
不存在
,要通过已有属性计算得来- 原理:底层借助了
Objcet.defineproperty
方法提供的 getter 和 setter- get函数什么时候执行?
- 初次读取时会执行一次。
- 当依赖的数据
发生改变
时会被再次调用。- 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
- 备注:
- 计算属性最终会出现在vm上,直接读取使用即可。
- 如果计算属性要被修改,那必须写
set函数
去响应修改,且set中要引起计算时依赖的数据发生改变。
姓名案例 - 拼接姓名
第一种写法
前端插值语法
实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{firstName}}-{{lastName}}</span>
</div>
</body>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
}
})
</script>第二种写法
methods
函数返回值 实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName()}}</span>
</div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
methods: {
fullName(){
return this.firstName + '-' + this.lastName
}
},
})
</script>第三种写法
computed
计算属性 实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
</div>
<script type="text/javascript">
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
computed:{
fullName:{
//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
//get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
get(){
console.log('get被调用了')
// console.log(this) //此处的this是vm
return this.firstName + '-' + this.lastName
},
//set什么时候调用? 当fullName被修改时。
set(value){
console.log('set',value)
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
</script>
计算属性简写
1 | computed:{ |
监视属性
监视属性watch:
- 当被监视的属性变化时, 回调函数自动调用, 进行相关操作
- 监视的
属性必须存在
,才能进行监视- 监视的两种写法:
- new Vue时传入watch配置
- 通过vm.$watch监视
天气案例
点击按钮,切换状态,从而显示不同内容
普通方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<div id="root">
<h2>今天天气很{{info}}</h2>
<!-- <button @click="isHot = !isHot">切换天气</button> -->
<button @click="changeWeather">切换天气</button>
</div>
<script type="text/javascript">
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
})
</script>监视方法,利用
watch
实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
<script type="text/javascript">
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
// watch 的第一种写法
/* watch:{
isHot:{
immediate:true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时。
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}
} */
})
// watch 的第二种写法
vm.$watch('isHot',{
immediate:true, //初始化时让handler调用一下
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
})
</script>
深度监视
深度监视:
- Vue中的watch默认不监测对象内部值的改变(一层)。
- 配置
deep:true
可以监测对象内部值改变(多层)。- 备注:
- Vue自身可以监测对象内部值的改变(setter监测到了),但Vue提供的watch默认不可以!
- 使用watch时根据数据的具体结构,决定是否采用深度监视。
1 | <body> |
监视的简写形式
简写模式下,默认:
immediate
为false
deep
为false
1 | // 向 Vue 传入 watch 配置对象写法 |
watch对比computed
computed
和watch
之间的区别:
computed
能完成的功能,watch
都可以
完成。
watch
能完成的功能,computed
不一定能完成,例如:watch可以进行异步操作。
解释:因为computed
依靠return
返回值,而 return 不能延时/异步两个重要的小原则:
- 所
被
Vue管理的函数,最好
写成普通函数
,这样this的指向才是vm 或 组件实例对象。- 所有
不被
Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),
最好
写成箭头函数
,这样this的指向才是vm 或 组件实例对象。
1 | <!-- 姓名案例_watch实现 --> |
绑定样式
class 样式
写法
:class="xxx"
,xxx 可以是字符串、对象、数组。字符串写法
适用于:类名不确定,要动态获取。对象写法
适用于:要绑定多个样式,个数不确定,名字也不确定。数组写法
适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
style 样式
:style="{fontSize: xxx}"
其中xxx是动态值。:style="[a,b]"
其中a、b是样式对象。
1 | <style> |
条件渲染
v-if
写法:
v-if="表达式"
v-else-if="表达式"
v-else="表达式"
适用于:切换频率较低的场景。 特点:不展示的DOM元素直接被移除。 注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。
v-show
写法:
v-show="表达式"
适用于:切换频率较高的场景。 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
备注:
使用v-if
的时,元素可能无法获取到,而使用v-show
一定可以获取到
1 | <div id="root"> |
列表渲染
key作用与原理
列表过滤
列表排序
更新时的一个问题
Vue监测数据的原理_对象
Vue.set()方法
Vue监测数据的原理_数组
总结Vue监视数据
收集表单数据
过滤器
v-text指令
v-html指令
v-cloak指令
v-once指令
v-pre指令
自定义指令_函数式
自定义指令_对象式
自定义指令总结
生命周期
组件
Vuex
- 安装VueX
- Vue2中,要使用Vuex的3版本
$ npm i vuex@3
- Vue3中,要使用Vuex的4版本
$ npm i vuex
- Vue2中,要使用Vuex的3版本
1 | $ npm i vuex |