Vue2入门学习笔记

Vue2入门必备!

⭐关注我查看更多配套笔记

学习视频:https://www.bilibili.com/video/BV1Zy4y1K7SH/

【尚硅谷Vue全家桶】

本博客是对该视频内容的整理以及加入自己的理解 想全面学习的推荐大家去看原视频

1.基础

1.特点

1.采用组件化模式,提高代码复用率,让代码更好维护

2.声明式编码,让编码人员无需直接操作DOM,提高开发效率

3.使用虚拟DOM + 优秀的Diff算法,尽量复用DOM节点

2.官网内容

官方网址 :cn.vuejs.org

3.下载及安装

1.下载

在官方网址 : 安装 — Vue.js (vuejs.org)

需要配置以下内容:

2.安装开发者工具

一、Chrome浏览器安装方式:
①:点击右上角三个点
②:点击更多工具
③:点击扩展程序
④:点击右上角的开发者模式,将他启用
⑤:将下载的Vue.crx文件直接拖动到浏览器窗口即可
二:Edge浏览器安装方式
①:点击浏览器右上角的三个点
②:点击扩展
③:点击左下角的开发人员模式,将他启用
④:将Vue.crx文件拖动到浏览器即可

https://pan.baidu.com/s/1MtYvMPew4lb14piIrs9x6w
提取码:6666

3.关闭开发者提示

Vue.config.productionTip = false;

2.基础使用

// 非Vue控制的函数尽量写成箭头函数

1.基础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
<div id="root">
<h1>你好,{{name}}</h1> <!-- 使用模板语法去渲染 -->
</div>

<div class="root">
<h1>你好,{{name}}</h1> <!-- {{ }} 中必须写JS表达式! -->
<h2>现在时间是{{Date.now()}}</h2>
</div>

<!-- 表达式: 一个表达式会生成一个值,可以放在任何一个需要值的地方 -->

<script>
x = new Vue({
el:'#root', //el用于指定当前Vue实例为哪个容器服务 通常为css选择器字符串
data:{ //储存数据,只能在指定的容器中去使用,值写成一个对象
name:'尚硅谷',
}
})

// 只会选择第一个 root
// 容器与Vue是一一对应的!!!
const y = new Vue({
el:'.root',
data:{
name:'尚硅谷'
}
// data第二种写法 函数式写法 vue自动调用该函数
// 不能使用箭头函数 this 会指向windows
data:fuction(){
console.log('QQQ', this)
return{
name:'尚硅谷'
}
}

}
})
// 使用方法修改参数
y.$mount('#root') // s修改实例构造器中的 element
</script>

2.模板语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 
插值语法
功能:用于解析标签体内容
写法:{[xXXx}]. xxx是js表达式,且可以直接读取到data中的所有属性
-->
<h1>你好,{{name}}</h1>

<!--
指令语法 设置元素的属性
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件.....)
举例:v-bind:href=""xxx”或简写为:href="xxx"",xxx同样要js表达式,且可以直接读取到data中的所有属性
备注:Vue中有很多的指令,且形式都是: v-????,此处我们只是拿v-bind举个例子。
-->
<a v-bind:href="url">点我</a>
<!-- 简写 -->
<a :href="url">点我</a>

3.数据绑定

1
2
3
4
5
6
7
8
<input v-bind:value="url">我是单项绑定
<input v-model:value="url">我是双向绑定
<!-- v-model 只能用在表单类元素上 输入类元素 含有value值 -->

<!-- 简写 -->
// 绑定后 为js表达式 不绑定为字符串
<input :value="url">我是单项绑定
<input v-model="url">我是双向绑定

4.MVVM模型

1.M:模型(Model):对应data中的数据

2.V:视图(View):模板

3.VM:视图模型(ViewModel) : Vue 实例对象心

image-20220328193753311

因此 vm 也经常作为 Vue的实例对象

const vm = new Vue({})

5.vm

1
2
3
4
5
6
7
8
9
<!--
vm中实例含有的内容
可以直接在 Vue 模板中直接使用
-->

<h1>
{{ $mount('#root') }}
</h1>
{{name}} 存在是因为会自动添加到 vm 对象中

6.进阶技术 Object方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 使用 object.defineProperty 添加对象成员
Object.defineProperty(对象名,添加的键,添加的值)

