初识Vue

1.发展历程

  1. 2013年,在 Google 工作的尤雨溪,受到 Angular 的启发,开发出了一款轻量框架,最初命名为 Seed。

  2. 2013年12月,更名为 Vue,图标颜色是代表勃勃生机的绿色,版本号是 0.6.0。

  3. 2015.10.26,1.0.0 Evangelion 是 Vue 历史上的第一个里程碑

  4. 2016.10.01,2.0.0 是第二个重要的里程碑,它吸收了 React 的虚拟 Dom 方案,还支持服务端渲染。

  5. 2020年09月18日,Vue.js 3.0 正式发布

2.使用Vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 准备好一个容器 -->
<!-- demo容器里面是 Vue模板 被Vue接管 -->
<div id="demo">
<h1>Hello,{{name.toUpperCase()}},{{address}}</h1>
</div>

<script type="text/javascript" >
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

//创建Vue实例
new Vue({
el:'#demo', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。
data:{ //data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。
name:'simplelife',
address:'南昌'
}
})

</script>

3.插值语法 {{ xxx }}

{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性;

一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新;

PS:插值语法里面可以写 JS表达式

区分:JS表达式 和 JS代码

  1. 表达式:一个表达式会产生一个值,可以放任何一个需要值的地方:三目表达式、函数(没有返回值是 undefined)
  2. js代码(语句):if(){}for(){}

4.容器和实例匹配

Vue实例和容器是一一对应的关系,容器是如何被Vue实例接管的呢

1
2
3
4
5
6
7
8
9
10
11
12
<div id="demo">

</div>
<script type="text/javascript" >
new Vue({
el:'#demo', // (1)接管id='demo'的容器
})

// (2) 第二接管方式
const vm = new Vue({})
vm.$mount('#demo');
</script>

需要注意的是:

  1. Vue实例在DOM元素从上自下,遇到id="demo"进行接管,后者不再接管
  2. 接管的DOM元素不一定要用 Id 选择器,可以选择class vm.$mount('.demo');

5.Vue模板语法

  1. 插值语法

  2. 指令语法

    功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…..)。

    举例:v-bind:href="xxx" 或 简写为 :href="xxx",xxx同样要写js表达式,

    ​ 且可以直接读取到data中的所有属性。

    备注:Vue中有很多的指令,且形式都是:v-????,此处我们只是拿v-bind举个例子。

数据绑定

1.绑定方式:单向(v-bind)和双向(v-model)

  1. 单向绑定:v-bind(:) 语法糖简写成一个冒号
1
2
3
4
5
6
// 写一段Vue实例
new Vue({
data:{
name: 'simplelife'
}
})
1
<input type="text" :value="name" /> 输入框显示 simplelife
  1. 双向绑定:v-model:value 语法糖写法 v-model
1
<input type="text" v-model="name" /> 输入框显示 simplelife

如右代码是错误的,因为v-model只能应用在表单类元素(输入类元素)<h2 v-model:x="name">你好啊</h2>

2.Vue实例data数据两种写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// data 有两种写法:对象式、函数式
// (1) 对象式
new Vue({
data:{
name: 'simplelife'
}
})

// (2) 函数式
new Vue({
data(){
return{
name: 'simplelife'
}
}
})

// 总结:对象式更方便,函数式更麻烦,所以我们选择对象式 -_-

// 目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。请记住一定选择麻烦的那种,你会感谢我

// 原则:由Vue管理的函数,一定不要写箭头函数,因为 this 指向问题。原本需要指向Vue实例,但是由于使用了箭头函数,可能导致this指向其它。

3.MVVM模型

模型拆析:

  1. M:模型(Model):data中的数据
  2. V:视图(view):模板代码
  3. VM:视图模型(ViewModel):Vue实例

观察发现:

  1. data中所有的属性,最后都出现在了vm(vm指Vue实例对象)身上
  2. vm身上所有的属性及 Vue 原型上所有属性,在Vue模板中都可以直接使用

4.数据代理

数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)