Object.defineProperty(obj,keys,{
value:18, // 设置
enumerable:true, // 控制属性是否可以被枚举(被遍历) 默认为false
writable:true, // 控制属性是否可以被修改 默认为false
configurable:true, // 控制属性石佛可以被删除 默认为false
// 当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get:function(){
return number;
}
// 简写
get(){
return number;
}
// getter 与 setter
set(value){
number = value;
}

})

7.数据代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--数据代理:通过一个对象代理对另一个对象中属性的操作(读/写) -->
<script>
obj1 = {
x:100,
}
obj2 = {
y:200,
}

Object.defineProperty(obj2,x,{
value:obj1.x, // 此处与 obj1 的属性绑定
})
</script>

数据代理在 Vue 中的应用

1
2
3
<!-- 
vm 实例中的数据 与构造器中 data中的数据绑定
-->

image-20220328202239085

_data实际上里面为数据劫持

8.事件的基本使用

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
<div id="root">
<!-- 事件触发回调函数 -->
// 需要传参可以加括号 但是 event会消失 加入 $event Vue帮助传参
<button v-on:click="showInfo($event,66)">点我提示信息</button>


<!-- 事件修饰符 + 简写 @ -->
<a href="#" @click.prevent="methods">点我跳转</a> // 阻止跳转
<!--
1.prevent: 阻止默认事件(常用);
2.stop:阻止事件冒泡(常用);
3.once:事件只触发一次(常用);
4.capture:使用事件的捕获模式;
5.self:只有event.target是当前操作的元素是才触发事件;
6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
// 默认的时候 先执行回调函数 等待回调函数执行完毕再运行默认事件(鼠标下滑等)
-->
</div>

<script>
x = new Vue({
el:'#root',
data:{ // 数据劫持 + 数据代理
name:'尚硅谷',
},
methods:{ // methods中的函数可以加到data中 但会拖累Vue
showInfo(event,number){ // event 为事件对象
alert("同学你好" + number);
},
aClick(e){
e.preventDefault();
alert("同学你好")
}
}

})
</script>

9.键盘事件

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
<!--准备好一个容器-->
<div id="root">
<h2>欢迎来到{{name}学习</h2> <!-- 这里的.enter代表按下键盘enter键 -->
<input type="text" placeholder="按下回车提示输入"@keyup.enter="showInfo">
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue在启动时生成生产提示
new Vue({
el : "#root",
data:{
name:"尚硅谷"
},
methods:showInfo(e){
console.log(e.target.value)
},
})
</script>
1.Vue中常用的按赞别名:
回车 =>enter
删除=>delete(捕获“删除”和“退格”键)
退出=>esc
空格=>space
换行=>tab
上=>up
下=>down
左=>left
右=> right
2.Vue未提供别名的按健,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)
caps-lock 大小写键别名
3.系统修饰健(用法特殊): ctrl、alt、shift、meta(win)
(1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键。事件才被触发。
(2).配合keydown使用:正常触发事件。
4.也可以使用keyCode去指定具休的按键(不推荐)
5.Vue.config.keyCodes.自定义健名=健码,可以去定制按健别名

/*

修饰符是可以连续使用的(链式调用)

  • @click.prevent.top
  • @keydown.alt.y /* y 与 alt 一起按下 */

*/

10.计算属性

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
57
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
// 模板中可以写一些简单的语句 但是不能写 Vm中没有的!
<h2>欢迎来到{{name = !name}}学习</h2>
<input type="text" placeholder="按下回车提示输入"@keyup.enter="showInfo">
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue在启动时生成生产提示
new Vue({
el : "#root",
data:{
// firstname 叫属性
// "尚硅谷" 叫属性值
firstname:"尚硅谷",
lastname:"snowman",
},
methods:{
get(){
// method中的方式不会缓存 会被多次调用
}
}
// computed的属性叫做计算属性
computed:{
// 输入 {{fullname}} 自动调用fullname get函数
fullname:{
// fullname 被读取调用get
get(){
// 此处的 this 被 Vue 配置为 vm
// get 什么时候调用?
// 1.初次读取fullname时 2.所依赖的数据改变时
return this.firstname + this.lastname;
// fullname 被修改时 调用set
set(value){
const arr = value.split('-');
this.firstname = arr[0];
this.lastname = arr[1];
}
/*
* 1.定义:要用的属性不有在,要通过已有属性计算得来。
* 2.原理:底层什助了objcet.defineproperty方法捉供的getter和setter.
* 3.get函数什么时候执行?
(1).初次读取时会执行一次.
(2).当依赖的数据发生改变时会被再次调用。
* 4.优势:与methods实现和比,内部有级存机制(复用)。效率更高。调试方便
* 5,备注:
1.计算届性最终会出现在vm上,直接读取使用即可..
2.如果计算属性要被修返,那必须写set函数夫响应修改,fset中要引起计算时依赖的数据发牛
*/
}
// 简写方式 确定只读不改
fullname(){
return "小猪佩奇";
}
}
}
})
</script>

11.监视属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Vue ({
// 监视在 vm 中的值是否发生变化 变化时 作何处理
watch:{
isHot:{
// 初始化时调用一次handler
immediate:true,
// isHot发生变化 传参 newValue为新的值 oldValue 为旧的值
handler(newValue,oldValue){
console.log(newValue,oldValue);
}
}
}
})
// 第二种写法 添加到vm实例中
vm.$watch('isHot',{
immediate:true,
handler(newValue,oldValue){
console.log(newValue,oldValue);
}
})

12.深度监视

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
// Vue可以检测多层级的监视 watch不检测
/*
* (1).vue中的watch默认不监测对象内部值的改变(一层)。
* (2).配置deep:true可以监测对象内部值改变(多层)。
* 备注:
* (1).vue自身可以监测对象内部值的改变,但vue提供的watch默认不可以!
* (2).使用watch时根据数据的具体结构,决定是否采用深度监视。
*/

Vue ({
data:{
number:{
a:500,
b:600,
},
name:'逯少',
}
// 监视在 vm 中的值是否发生变化 变化时 作何处理
watch:{
number:{
// 开启深度监视 不开启的话number的成员不会被检测
deep:true,
// 初始化时调用一次handler
immediate:true,
// number发生变化 传参 newValue为新的值 oldValue 为旧的值
handler(newValue,oldValue){
console.log(newValue,oldValue);
}
}
},
// watch 简写 前提: 不需要 deep immediate
watch:{
name(){
console.log("name被改变了");
}
}
})

// $符简写
vm.$watch('isHot',fuction(){
console.log("isHot被改变了");
})

13.watch与computed对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// computed更容易写
// 但是computed无法进行异步操作
// computed 需要返回值 异步会出错
// watch中的异步操作
handler(){
setTimeout(()=>{
console.log("1s passing number改变了");
},1000)
}
/*
* computed和lwatch之间的区别:
* 1.computed能完成的功能。 watch都可以完成..
* 2.watch能完成的功能,computed不一定能完成,例如: watch可以进行异步糅作。
* 1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象。
* 2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数。这样this的指向才是vm或组件实例对象。
*/

14.修改/绑定 class

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
Vue 会解析数组/对象 --> Js表达式

<!-- 需要的 class 是动态的 -->
<div class="basic" :class="yourclass"></div><br/><br/>
<!--绑定class样式--数组写法,适用丁:要绑定的样式个数不确定、名字也不确定-->
<div class="basic" :class="list_arr"></div>
<!--绑定class样式对象写法。适用于:要绑定的样式个数确定、名宁也确定但要动态决定用不川-->
<div class="basic" :class="classObj"></div>

<!-- Style行内样式 传入Style对象 或者 数组内包含Style对象-->
<div class="basic" :style="styleObj"></div>

---> 经过Vue解析之后会变成
<div class="basic normal"></div><br/><br/>
<div class="basic class1 class2 class3" :class="list_arr"></div>
<div class="basic class1 class3"></div>
<div class="basic" style="color:red;fontSize:10px;backgroundColir:grzy;"></div>


<script>
new Vue({
el:'#id',
data:{
yourclass:'normal',
list_arr:['class1','class2','class3'],
classObj:{
class1:true,
class2:false,
class3:true,
}
// 此处的样式必须为 css 中有的样式 font-size --> fontSize 多单词拆散大小写拼接
styleObj:{
color:red,
fontSize:10px,
backgroundColir:grzy,
}
}
})
</script>

15.条件渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- v-show 与 v-if show控制display属性 if直接会删除/保留该元素 -->
“” 中填写 js 表达式
<div v-show="false">我的display属性为none</div>
<div v-show="true">我的display属性为默认</div>

<!-- 与js语法中if else if else 的用法一致 -->
<div v-if="false">我不会在DOM中出现</div>
<div v-else-if="false">我不会在DOM中出现</div>
<div v-else="false">我不会在DOM中出现</div>
<div v-if="true">我会在DOM中出现</div>



需要整体隐藏的时候 使用 template不会影响结构
div也可以 注意css
template 只能与 v-if 配合 v-show 会失效
<template v-if="表达式">
<h1>h1</h1>
<h1>h2</h1>
</template>

16.列表渲染 循环

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
<div>
<ul>
<!-- 每个li标签需要有其单独唯一的标识 -->
<li v-for="p in persons" :key="p.id">{{p.id}}-{{p.name}}</li>


<!-- p为persons中的元素 index为其对应的下标 index写key比较方便 -->
<li v-for="(p,index) in persons" :key="index">{{p.id}}-{{p.name}}</li>

<!-- v-for 可以遍历 数组,对象,字符串 -->
<!-- 遍历对象 -->
<li v-for="(value,key) in Obj" :key="key">{{key}}-{{value}}</li>
</ul>
</div>

<script>
new Vue({
el:'#id',
data:{
persons:[
{id:"001", name:"001"},
{id:"002", name:"002"},
{id:"003", name:"003"},
]
Obj:{
name:"王二",
adress:"二仙桥",
}
}
})
</script>

<!--
v-for指令:
1.用于展示列表数据
2.语法:v-for="(item,index) in xxx" : key="yyy"
3.可逅历:数组、对象、字符串(用的很少)、指定次致(用的很少)
-->

17.循环 key详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 虚拟Dom 对比算法 !!! 对比后转化为真实 Dom
key 如果用 index进行绑定会出问题 -->
<!-- 一定要使用唯一的 key 可以使用数据库中的主键 -->

<!--
面试题: react、 vue中的key有什么作用?(key的内部原理)
1,虚拟DON中'key的作用:
key是虚拟DOA对象的标识,当状态中的数据发生变化时,Vue会根据【新数据】生成【新的虚拟DO随后Vue进行【新虚抵DOM】 与【旧虚拟DOM】的差异比较,比较规则如下:
2.对比规则:
(1).旧虚拟DOM中找到了与新虚拟DO相同的key:
若虚拟DOM中内容没变,百接使用之前的真实DOM
若虚拟DOM中内容变了,则生成新的真实DOM。随后替换掉页面中之前的真实DOM
(2).旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM。随后渲染到到页面。
3.用index作为key 可能会引发的问题:
1.若对数据进行:逆序添加、逆序剧除等破环顺序操作:
会产生没有必要的真实DOM更新==>界面效果没问题,但效率低。
2.如果结构中还包含输入类的DOM:
会产生错误DOM更新==>界面有问题
4.开发中如何选择key?:
1.最好使用每条数据的唯一标识作为key,I比如id、于机号、身份证号、学号等唯一伯。
2.如果不存在对数据的逆序添加、逆序朋除等破坏顺序操作,仅用于渲染列表用于展示使用index作为key是没有问题的。
-->

18.列表过滤 (搜索)

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
57
58
59
60
61
62
63
64
<input v-model="keyWord" placeholder="请输入姓名">
<ul>
<li v-for="p in filterPersons" :key="p.id">{{p.id}}-{{p.name}}</li>
<button @click="sortType = 1">id降序</button>
<button @click="sortType = 0">原排序</button>
</ul>


<script>
new Vue({
el:'#id',
data:{
sortType:0,
keyWord:"",
persons:[
{id:"001", name:"001"},
{id:"002", name:"002"},
{id:"003", name:"003"},
{id:"004", name:"004"},
],
filterPersons:[],
},
// 使用watch 实现搜索方法
watch:{
keyWords:{
immediate:true,
handler(val){
this.filterPersons = this.persons.filter((e)=>{
return p.name.indexOf(bal) !== -1;
})
}
}
},
// 计算属性实现

computed:{
filterPersons:{
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1;
})
}
}

// 实现 分需求 排序功能
computed:{
filterPersons:{
const list = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1;
})
if(this.sortType){
list.sort((p1.age,p2.age)=>{
return this.sortType === 1 ? p1.age-p2.age : p2.age-p1.age;
}
return list;
}
}
}

})
</script>