想要去理解Vue实现数据代理的原理,那就要追溯JS的一个对象方法 Object.defineProperty

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
var number = 18;
var obj = {
name: 'simplelife',
age: '18',
}
// number变化了,对象的age会变化吗
// 控制台
number = 20;
obj.age Enter 回车
18 // 显然现在number和obj.age没有半毛钱关系,那怎么制造关系呢

// 我们需要借助 Object.defineProperty 内置方法
// 那我们就有必要详细学习下这方法的门道了
Object.defineProperty(obj,'age',{
value, // 值
enumerable, // 是否能被枚举
writable, // 是否能被修改
configurable,// 是否能被删除
get(){},
set(){}
})
// 重点讲解 get(getter) 和 set(setter) 方法
// 当有人获取 age 值时,调用get函数去获取值,需要return返回
get(){
console.log('有人读取age属性了')
return number // 将number值返回给读age值
}
// 当有人修改 age 值时,调用set函数去修改,接受传递进来的值
set(val){
console.log('有人修改了age属性,且值是',val)
number = val // 改变number值
}

// 相信此时,你对number的值影响obj.age有初步的理解了
  1. Vue中的数据代理:

​ 通过vm对象来代理data对象中属性的操作(读/写)

  1. Vue中数据代理的好处:

​ 更加方便的操作data中的数据

  1. 基本原理:

​ 通过Object.defineProperty()把data对象中所有属性添加到vm上。

​ 为每一个添加到vm上的属性,都指定一个getter/setter。

​ 在getter/setter内部去操作(读/写)data中对应的属性。

事件处理

1.事件的基本使用:

  1. 使用v-on:xxx @xxx 绑定事件,其中xxx是事件名;
  2. 事件的回调需要配置在methods对象中,最终会在vm上;
  3. methods中配置的函数,不要用箭头函数!否则this就不是vm了;
  4. methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
  5. @click="demo"@click="demo($event)" 效果一致,但后者可以传参;

2.Vue中的事件修饰符:

  1. prevent:阻止默认事件(常用);
  2. stop:阻止事件冒泡(常用);
  3. once:事件只触发一次(常用);
  4. capture:使用事件的捕获模式;
  5. self:只有event.target是当前操作的元素时才触发事件;
  6. passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<!--
prevent ==> e.preventDefault() 阻止默认事件
stop ==> e.stopPagation() 阻止事件冒泡
-->
<div id="demo" @click="clickFather"> <!-- 给父元素点击事件添加 self 修饰符,不受冒泡影响 -->
<!--默认行为不阻止,不能跳转-->
<a href="www.baidu.com" @click.prevent="clickMe"></a>
<!--事件修饰符组合技能,阻止默认事件和事件冒泡,不过有先后的,顺序会导致一些其它发生-->
<a href="www.baidu.com" @click.prevent.stop="clickMe"></a>

</div>

<button @click.passive = "clickMe">
<!-- 假如clickMe方法内容很多执行效率低,那么不能第一时间去执行默认事件,此时就需要用passive修饰符,去立即执行默认事件了 -->
</button>

2.键盘事件修饰符:

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
<!--
1.Vue中常用的按键别名:
回车 ==> enter(Enter)
删除 ==> delete(捕获'删除'和'退格'键)
退出 ==> esc
空格 ==> space
换行 ==> tab (特殊,当按下tab时会取消表单类焦点,因此只能配合 keydown 事件)
上(up)、下(down)、左(left)、右(right)
-->
<!-- 当按下回车键会触发事件 clickMe enter是Vue别名,原始键名Enter也是可以触发的-->
<input type="text" @keyup.enter="clickMe">
<input type="text" @keyup.Enter="clickMe">


<!--
2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)
大小写键:caps-locks
-->

<!--
3.系统修饰键(用法特殊):ctrl、alt、shift、meta(window徽标键)
(1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
(2).配合keydown使用:正常触发事件。

(1)按下ctrl+按下任意键释放 触发 <button @keyup.ctrl="clickMe"></button>
(2)组合键:ctrl+y释放触发 <button @keyup.ctrl.y="clickMe"></button>


4.也可以使用keyCode去指定具体的按键(不推荐)
回车键Enter的keyCode的值是13,通过keyCode去指定按键,同样有效,只是不同的键盘keyCode值不一样
<button @keyup.13="clickMe"></button>

5.Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名
Vue.config.keyCodes.backCar = 13 // 回车键
-->

计算属性

定义:要用的属性不存在,要通过已有属性计算得来

原理:底层借助了Object.defineProperty方法提供的getter和setter实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 解析计算属性 完整版
new Vue({
data(){
name: 'simplelife',
age: 18
},
methods:{
getAge(){
return this.age
}
}
computed:{
'getUpAge':{ // 'getUpAge' 默认是不用写引号,其实是存在的
get(){
return this.age
},
set(val){ // 获取修改的值
this.age = val
}
}
}
})
// 计算属性直接放入插值语法解析
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 
这就是为什么插值解析methods方法需要去加一个括号
因为加一个括号是去执行返回获取返回值

这时可能就有人问了,如果没有return给函数返回呢,那么函数就会返回 undefined,但是浏览器不会去显示undefined
-->

{{ getAge() }}

<!-- 而计算属性,它就真的只是属性,当你去读取计算属性的值,会自动调用它的get方法,修改会自动调用 set 方法 -->
{{ getUpAge }}

1
2
3
4
5
6
7
8
// 简写计算属性
computed:{
getUpAge(){
return this.age
}
}
// 此时计算属性就是 get 方法。简写方式无法去修改值,只能获取值
// 剖析原理才能明白 为啥插值解析 methods方法和computed的方法不一样

优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。

PS:计算属性最终会出现在vm上,直接读取使用即可。

监视属性

Vue侦听器:watch,用于给用户去监听数据,实现原理类似Vue实现数据响应式原理。但它是提供给用户使用的

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// (1) new Vue配置watch侦听数据变化
// 完整版,需要注意的是,命名需要和侦听数据名称一致
const vm = new Vue({
data:{
name: 'simplelife'
},
watch:{
'name':{
immediate:true, // 初始化时让handler调用一下
handler(newValue,oldValue){
// newValue 新值,oldValue 旧值
this.name = newValue
}
}
}
})
//PS:在写计算属性和侦听属性,我都加了引号,并不是它们不能一定要加,我只是告诉你们,
//它这个是引号不加也是存在的,避让你不理解如下这种方式,添加侦听器

// (2) 第二种方式添加侦听器
vm.$watch('name',{
immediate:true,
handler(newValue,oldValue){}
})


// (3) 以上两种完整写法,有时我们并不需要在初始化时调用下handler函数,我们可以简写watch侦听
watch:{
name(newValue,oldValue){
this.name = newValue
}
}

vm.$watch('name',function(){
handler(newValue,oldValue){}
})

// (4) 深度监视 侦听器默认只能监听一级结构
// 此时name是一个对象,如果name里面的age被改变,侦听器无法监测到,因此handler函数不会执行
// 如何进行深度监测呢,开启深度
const vm = new Vue({
data:{
name:{
name: 'simplelife'
age: 18
}
},
watch:{
name:{
deep: true, // 开启深度监测
handler(newValue,oldValue){
this.name = newValue
}
}
}
})

样式绑定

1.class样式

写法:class="xxx" xxx可以是字符串、对象、数组。

  1. 字符串写法适用于:类名不确定,要动态获取。
  2. 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
  3. 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。

2.style样式

  1. :style="{fontSize: xxx}"其中xxx是动态值。
  2. :style="[a,b]"其中a、b是样式对象。
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
<!--
1.class绑定

PS: `<div class="one" :class="classArr"></div>` 重复class并不会报错,因为`:class`由Vue解析,会
自动合并原先class
-->
<div :class="classArr"></div> (1) 数组型
<div :class="classObj"></div> (2) 对象型

<div :class="flag ? 'one':'two'"></div> (3) 三目表达式,根据flag真假动态获取
<div :class="{'one':flag}"></div> 同(3)

<div :class="mood"></div> (4) 字符串型,可以通过方法去改变数据内容

<script>
new Vue({
el:'#demo'
data:{
flag: true,
mood:'nomal',
classArr:['one','two','three'],
classObj:{
one:true,
two:true,
three:false
}
}
})
</script>

style行内样式虽然很少用,但值得注意的是,命名规则都是驼峰命名,如下

1
<div :style="{fontSize:'40px',backgroundImage:'xxx'}"></div>

条件渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app-3">
<!--v-if="boolean"是一个布尔值-->
<!--v-show="boolean"同样是布尔值>
<p v-show="seen">现在你看到我了</p>
<p v-if="seen">现在你看到我了</p>
</div>
<script>
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
</script>

v-if 和 v-show的区别:v-if 的布尔值是false是不执行该标签的,不会渲染在DOM结构。v-show 是改变display属性,渲染在DOM结构

PS:频繁的显示和隐藏标签,请使用v-show

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true值的时候被渲染。

v-if && v-else联合使用

1
2
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>

v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

v-else-if和 js 里面的else-if是一样的功能,用来连续判断的

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--可以用判断句返回boolean值-->
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>

key管理可复用的元素

Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做除了使 Vue 变得非常快之外,还有其它一些好处。例如,如果你允许用户在不同的登录方式之间切换:

1
2
3
4
5
6
7
8
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
效果模拟:


结论:条件渲染时,会出现复用组件情况。这也是节约DOM性能。我们在输入值是,切换登录value值依然在,这就是复用了input组件。如果不希望出现这个结果,可以给input 添加 key属性,不同的key值,将会重新渲染一个新的组件,而不是复用

复用虚拟DOM,通过Key值

Vue渲染DOM,并不是简单的直接渲染成真实DOM,而是通过渲染成虚拟DOM,再渲染成真实DOM。Vue为了提高效率,会进行比对(diff算法),对可以进行复用的虚拟DOM直接拿过来渲染成真实DOM

在条件渲染v-for生成标签,使用:key="index" 通过key绑定唯一标识,来让Vue渲染

1
2
3
4
5
6
7
8
9
<!--
item: 数组每一个元素
index:索引值,如果以索引值作为唯一标识那么后期向数组arr后面添加元素是不会有问题的,但向前面添加就有问题了
:key最好绑定元素id,去绑定唯一标识,更好去复用虚拟DOM
-->
<ul>
<li v-for="(item,index) in arr" :key="index"></li>
</ul>

1.虚拟DOM中key的作用:

​ key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,

​ 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

2.对比规则:

​ (1).旧虚拟DOM中找到了与新虚拟DOM相同的key:

​ ①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!

​ ②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

​ (2).旧虚拟DOM中未找到与新虚拟DOM相同的key

​ 创建新的真实DOM,随后渲染到到页面。

3.用index作为key可能会引发的问题:

  1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:

​ 会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。

  1. 如果结构中还包含输入类的DOM:

​ 会产生错误DOM更新 ==> 界面有问题。

4.开发中如何选择key?:

  1. 最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。

  2. 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,

​ 使用index作为key是没有问题的。


列表渲染

我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items源数据数组,而 item 则是被迭代的数组元素的别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- 渲染数组,在data数据中存放了items数组,每一个li标签绑定了不同的key值,避免复用,
item 是别名,可以任意,但最好能表达数组含义。-->

<ul id="example-1">
<li v-for="item in items" :key="item">
{{ item.message }}
</li>
</ul>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
</script>

v-for 块中,我们可以访问所有父作用域的 property。v-for 还支持一个可选的第二个参数,即当前项的索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<ul id="example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var example2 = new Vue({
el: '#example-2',
data: {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
</script>

你也可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:

1
2
<div v-for="item of items"></div>

v-for 里使用对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
</script>

你也可以提供第二个的参数为 property 名称 (也就是键名):

1
2
3
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>

还可以用第三个参数作为索引:

1
2
3
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>

ES6语法遍历数组

1
2
3
4
5
6
7
8
9
10
11
12
13
//this.libararys是data数据数组,用in获取的是元素索引
//用of获取的是元素本身,如果是对象的话,直接获取拿到属性值
let sum=0;
for(let i in this.libararys){
sum+=this.libararys[i].num * this.libararys[i].price;
}

for(let item of this.libararys){
sum += item.price * item.num;
}

// v-for使用of遍历数组或对象,更符合JS迭代语法
v-for="item of items"

v-ifv-for 一起使用

v-ifv-for 一起使用时,v-for 具有比 v-if 更高的优先级。所以不建议同时使用。

列表过滤

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
new Vue({
el:'#demo',
data:{
keyWord:''//关键词
persons:[
{id:'1001',name:'simplelife1',age:18},
{id:'1002',name:'simplelife2',age:15},
{id:'1003',name:'simplelife3',age:28}
],
filerPersons:[]
},
watch:{
keyWord:{ // 检测关键词的变化
immediate=true,
handler(val){ // val:最新的值
this.filerPersons = this.persons.filter((p)=>{
return p.name.inderOf(this.keyWord) !=== -1
})
}
}
}
})

// filter 过滤函数是不改变数组,因此我们需要去用一个新函数接收,
// 但是我们DOM用过滤后的数组去渲染的,但是默认是为空的,因此我们需要先初始化执行一次handler函数
// 使用 immediate

数据更新的问题

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
<div id="root">
<h2>人员列表</h2>
<button @click="updateMei">更新马冬梅的信息</button>
<ul>
<li v-for="(p,index) of persons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>

<script type="text/javascript">
const vm = new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'马冬梅',age:30,sex:'女'},
{id:'002',name:'周冬雨',age:31,sex:'女'},
{id:'003',name:'周杰伦',age:18,sex:'男'},
{id:'004',name:'温兆伦',age:19,sex:'男'}
]
},
methods: {
updateMei(){
// this.persons[0].name = '马老师' //奏效
// this.persons[0].age = 50 //奏效
// this.persons[0].sex = '男' //奏效
this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'} //不奏效
// this.persons.splice(0,1,{id:'001',name:'马老师',age:50,sex:'男'})
}
}
})
</script>
<!--
当前注释的更新数据方法,都是响应式的,可以渲染到页面
但是直接去替换元素对象,它不是响应式的。