<!--
"abc".indexOf('') >>> 0 //空字符串返回值为 0
-->

3.Vue检测数据的原理

19.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
<!-- 更改数据 -->
<script>

// Vue无法检测
vm.persons[0] = {id:"001", name:"马老师", age:50};

// Vue可以检测
vm.persons[0].name = "马老师";
vm.persons[0].age = 50;
</script>

<script>
// data --> 加工后 vm 对象中生成 _data 包含data中的属性 并创建对应的getter setter方法
get set 方法 在调用 对象时会自动被更改


// 直接 object.defineProperty 对应的对象 调用get set 会陷入死循环

// 创建检测实例对象 进行数据代理
data = {
name:"王二",
age:18,
}
const obs = new Observer(data)
console.log(obs)

function observer(obj){
//汇总对象中所有的属性形成一个数组
const keys = object.keys(obj)
//遍历
keys.forEach((k)=>{
object.defineProperty(this,k,{
get(){
return obj[k]
},
set(val){
obj[k] = val
}
</script>
!!!!!! 检测原理就是使用setter 考虑非常周到!递归数组都能检测!!!

20.vue.set 添加响应式属性

1
2
3
4
5
6
7
8
9
10
11
12
13
// _data 与 data 是数据代理

// Vue 方法
Vue.set(target,key,value)
Vue.set(vm.student,"name","王二")
Vue.set(vm._data.student,"name","王二")

// vm 方法
vm.$set(vm.student,"name","王二")
vm.$set(vm._data.student,"name","王二")


// 局限性 set 不能 将 vm 作为 target

21.Vue检测数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 不能直接更改数组中的数值 vue 无法检测
// Vue 可以检测程序员使用数组方法

// 以下均为可以修改数组的方法
/* push/pop 末尾 添加/删除 元素
* unshift/shift 开头 添加/删除 元素
* splice 替换元素
* sort 排序
* reverse 反转
*/

// 两个push不一样 vue 对push进行了覆写 原push功能 + 响应式的更改
vm.data.student.hobby.push === Array.prototype.push
>>> false

总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
Vue监视数据的原理:
1. vue会监视data中所有层次的数据。
2.如何监测对象中的裁据
通过setter实现监视,且要在new Vue时就传入要监测的数据。
(1).对象中后追加的属性,Vue默认不做响应式处理
(2).如T给后添加的属性做响应式,请使用如下API:
vue.set(target.propertyName/index.value)
vm.$set(target. propertyName/index. value)
3。如何监测数组中的数据
通过包裹数组更新元素的方法实现,本质就是做了两件事:
(1).调用原生对应的方法对数组进行更新。
(2).重新解析模板,进而更新页面。
4.在Vue修改数组中的某个元素一定要用如下方法:
1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
2.Vue.set()或vm.$set()

特别注意: Vue.set()和 vm.$set()不能给vm 或 vm的根数据对象添加属性 !!
*/

4.收集表单数据

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
若:<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组成的数组
备注:v-model的三个修饰符:
lazy:失去焦点再收集数据
number:输入字符串转为有效的数字
trim:输入首尾空格过滤
*/

5.过滤器

day.js 库可以格式化时间

在BootCDN可以查询到开源的所有库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
过滤器 可以在 v-bind 与 插值语法中使用
<!-- 语法: 本质是一种函数 可以连续链式使用-->
<h3>现在是: {{time | timeFormater() | otherFilters()}}</h3>
<script>
// 全局过滤器 任意 Vue 实例对象中均可使用
Vue.filter("mySlice",fuction(){
return "过滤后的内容"
})
var vm = new Vue({
filters:{
timeFormater(value){
return "value为传入time的值 返回值作为 表达式展示的值"
}
}
})
</script>

6.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
<!--
v-bind :单向绑定解析表达式,可简写为:XXX
v-model :双向数据绑定
v-for :遍历数组/对象/字符串
v-on: 绑定事件监听,可简写为@
v-if:条件渲染(动态控制节点是否存存在)
v-else:条件渲染《动态控制节点是否存存在)
v-show:条件渲染(动态控制节点是否展示)
v-text: 替换整个 Value
v-html: 可以渲染html语法 <h1></h1>
// v-html 具有安全性问题 xss注入
v-cloak: 加入该属性与css display:none Vue接管时会删除该属性
v-once: 让某元素只渲染一次
v-pre: 阻止Vue解析doucment
-->

<!--
v-html指令:
1.作用:向指定节点中渲染包含html结构的内容
2.与插值语法的区别:
(1).v-html会替换掉节点中所有的内容,{{xx}}则不会
(2).v-html可以识别html结构。
3.严重注意: v-html有安全性问题!!!!
(1).在网站上动态渲染任意HTAL是非常危险的,容易导致XSS攻击.
(2).一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
-->

<!--
v-cloak指令(没有值):
1.本质是一个特殊属性,Vue实例创建完中并接管容器后。会删掉v-cloak属性.
2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。

-->
<style>
[v-cloak]{
display:none;
}
</style>



<!--
v-once指令:
1.v-once所在节点在初次动态渲染后,就视为静态内容了
2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
-->

<!--
v-pre指令:
1.跳过其所在节点的编译过程。
2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。

-->

7.Vue自定义指令

7.1函数式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
n放大十倍之后的值为:
<span v-big="n"> </span>
<input v-bind:value="n">


<script>
new Vue({
directives:{
// element传入对应元素对象
// binding 与 big中的表达式绑定 "n"
big(element,binding){
element.innerText = binding.value * 10;
// 绑定时会自动调用 但是 input 还没有放入doucment fouce不起作用
element.fouce();
}
// big函数何时会被调用?
// 1.指令与元素成功绑定时(一开始)
// 2.指令所在的模板被重新解析时
}
})
</script>

7.2对象式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<input v-fbind:value="n">

<script>
new Vue({
directives:{
// 此对象中所有的 this 均指向 window
fbind:{
// 绑定时被调用
bind(){
},
// 元素被插入时被调用
inserted(){
},
// 模板被重新解析时被调用
update(){
},
}
}
})
</script>

7.3小总结

1
2
3
4
5
6
7
8
9
注意: 命名时尽量不要用大写字母 Vue 会将大写字母 解析成小写字母
v-set-member ---> `set-member`(){}

<script>
// 全局Vue directives配置
Vue.directive('big',{
...
})
</script>

8.生命周期函数

8.1 mounted介绍

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
// 动态绑定数据需要写成对象的形式
<h2 style="{opacity: opacity}"> 我会变化透明度 </h2>
// 属性值与键名重复时可简写
<h2 style="{opacity}"></h2>
<script>
new Vue({
data:{
opacity:1,
},
methos:{
change(){
// 非 Vue 管理的函数 使用箭头函数 this 指向 Vue(vm)
setInterval(()=>{
this.opacity -= 0.01;
if(this.opacity <= 0) this.opacity = 1;
// 透明变化的字体
},16)
}
},
// mounted 挂载
// Vue完成模板的解析并且把初始的真实Dom放入元素页面后(挂在完毕后) 执行mounted
// 写入此处执行一次 mounted 函数 进行计时器函数书写
// 第一次放入时执行 !!! 之后的叫更新 重新解析 不执行 mounted
mounted(){
setInterval(()=>{
this.opacity -= 0.01;
if(this.opacity <= 0) this.opacity = 1;
// 透明变化的字体
},16)
}
// 生命周期函数有多种 这里只介绍了 mounted
})
</script>

8.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
<script>
new Vue({

tmplate:`在此处可以写 HTML 语法 替换模板`
// 初始化:生命周期、事件,但数据代理还未开始。
// 此时:无法通过vm访问到data中的数据. methods中的方法。
beforeCreate(){}

// 初始化:数据监测、数据代理。
// 此时:可以通过vm访问到data中的数据、 methods中配置的方法。
// 还未进行模板解析 生成虚拟DOM
created(){}

// 1.页面呈现的是未经Vue编译的DOM结构。
// 2.所有对DOM的操作,最终都不奏效。 因为在最后会使用 虚拟DOM 替换全部真实DOM
// 进行模板解析之后 虚拟DOM已生成
beforeMount(){}

// 将虚拟DOM转为真实DOM插入页面
// 1.页面中呈现的是经过Vue编译的DOM.
// 2.对DOM的操作均有效(尽可能避免)。
// 至此初始化过程结束,一般在此进行:
// 开启定时器、发送网络请求、订阅消息、绑定自定义事件、等初始化操作。
mounted(){}
})
</script>

8.3更新流程:

1
2
3
4
5
6
7
8
9
new Vue({
// 此时:数据是新的,但页面是旧的,即:页面尚未和数据保持同步。
beforeUpdate(){}

// 虚拟DOM 之间的对比 修改虚拟DOM

// 此时:数据是新的,页面也是新的,即:页面和数据保持同步。
updated(){}
})

8.4销毁流程

1
2
3
4
5
6
7
8
9
10
11
// 使用 $destroy() 方法 完全销毁vm实例 不会进行管理 DOM页面了
// vm.$destroy()
// 原生DOM事件不会被销毁 会销毁自定义事件

new Vue({
// 此时: vm中所有的: data、methods、指令等等,都处于可用状态,马上要执行销毁过程,一般在此阶段:关闭定时器、取消订阅消息.解绑自定义事件等收尾操作
beforeDestory(){}

// vm 已销毁
destoryed(){}
})

在这里插入图片描述

9.组件化 !!!

定义:现实应用中局部功能代码和资源的集合

非单文件组件∶

​ 一个文件中包含有n个组件。

单文件组件∶

​ 一个文件中只包含有1个组件。

1.非单文件组件

1.非单文件组件

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
// 1.创建组件
const school = Vue.extend({
// 不需要写 el 配置项 只可配置在 vm 实例中
// el:"",
// data 必须写成函数式
// 对象式引用的内存中同一地址 会出错(Vue报错阻止)
data:fouction(){
return {...}
}
template:`
HTML 内容
`
})


// 2.注册组件
new Vue({
el:"#root",
// 注册组件 (局部注册)
components:{
xuexiao:school,
// 以下可以简写
school:school,
// 简写形式
school
}
})
// 全局注册组件
// Vue.component('hello',hello)


// 3.在HTML页面中使用组件标签
// 在 components 中配置的键值
/*
<div id="root">
<xuexiao></xuexiao>
</div>
*/

注意点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Vue推荐组件命名
/*
单个单词: 1.school (纯小写) 2.School(首字母大写)
多个单词: 1.my-school (用-连接) 2.MySchool(每个单词首字母均大写 需要Vue脚手架支持)
备注:
(1).组件名尽可能回避HTAL中已有的元素名称,例如:h2、H2都不行。
(2).可以使用name配置项指定组件在开发者工具中呈现的名字。
Vue.extend({
name:"显示的名字",
})


2.关于组件标签:
第一种写法:<school></school>
第二种写法:<school/>
备注:不用使用脚手架时,<schoo1/>会导致后续组件不能渲染。

3.一个简写方式:
const school = Vue.extend(options)可简写为: const school = options
// 如果注册时传入的是对象 Vue 自动调用Vue.extend
*/

2.组件的嵌套

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 可以在组件中书写组件配置项

const school = Vue.extends({
template:"...",
compoent:{
scool,
"..."
}
})

const student = Vue.extends({
template:"...",
components:{
scool,
"..."
}
})

3. Vue Compoent构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
vm 实例中 包含 $children 为数组 数组中包含着 VueComponent 对象
VueComponent 中 的成员变量以及方法与 vm 一致

组件: 不可使用 el data 只能使用函数式
/*
关于VueComponent:
1.school组件木质是一个名为vueComponent的构造函数,且不是和序员定义的,是Vue.extend生成的。
2.我们只需要写<school/>或<schoolx</school>.Vue解析时会帮我们创建school组件的实例对象,Nvue帮我们执行的:new VueComponent(options)-
3.特别注意:每次调用vue.extend,返回的都是一个全新的VueComponent! !!!
4.关于this指向:
(1).组件配置中:
data函数、methods中的函数、watch中的函数、computed中的函数它们的this均是【VueComponent实例对象】
(2).new Vue配置中:
data雨数、methods中的函数、watch中的函数、computed中的函数它们的this均是【Vue实例对象】.
5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象).
Vue的实例对象,以后简称vm.
*/

4.重要的内置关系

1
2
3
4
/*
1.一个重要的内置关系:VueComponent.prototype._proto_ == Vue.prototype
2.为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性、方法。
*/

Vue 与 VueComponent 的关系

image-20220405165609319

2.单文件组件

{webpack, 脚手架} 编译使用 .vue后缀

image-20220405182255969

App结构

安装 VSCODE vue 插件 后 输入 <v tab键就可自动补全

image-20220405182553879

main.js

image-20220405182701818