如果你对数据代理有深刻的了解,那么你的一定知道每一项数据都带着`get`和`set`方法,
但如上这种情况,是没有 get 和 set 的方法的,因此无法响应式渲染页面
-->

Vue.set()方法的使用

Vue监视数据的原理:

  1. vue会监视data中所有层次的数据。

  2. 如何监测对象中的数据?

​ 通过setter实现监视,且要在new Vue时就传入要监测的数据。

​ (1).对象中后追加的属性,Vue默认不做响应式处理

​ (2).如需给后添加的属性做响应式,请使用如下API:

Vue.set(target,propertyName/index,value)

vm.$set(target,propertyName/index,value)

  1. 如何监测数组中的数据?

​ 通过包裹数组更新元素的方法实现,本质就是做了两件事:

​ (1).调用原生对应的方法对数组进行更新。

​ (2).重新解析模板,进而更新页面。

  1. 在Vue修改数组中的某个元素一定要用如下方法:
  • 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
  • Vue.set() 或 vm.$set()

PS:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!

收集表单数据v-model

使用v-model收集表单数据

若:<input type="text"/>,则v-model收集的是value值,用户输入的就是value值。

若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值。

若:<input type="checkbox"/>

​ 1.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)

​ 2.配置input的value属性:

​ (1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)

​ (2)v-model的初始值是数组,那么收集的的就是value组成的数组

PS:v-model的三个修饰符:

​ lazy:失去焦点再收集数据

​ number:输入字符串转为有效的数字

​ trim:输入首尾空格过滤

生命周期

生命周期:又称生命周期回调函数、生命周期函数、生命周期钩子;Vue在关键时期会帮我们调用回调函数;生命周期函数的名称不可更改,不然无法被Vue识别;生命周期函数中的this指向Vue实例对象 或 组件实例对象。

1.常用的生命周期钩子:

​ 1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。

​ 2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。

2.关于销毁Vue实例

​ 1.销毁后借助Vue开发者工具看不到任何信息。

​ 2.销毁后自定义事件会失效,但原生DOM事件依然有效。

​ 3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。