vue学习笔记(vue核心知识)

目录

简介

使用Vue写一个"hello,world"

前置准备 

代码书写

MVVM模型理解

插值语法和指令语法

插值语法 

指令语法

指令:v-bind

 指令:v-model

 vue中的el和data的两种写法

 数据代理

方法:defineProperty() 说明(原生数据代理)

vue中的数据代理

 事件处理(绑定监听)

指令 v-on(用于事件监听)

方法参数说明

事件修饰符(阻止默认事件,阻止冒泡...)

键盘事件

计算属性

概述: 

作用演示

简写形式

监听属性

概述

作用演示

 监视多级属性-深度监视

简写形式

class绑定

概述

作用演示

数组和对象形式绑定class

style绑定 

作用演示

条件渲染

概述 

 如何使用

v-show和v-if的区别  

 template的使用(配合v-if)

列表渲染

如何使用

:key作用和原理

列表过滤和排序(案例)

vue数据监测的原理

Vue监测对象数据原理

方法Vue.set()和vm.$set()

 Vue监测数组数据的原理

数据劫持概念

收集表单数据

基本使用

v-model.number、v-model.lazy和v.model.trim 

过滤器

作用-用法 :

全局过滤器和局部过滤器

多重过滤器

自定义指令及内置常用指令

指令:v-text

指令:v-html

 指令:v-cloak

指令:v-once

指令:v-pre

自定义指令

 对象式 

参数说明 :

 函数式 

命名注意点

 Vue生命周期

挂载流程

更新流程

销毁流程


简介

此文章用于记录vue学习过程中笔记,知识点。

使用Vue写一个"hello,world"

前置准备 

 使用vue前,需要到vue官网下载vue的库vue.js,并且将文件vue.js正确引入到html结构中。

 点击连接,点击如下图的"开发版本"进行vue.js的下载。

 开发版本:占内存比较大,但是有vue的报错提示信息,比较适合学习和调试使用。

生产版本(压缩版):占内存较小,没有错误信息的提示信息,比较适合上线发布的程序使用。

将下载的vue.js引入html文件

// 根据自己实际情况引入正确路径
<script src="../vue.js"></script>

代码书写

先看代码:

// 1.引入vue.js文件
<script src="../vue.js"></script>
<body>
	// 2.准备一个模板容器
	<div id="root">
		<h1>{{info}}</h1>
	</div>
	<script>
		// 3.编写vue实例格式
		new Vue({
			// 4. 绑定模板容器(在此可使用CSS选择器)
			el:"#root",
			// 5. 编写数据模型
			data:{
				info:"Hello,World"
			}
		})
	</script>
</body>

 界面展示:

说明: 代码中,在DOM结构准备一个容器是必要的,并且需要将此容器绑定到vue实例中,从上述代码可以看出,vue实例的格式是固定的,只是其中的属性多少有无不同。也许有些看不懂代码中的{{info}}等地方,不要紧,先记住vue实例的固定写法格式即可,其他的下面会提及。

MVVM模型理解

为什么要了解MVVM模型?

我们可以先看vue官网对MVVM的一些说明:

可以看到,虽然vue没有完全遵循MVVM,但是此模型思想是重要的,因此我想我们有必要去了解MVVM。MVVM可以看为M-V-VM。

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

2. V:视图(View) :模板(DOM结构)

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

我们可以看如下代码:

<div id="root">
	<!-- M-V-VM中的V(模板视图) -->
	<h1>姓名:{{name}}</h1>
</div>
<script>
	var vm = new Vue({  //M-V-VM中的VM (vue实例)
		el:"#root",
		data:{ //M-V-VM中的M (数据模型)
			name:"Maohe"
		}
	})
</script>

VM(vue实例)是V(模板)和M(数据模型)之间的桥梁。

插值语法和指令语法

插值语法 

1. 功能: 用于解析标签体内容。

2. 语法: {{xxx}} ,xxxx 会作为 js 表达式解析。

 用法 

<body>
	<div id="root">
        // 插值语法
		<h1>姓名:{{name}}</h1>
	</div>
	<script>
		new Vue({
			el:"#root",
			data:{
				name:"MaoHe"
			}
		})
	</script>
</body>

页面效果:

指令语法

1. 功能: 解析标签属性、解析标签体内容、绑定事件。

2. 举例:v-bind:href = 'xxxx' ,xxxx 会作为 js 表达式被解析。

3.说明:vue中的指令有很多,在此使用v-bind和v-model演示用法。

指令:v-bind

1. 语法:v-bind:href ="xxx" 或简写为 :href

2. 特点:数据只能从 data 流向页面(数据单向绑定)

3.使用范围:任何标签都可用此指令

 用法-作用:

<div id="root">
    // 使用v-bind,可以跟vue实例data中对应模型绑定
	<a v-bind:href="rul">点击跳转</a>
    // 简写形式
    <a :href="rul">点击跳转</a>
</div>

<script>
	new Vue({ 
		el:"#root",
		data:{
			rul:"http://www.baidu.com"
		}
	})
</script>

使用v-bind,可以给标签中属性做绑定,当vue中data(数据模型)发生变化的时候,页面(模板)设置有指令v-bind的标签属性也会跟着改变。

重要特性:为什么data中的数据发生变化,模板里的数据会跟着改变?

因为当data中数据发生改变的时候,vue会重新加载模板,所以解析到标签使中用了data中的数据时,就会重新赋值,就会达到当vue中data发生变化,则模板中数据会跟着变化。

 指令:v-model

1. 语法:v-mode:value="xxx" 或简写为 v-model="xxx"

2. 特点:数据不仅能从 data 流向页面,还能从页面流向 data(数据模型)。

3.适用范围:只有表单元素可以使用,因为v-model是服务与value属性的,是双向绑定,如果页面没有输入,那么数据双向绑定也就没有了意义。

 用法-作用:

<div id="root">
    // 使用指令:v-model (数据双向绑定)
	姓名:<input type="text" v-model:value="name">
    // 简写形式(value可以省略)
    姓名:<input type="text" v-model="name">
</div>
<script>
	new Vue({
		el:"#root",
		data:{
			name:"MaoHe"
		}
	})
</script>

 效果:

当我们改变输入框中内容时,vue实例中的data也会跟着改变,相同的,我们改变data中的数据,页面的输入框内容也会改变。这就是数据的双向绑定。这就是区别于v-bind的重要特点。

v-model操作的是表单元素,也就是说,只要标签中有value属性的都可以使用指令v-model。例如:单选框,多选框等等。 

 vue中的el和data的两种写法

说明:在vue实例el和data书写的时候,还有另一种格式,在vue实例外书写。看如下格式:

 el的另一种写法 

<div id="root">
    // 使用指令:v-model (数据双向绑定)
	姓名:<input type="text" v-model:value="name">
    // 简写形式(value可以省略)
    姓名:<input type="text" v-model="name">
</div>
<script>
	var vm = new Vue({
		//el:"#root",
		data:{
			name:"MaoHe"
		}
	})
    // 在vue实例后添加el容器的绑定
    vm.$mount("#root")
</script>

data的另一种写法

<div id="root">
	姓名:<input type="text" v-model:value="name">
</div>
<script>
	new Vue({
		el:"#root",
        // 对象式的写法 
		// data:{
		// 	name:"MaoHe"
		// }
        // 函数式的写法
		data:function(){
			return{
				name:"MaoHe"
			}
		}
	})
</script>

 数据代理

通过一个对象代理对另一个对象中属性的操作(读/写) ,例如对象a代理对象b中的name属性,当我们操作a中的name属性,实际上改变的是b中的name属性。

方法:defineProperty() 说明(原生数据代理)

 在说vue的数据代理之前,需要先说明方法defineProperty(),因为vue的数据代理底层使用的就是此方法。所以有必要了解此方法。

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

参数:

Object.defineProperty(obj, prop, descriptor)

obj:要定义属性的对象。

prop:要定义或修改的属性名称。

desctipt:要定义或修改的属性描述符。

  需求:现有对象obj1和对象obj2,我们让obj2代理obj1中的name属性。如下:

<script>
	obj1 = {name:"Maohe"};
	obj2 = {age:18};
	//当使用obj2操作name属性时,实际变动的是obj1中的name属性。
	Object.defineProperty(obj2,"name",{
		get() {
			return obj1.name;
		},
		set(value){
			obj1.name = value;
		}
	})
	//测试
	console.log(obj2.name); //输出:Maohe
	console.log(obj1.name); //输出:Maohe
	obj2.name = "Tom";
	console.log(obj2.name); //输出:Tom
	console.log(obj1.name); //输出:Tom
</script>

通过上述代码容易看出,对象obj2中本来是没有name属性的,但是通过defineProperty()方法设置了数据代理,使得obj2可以操作obj1中的name属性。就是将obj1中的name属性代理给了obj2

vue中的数据代理

 当我们访问模型data中的数据时,例如一个属性name,我们在插值表达式中是直接写name,而不是data.name,在此就是做了数据代理,而且data的数据存在VUE实例中也不叫data,而是_data。

<div id="root">
	<h1>{{name}}</h1>
</div>
<script>
	var vm = new Vue({
		el:"#root",
		data:{
			name:"MaoHe"
		}
	})
</script>

我们可以看一下vue实例中的东西(在控制台输出vm):

 一个数据代理图示:

总结:

 当我们在data中声明了属性,这些属性就会被vue自动的加上数据代理,将代理对象放到vm中,例如:如上图例,在data中声明了name和address属性,vue会先将两个属性添加到vm的_data中,然后使用defineProperty()方法给两个属性设置代理,将name和address代理者放到vm中。当操作vm中的name和address,实际上改变的是_data中的name和address。

 事件处理(绑定监听)

事件处理,也就是给某节点绑定事件。

如下是书写的概述:

1. v-on:xxx="fun"  ---正常写法,xxx是事件名称,如点击click

2. @xxx="fun"  ---@简写

3. @xxx="fun(参数)"  ---有框号用于传递参数

4. 默认事件形参: event  ---接收事件参数(没有参数时)

5. 隐含属性对象: $event ---接收事件参数(有参数时)

指令 v-on(用于事件监听)

 用法:

// 需求:当点击按钮,触发showAlert方法,出现弹窗。 
<div id="root">
	<h1>指令v-on的说明</h1><br>
    // 一般书写
	<button v-on:click = "showAlert">点击弹窗</button>
    // 简写形式
    <button @click = "showAlert">点击弹窗</button>
</div>
<script>
	new Vue({
		el:"#root",
		data:{},
		methods: {
			showAlert() {
				alert("我是弹窗...")
			}
		},
	})
</script>

方法参数说明

在上如案例中,代码:v-on:click = "showAlert" ,调用的时候可以不用括号,代表不传参数的调用方法,但是在vue的方法调用中,会有一个默认的事件对象,不用传入也可以接收到。看如下:

new Vue({
		el:"#root",
		data:{},
		methods: {
			showAlert(e) {
                console.log(e);
				alert("我是弹窗...")
			}
		},
	})

当我们触发点击事件后,会打印e,这个e就是事件对象。输入如下:

 会有触发事件时的一些状态信息。例如触发事件的节点,点击页面的位置信息等等。

其实如上方式输入事件对象是一种特殊,也就是当没有参数的方法调用时,上面的方式是有效的,但是如果有参数的调用,那么将不会接收到事件对象了。如下:

<div id="root">
	<h1>指令v-on的说明</h1><br>
	<!-- <button v-on:click = "showAlert">点击弹窗</button> -->
	<button @click = "showAlert(18)">点击弹窗</button>
</div>
<script>
	new Vue({
		el:"#root",
		data:{},
		methods: {
			showAlert(args1,args2,agrs3) {
				//打印事件对象
				console.log(args1); //18
				console.log(args2); //undefined
				console.log(args3); //报错args3 is not defined
				alert("我是弹窗...")
			}
		},
	})
</script>

那么我们该如何获取事件对象呢?可以看如下代码:

<div id="root">
	<h1>指令v-on的说明</h1><br>
	<!-- <button v-on:click = "showAlert">点击弹窗</button> -->
	<button @click = "showAlert($event,18)">点击弹窗</button>
</div>
<script>
	new Vue({
		el:"#root",
		data:{},
		methods: {
			showAlert(args1,args2,agrs3) {
				//打印事件对象
				console.log(args1); //事件对象
				console.log(args2); //18
				console.log(args3); //报错args3 is not defined
				alert("我是弹窗...")
			}
		},
	})
</script>

事件修饰符(阻止默认事件,阻止冒泡...)

先介绍vue中的事件修饰符,接下来再演示用法。 

Vue中的事件修饰符:

1、prevent: 阻止默认事件。

2、stop:阻止事件冒泡。

3、once:事件只触发一次。

4、capture:使用事件的捕获模式。

5、self:只有event.target是当前操作的元素是才触发事件。

6、passive:事件的默认行为立即执行,无需等待事件回调执行完毕。

 事件修饰符的用法:

事件修饰符的使用方式是简单的,下面我们就使用preven阻止默认事件和stop阻止事件冒泡做演示即可。其他的用法都一样,只是功能不同罢了。

 阻止默认事件演示 

<div id="root"> 
	// 阻止默认事件
    // 当点击时,a标签的默认事件是跳转到href属性的地址
    // 我们使用链式编程的方式书写.prevent后,将不再会跳转
	<a @click.prevent= "showAlert" href="http://www.baidu.com">点击跳转</a>
</div>
<script>
	new Vue({
		el:"#root",
		data:{},
		methods: {
			showAlert() {
				alert("我是弹窗!")
			}
		},
	})
</script>

 阻止事件冒泡演示 

<div id="root"> 
	<div title="我是父标签" id="father" @click="bubble">
        父标签
		<!-- // 阻止事件冒泡 -->
		<div title="我是子标签" id="sun" @click="bubble">
			子标签
		</div>
	</div>
</div>
<script>
	new Vue({
		el:"#root",
		data:{},
		methods: {
			showAlert() {
				alert("我是弹窗!")
			},
			bubble(){
				alert("我是div点击触发的弹窗...")
			}
		},
	})
</script>

  页面效果 

 说明:根据事件冒泡原理,当我们点击子标签后(红色背景盒子),会触发点击事件,然后会自动冒泡到父标签,父标签又会触发一次同一个点击事件。也就是会出现两次弹窗,bubble方法会执行两次。

那么,在vue中阻止事件冒泡方式很简单,看如下代码:(在上面代码的基础上进行改动)

<!-- 只需要在子标签@click后添加.stop即可阻止事件冒泡 -->
<div title="我是父标签" id="father" @click="bubble">
	父标签
	<!-- // 阻止事件冒泡 -->
	<div title="我是子标签" id="sun" @click.stop="bubble">
		子标签
	</div>
</div>

键盘事件

在vue中绑定键盘事件的方式和上面的点击事件是一样的,@keydown,@keyup...,这些不值得多说,值得提的是我们想要确定用户点击了某个按键,和组合键的判断,这是我们需要注意的地方。

需求: 想要判断用户是否按下了x键。

<div id="root">
	<input type="text" @keydown.x="keyDownX" >
</div>
<script>
	new Vue({
		el:"#root",
		methods: {
			keyDownX() {
				alert("按下了x键")
			}
		},
	})
</script>

 需求:判断用户是否按下了esc键

<div id="root">
	<input type="text" @keydown.esc="keyDownESC" >
</div>
<script>
	new Vue({
		el:"#root",
		methods: {
			keyDownESC() {
				alert("按下了esc键")
			}
		},
	})
</script>

说明:为什么我们可通过@keydown.x ,@keydown.esc就可以锁定x,或esc键呢?

其实是vue给我们这些键设置了别名。一些字母和一些功能键可以这样绑定,但是,如果需要我们判断用户是否按下数字键1,2,3等等,那么我们不就没招了吗?当然不是,下面讲解,但是需要先了解vue帮我们封装了哪些内置的按键别名。

==========vue内置的键盘按键别名==============

 回车 => enter

删除 => delete(此处捕获"删除"和"退格") 

退出 => esc

空格 => space

制表符 => tab

上 => up

下 => down

左 => left

右 => right

=======================================

 keyCode的方式绑定按键(通用方法)

 一个演示

需求:判断用户是否按下数字键1

<div id="root">
	<input type="text" @keydown.97="keyDown" >
</div>
<script>
	new Vue({
		el:"#root",
		methods: {
			keyDown() {
				// console.log(e.keyde);
				alert("按下了数字键1")
			}
		},
	})
</script>

看到@keydown.97也许会有疑问,这个97为什么可以代表数字1,这其实是数字1的键码,也就是ascii码表中数字1的码值,不晓得的可以百度一下ascii码表,就会看到一张表,ascii码表上有着所有字符代表的数字。

但是,如果每次我们想要知道某个按键的键码,那么每次都去看ascii码表就会太麻烦了,因此,我们可以动态的某个键的键码,可以看如下代码:

<div id="root">
	<input type="text" @keydown="keyDown" >
</div>
<script>
	new Vue({
		el:"#root",
		methods: {
			keyDown(e) {
                // 通过事件对象,获取用户输入的键的键码
				console.log(e.keyCode);
			}
		},
	})
</script>

 这样用户就可以通过此方式获取任意键的键码,通过@keydown.键码来绑定事件了。

 需求:判断用户是否按下了alt + a 组合键

<div id="root">
			<input type="text" @keyup.alt.a="keyDown" >
		</div>
		<script>
			new Vue({
				el:"#root",
				methods: {
					keyDown() {
						// console.log(e.keyCode);
						alert("按下了alt + a 组合键")
					}
				},
			})
		</script>

如上就是组合键的判断,类似,想要什么键组合就链式编程连起来即可。

 自定义键名  

 说明:如果一个键经常使用的话,那么使用键码来绑定的话,可读性可能没那么好,那么我们就想,能不能像vue中的内置别名一样,我们也设置常用的键的别名,使用时直接通过@keyup.自定义键名就能绑定事件。

自定义键别名:给delete设置键别名为del。

首先,我们需要先知道delete的键码,通过上面我们已经知道该如何获取一个键的键码,要么通过事件对象获取keycode要么去查ascii码表,delete的键码为46

那么我们就可以这样设置自定义键别名:

<div id="root">
    // vue内置delete键别名绑定事件
	<input type="text" @keyup.delete="keyDown" >
    // 通过用户自定义键别名绑定事件
	<input type="text" @keyup.del="keyDown" >
</div>
<script>
	// 自定义键别名
	Vue.config.keyCodes.del = 46; //delete键的键码为46
	new Vue({
		el:"#root",
		methods: {
			keyDown(e) {
				alert("Delete...")
			}
		},
	})
</script>

计算属性

概述: 

1. 什么是计算属性(作用):要显示的数据不存在,要通过已有的属性计算得来。

2. 书写位置:在 computed 对象中定义计算属性。

3. 数据展示:在页面中使用{{方法名}}来显示计算的结果

作用演示

需求:有两个输入框,一个输入姓名的姓一个输入姓名的名,当用户输入后将自动识别,将全名显示出来。

 界面:

 代码(使用计算属性):

<div id="root">
	姓<input type="text" v-model="firstName"><br>
	名<input type="text" v-model="lastName"><br><br>
	全名:<span>{{fullName}}</span>
</div>

<script>
	new Vue({
		el:"#root",
		data:{
			firstName:"张",
			lastName:"三"
		},
		computed:{
			fullName:{
				get(){
					return this.firstName + this.lastName
				}
			}
		}
	})
</script>

说明:使用计算属性,格式看代码演示,在computed关键字中,将计算属性名写上,在计算属性作用域中写get和set方法,我们不需要设置fullName所以不需要设置set方法,在其中,当模板解析到{{fullName}}时,会调用到get方法但是不是每一次都会调用一次,计算属性computed存在缓存,在一定条件下才会调用,此条件下面会说到,在案例中将返回值给到fullName属性。

优势:

其实在上面的案例中,我们是可以直接用原生JS书写方法,在方法中写拼接语句也可以实现,但是对比计算属性,在此计算属性优势还是比较大的,因为计算属性存在缓存机制,方法调用较少,效率更高些。

缓存机制当我们调用get函数后,其实底层是会给get函数的返回值做缓存的,当计算属性的依赖数据没有改变,也就是fullName的firstName和lastName没有改变的时候,当再次访问fullName属性时,不需要再次调用get方法获取返回值给fullNane属性,而是从缓存中将数据给到fullName,但是也许会有一个疑问,当依赖数据发生改变的时候,那么还从缓存中拿,而不重新调用get方法获取返回值给计算属性的话,计算属性数据不就过时了吗?其实不然,在了解get方法的调用时机后会解决改疑问(调用时机如下会提到)。

总结:

1.看案例可以看出,我们的计算属性是不需要事先在vm的data中定义的

2.底层原理:底层还是使用到了数据代理,object.defineproperty()中提供的get和set方法。

这样使我们才可以在插值语法中直接使用计算属性。

3.get函数调用时机

        (1).第一次解析模板读取到计算属性时执行,将返回值给到计算属性。

        (2).当计算属性使用的数据依赖发生改变时会调用(在案例中就是当firstName和lastName发生变化时,会重新调用get方法,将新拼接的全名给到fullName)。

简写形式

从上面的案例中,看出计算属性的书写还是有点繁琐的,其实当计算属性中只有get方法,是可以简写的。书写形式如下:

<div id="root">
	姓<input type="text" v-model="firstName"><br>
	名<input type="text" v-model="lastName"><br><br>
	全名:<span>{{fullName}}</span>
</div>

<script>
	new Vue({
		el:"#root",
		data:{
			firstName:"张",
			lastName:"三"
		},
		computed:{
			fullName:function(){
				return this.firstName + this.lastName;
			}
		}
	})
</script>

监听属性

概述

1. 书写形式:通过 vm 对象的$watch()或 watch 配置来监视指定的属性。

2. 作用:当监听的属性变化时, 回调函数自动调用, 在函数内部进行计算。

作用演示

演示需求:监听data中的flag属性,当flag变化时控制台打印提示。

 页面:

点击按钮控制台提示 

  

 代码:

<div id="root">
	<span>当前flag值为:{{flag}}</span><br><br>
	<button @click="change">点击切换</button>
</div>
<script>
	new Vue({
		el:"#root",
		data:{
			flag:true
		},
		watch:{
			flag:{
				handler(newValue,oldValue){
					console.log("flag变化了,原为:",oldValue,"变化为",newValue,);
				}
			}
		},
		methods: {
			change() {
				this.flag = !this.flag;
			}
		},
	})
</script>

说明:如上案例,我们对flag属性进行了监视,当flag值发生改变的时候,我们会在控制台输出提示。这是一种最简单的属性监视。

 监视多级属性-深度监视

案例需求:现在一个属性people,属性peole下又有name和age属性。此时,我们想要监视people下的name属性,当name属性变化时,我们控制台输入提示。

 页面:

 代码:

<div id="root">
	<span>name值为:{{people.name}}</span><br><br>
	name值:<input type="text" v-model="people.name">
</div>
<script>
	new Vue({
		el:"#root",
		data:{
			people:{
				name:"Maohe",
				age:18
			}
		},
		watch: {
			'people.name':{
				handler(){
					console.log("people下面的name变化了...");
				}
			}
		}
	})
</script>

过渡说明:看了上面的案例,我们知道了如何监视多级属性下的某个属性是否变化,但是如果我们想要监视多级属性的父属性,也就是上面案例的people属性,如果我们像监视people属性是否变化,那么只有当people下面的所有属性name和age都变化时,才会触发handler,这是一种情况,但是,在一般情况下,我们想要达到的效果是:只要people下面的任一属性发生变化,那么handler就会触发。这时我们就要使用深度监视。

开始深度监视:

设置配置项deep为true即为开启深度监视。

简写形式

 值得注意的是:使用如上的简写形式会有一些限制,就是不能够深度监视属性,因为没有地方设置配置项deep为true了,使用简写形式,就只能默认使用普通监视。但基本也够用,是否使用深度监视需要看开发时的数据结构。

class绑定

 此处的classs绑定说的是使用vue对DOM标签绑定上类名的一些格式。

概述

1. 书写格式:  :class='xxx'

2. 书写形式一:表达式是字符串: 'classA'

3. 书写形式二:表达式是对象: {classA:isA, classB: isB}

4. 书写形式三:表达式是数组: ['classA', 'classB']

作用演示

需求:当我们在div标签中使用class指定了类名后,我们再想要去给此div盒子追加类名,那么这时候我们有两种选择,第一种是使用原始方式,在类名后空格追加,另一种是使用vue的:class形式追加。两种方式比较说明在下面会说到,接下来看两种形式的代码书写。

 原始方式给标签绑定多了类名

<div class="c1 c2">
<!--原始方式绑定多个class-->
</div>

vue中class绑定的方式

<div id="root">
	<div class="c1" :class="divClassName">
		// vue中绑定class
	</div>
	<script>
		new Vue({
			el:"#root",
			data:{
				divClassName:"c2"
			}
		})
	</script>
</div>

说明:上述的代码中使用了:class的方式进行class的绑定,这样写有些人会觉得是多次一举,因为书写好像比较繁琐,要多写:class和多定义数据模型,但是其实这样的可扩展性更好一些,想要修改直接在模型中修改即可。

数组和对象形式绑定class

 在上述的例子中,我们只能多绑定一个class,那么当我们要绑定更多class的时候,使用上述的方式显然不行了,这时候就需要使用到数组和对象的形式才可以将多个class绑定上。

 数组形式绑定class

<div id="root">
	<div class="c1" :class="classArray">
		
	</div>
	<script>
		new Vue({
			el:"#root",
			data:{
				classArray:["c2","c3"]
			}
		})
	</script>
</div>

对象形式绑定class

<div id="root">
	<div class="c1" :class="classObj">
		
	</div>
	<script>
		new Vue({
			el:"#root",
			data:{
				classObj:{
                    //使用true或false决定是否使用此class
					c2:true,
					c3:true
				}
			}
		})
	</script>
</div>

说明:在对象绑定class中,我们发现是比较特殊的,在对象中类名是键,而值是布尔值,使用布尔值控制是否使用此属性,还是比较实用的。

style绑定 

vue中style绑定和class绑定的用法非常相似,只有功能有所区别,一个是绑定类名一个是绑定样式罢了。

作用演示

需求:使用vue的style绑定给一个div盒子添加一个背景和宽高的样式。

<div id="root">
	<div :style="styleObj">
		vue进行style绑定
	</div>
</div>
<script>
	new Vue({
		el:"#root",
		data:{
			styleObj:{
				width:"200px",
				height:"200px",
				backgroundColor:"red"
			}
		}
	})
</script>

值得注意的是,使用上述对象的形式添加样式,当样式属性名是由"-"连接的,那么我们在对象域中就应该使用小驼峰的格式书写样式名。比如background-color变成backgroundColor。

绑定style的其他方式

其实在vue中绑定style不只上述的对象形式绑定,还可以直接在标签上书写,以及使用数组的形式书写。如何使用看如下代码: 

直接在标签上定义 

<div :style="{backgroundColor:'red'}">
	vue进行style绑定
</div>

绑定数组

<div id="root">
	<div :style="[styleA,styleB]">
		vue进行style绑定
	</div>
</div>
<script>
	new Vue({
		el:"#root",
		data:{
			styleA:{
				width:"200px",
				height:"200px"
			},
			styleB:{
				backgroundColor:"red"
			}
		}
	})
</script>

条件渲染

概述 

什么是条件渲染:我们可以将条件渲染分为"条件"和"渲染"来看,就是当满足某些条件,我们就在页面渲染某些东西。

作用:根据条件使标签选择性在页面显示。

使用指令:v-if、v-else-if、v-else和v-show。

 如何使用

需求: 定义一个属性age,当age大于18时,页面展示"可以观看"否则显示"不可观看"。

使用v-show实现

<div id="root">
	<div v-show="age >= 18">
		提示:已满18,可以观看
	</div>
	<div v-show="age < 18">
		提示:未成年不可以观看
	</div>
</div>
<script>
	new Vue({
		el:"#root",
		data:{
			age:18
		}
	})
</script>

页面检查代码:

可以看到使用v-show的话,未显示的vue底层很简单,就是加了一个display为none罢了。

使用v-if实现

<div id="root">
	<div v-if="age >= 18">
		提示:已满18,可以观看
	</div>
	<div v-else>
		提示:未成年不可以观看
	</div>
</div>
<script>
	new Vue({
		el:"#root",
		data:{
			age:17
		}
	})
</script>

页面代码检查 

 

 可以看到,使用if的话,当条件不成立,对应的分支直接在结构中被删除了。

那么,既然v-show和v-if都可以实现,两者使用该如何选择呢?

v-show和v-if的区别  

1.v-if 与 v-show 都能控制dom元素在页面的显示,但是v-if和v-show的控制手段不同,v-show隐藏则是为该元素添加css--display:nonedom元素依旧还在。v-if显示隐藏是将dom元素整个添加或删除
2.v-if 相比 v-show 开销更大的(直接操作dom节点增加与删除)
3.如果需要非常频繁地切换,则使用 v-show 较好
4.如果在运行时条件很少改变,则使用 v-if 较好

 template的使用(配合v-if)

需求:例如我们有3个h1标签,当我们想要给所有h1标签添加判断age大于等于18时都显示,那么我们就要给所有h1都书写v-if或v-show控制显示,这样的书写方式是冗余的,那么我们就可以有一个解决方法,就是在所有h1的外边添加一个div包裹,给此div添加一个判断是否显示即可,但是使用div包裹会影响DOM结构,例如加了以后css选择器就找不到标签了,所以我们应该使用template标签,此标签在DOM解析时不会被解析,就不会影响结构了。

<template v-if="age >= 18">
	<h1>您已18</h1>
	<h1>可以观看</h1>
	<h1>注意身体</h1>
</template> 

列表渲染

顾名思义,列表渲染就是对列表的展示进行控制。上方说的是if可以看作是条件判断,那么在此就可以看作是循环。

如何使用

 需求:定义一个数组,使用v-for使数组中全部元素进行渲染。

<ul id="roo	t">
	<li v-for="user in users" >
		姓名:{{user}}
	</li>
</ul>
<script>
	new Vue({
		el:"#root",
		data:{
			users:["王虎","王小虎","王大虎"]
		}
	})
</script>

页面展示:

代码说明:在指令v-for中,users代表可迭代对象 ,user代表自定义变量,用来接收可迭代对象中的每一个对象。

可迭代对象:就是可以进行遍历的对象,例如数组,字符串,对象等。

遍历次数v-for遍历的次数是根据可迭代对象的”长度”决定的。

在上面的代码中,其实严格来说是有缺陷的,在使用v-for的使用,必须有唯一标识符

 例如下面代码 

<ul id="root">
	<li v-for="user in users" :key="user.id">
		姓名:{{user.name}}
	</li>
</ul>
<script>
	new Vue({
		el:"#root",
		data:{
			users:[
				{id:001,name:"王虎"},
				{id:002,name:"王大虎"},
				{id:003,name:"王小虎"}]
		}
	})
</script>

 页面展示:

 代码说明:在上方代码,可迭代对象变成了对象数组,数组中的每一个对象中有id和name,我们使用每一个对象的id作为此<li>标签的唯一标识。

这时候也许问题就出来了,我们第一块代码并没有使用任何标识填写:key,那么编译也没有报错,页面展示也正常,这是为什么呢?

不写:key底层做了什么?

 当我们在v-for后不写:key时,其实底层是使用了内置的索引index作为唯一标识

看如下代码:

<ul id="root">
	<li v-for="(user,index) in users" :key="index">
		姓名:{{user.name}}-{{index}}
	</li>
</ul>
<script>
	new Vue({
		el:"#root",
		data:{
			users:[
				{id:001,name:"王虎"},
				{id:002,name:"王大虎"},
				{id:003,name:"王小虎"}]
		}
	})
</script>

在v-for后面接收可迭代对象的变量有两个,user和index我们都使用{{}}进行页面显示:

 可以看到参数index为0,1,2....,所以我们就能使用index作为:key的值。当我们什么都不写时,底层也会自动的使用index作为唯一标识。

:key作用和原理

为什么要书写:key

key是给vue底层的虚拟DOM使用的,用来作为虚拟节点的唯一标识,以及给对比算法(diff算法)做比较使用,所以在底层的虚拟DOM中必须要有key。

虚拟DOM和对比算法

虚拟DOM:可以看作是在内存中的一个结构,作用是为了提高代码的复用性和效率。

对比算法对比过程:例如当我们创建了3个<li>标签,3个<li>标签中的内容均不同,当我们保存代码以后,vue底层就会创建3个<li>的虚拟DOM保存在内存中,然后转换成真实DOM在页面做渲染后我们就可以看见了,这时我们修改其中的第一个<li>标签中的内容然后保存,在底层就会再次生成新的虚拟DOM,接着所有的<li>使用对比算法,根据<li>中唯一标识key取出<li>旧的虚拟DOM相同的唯一标识key的<li>进行对比,发现只有一个li内容发生了改变,就将改变的这一个<li>进行转换成真实DOM做页面渲染,而其中没有改变的两个<li>则直接复用之前的即可不需要再次转换成真实DOM,实现了复用调高了效率。

使用自定义唯一标识和index,如何选择? 

 根据上述案例,我们知道书写唯一标识有两种方式,一种是我们自定义,一种则是使用内置的index,那么,我们该如何选择呢?

当操作会打乱节点顺序的时候,不建议使用index。

 原因:

我们知道index是自动生成的,并且在做虚拟DOM对比的时候,是根据新旧虚拟DOM中key相同为依据取出li的做对比的。那么如果我们后续在原有的节点最前面动态插入一个节点,使用index的话会重新自动从0开始添加索引,那么在做对比的时候,根据key前后取出的li将会都不一样,甚至导致出现数据错乱问题,使得都要重新转换成真实DOM,代码复用性不好,效率低。

举例:

我们有三个li,索引分别是0,1,2,当我们在三个li前面动态添加一个li,那么这时候使用index自动生成索引填充key,新添加的li索引将为0,而旧的三个li将为1,2,3,旧的三个li索引都会往后推。索引都改变了,那么这时候在做虚拟DOM对比的时候,根据key取出的li做对比就会出现问题。之前的索引为0的li现在为1,之前的索引为1的li现在为2,那么所有虚拟DOM将需要全部再次转换成真实DOM,复用性将不存在。

举例图解:

 说明:图解中使用index填充key,在页面点击按钮后,动态在所有<li>最前面添加一个<li>,使顺序发生变化,重新通过index填充的key将全部变化。导致出现数据位置错乱。

要是动态添加的<li>在最后面将不会出现问题。

使用自定义id作为key的值 

总结

1.在选择使最好使用数据中自定义的属性作为唯一标识。

2.如果不存在对数据的逆序添加,逆序删除等破坏顺序操作,仅用于渲染列表做展示,使用index会比较方便。

列表过滤和排序(案例)

 需求:我们创建一个输入框和一个人员列表,以及三个按钮,当我们在输入框输入包含人名的字符时,会通过模糊查询过滤剩下包含输入字符的人名信息,三个按钮分别是升序,降序和原序,点击时会实现排序功能。两种功能能实现交互使用。

页面展示

  完整代码(说明都在代码注释中):

<div id="root">
	<h2>人员列表</h2>
	搜索:<input type="text" placeholder="请输入姓名" v-model="keyWord">
		
	<ul>
		<!-- 使用filterResultArr将过滤后的结果进行列表展示 -->
		<li v-for="p in filterResultArr" :key="p.id">
			{{p.name}}--{{p.age}}
		</li>
	</ul>
	
	操作<br>
	<button @click="sortType = 1">升序排序</button>
	<button @click="sortType = 2">降序排序</button>
	<button @click="sortType = 0">原始顺序</button>
</div>
<script>
	new Vue({
		el:"#root",
		data:{
			//数据双向绑定,绑定搜索框,搜索框数据改变,计算属性重新计算
			keyWord:"",
			//排序类型:0原始排序,1升序排序,2降序排序
			sortType:0,
			persons:[
				{id:001,name:"Tom",age:18},
				{id:002,name:"Jerry",age:17},
				{id:003,name:"MaoHe",age:19}
			]
			// filterArr:[] //过滤后将数据承装的容器
		},
		computed: {
			filterResultArr() {
				//将过滤后的数组返回给计算属性filterResultArr
				//将过滤好的数组先存起来,到下方判断是否需要进行排序
				const tempArr =  this.persons.filter(p => {
					//indexof:查找name中是否包含keyword,包含返回索引,不包含返回-1.
					//当计算属性中的依赖keyWord发生改变,会重新计算属性
					//特殊:当输入框为空也就是keyWord为空时,indexOf返回的是0
					return p.name.indexOf(this.keyWord) !== -1;
				})
				//判断排序类型:1和2返回true,0返回false
				if(this.sortType){
					//进入方法体,说明是升序或降序
					tempArr.sort((p1,p2)=>{ //p1-p2是自定义变量
						//当返回p1-p2就是升序操作,返回p2-p1就是升序操作
						//根据对象中的age属性进行排序
						return this.sortType === 1? p1.age-p2.age :p2.age-p1.age;
					})
				}
				//如果没有进入if说明不需要排序,直接返回原数组即可
				//如果进入if,先将原数组排序后在返回
				return tempArr;
			}
		},
	})
</script>

vue数据监测的原理

 我们知道当vue实例中的data发生改变时,会重新解析模板,把用到该数据的地方进行更新,那么vue是怎么知道我们修改了data中的数据呢?或者说vue的监测数据的原理是什么呢?

Vue监测对象数据原理

 在data中创建了一个对象数据后,vue会给此对象中的所有属性添加数据代理,既然是数据代理,每一个对象的属性都会有get和set方法,当我们修改对象属性时,会调用set方法接收最新值对属性进行修改赋值,就是在set方法中调用一些方法使模板解析进行调用,使页面数据跟着改变。

当我们在data创建以后,也就是在页面动态的向data中添加属性时,此属性将不会是响应式的,表现为当我们修改此数据时vue将监测不到,导致页面数据无变化即使底层此数据真的已修改。为什么会这样呢?

因为我们在初始化data中没有此数据,后续向添加data中添加的属性vue并不会为其添加上get和set方法,因此当我们修改动态添加的数据时,不会经过set方法,也就不会重新解析模板了。

但是,动态添加属性的需求还是不少的,有什么方法可以让动态添加的属性跟起初就在data中声明的属性一样带有get和set方法呢?这时我们就需要了解方法Vue.set()和vm.$set()

方法Vue.set()和vm.$set()

由上说明可知,这两个方法可以使后续动态添加的属性有响应式的特性,也就是有get和set方法。

举例:如果我们需要在后续动态在data中添加一个属性,那么我们直接调用结构添加会有局限,例如data中有属性student:{name:"Tom"},我们书写动态方法追加student.age =18,我们这样添加的属性不会有响应式,当数据修改时不会取解析模板,因为如果直接追加属性是没有set和get方法的,这时我们应该调用vue中的api去添加,使用Vue.set或vm.$(set)去追加即可。这样追加的属性就和开始就在data中定义的属性别无两样了。

 

 Vue.set方法存在局限

不可直接在vm或data层级加属性,只可以在data的下一个属性层级加,例如data中有student和name属性,student的value是一个对象,student对象中有name和age属性,这时想要使用Vue.set只能在student对象中追加,不能追加在和student同级。

 Vue监测数组数据的原理

当创建数组时,vue中并不会去给数组中的所有元素去添加get和set方法,那么也就是说数组并不是根据当数据修改时调用set方法,set方法中去调用模板进行解析,跟对象监测的原理并不相同,那么数组中监测数据的原理是什么呢?

当我们调用特定方法使原数组发生变化的时候,才会触发模板重新解析。

 特定方法(官网说明):

说明:也就是说,当我们调用这样方法去操作数组时,就会触发模板的重新解析。

为什么调用push等方法会使得模板重新解析?

因为push()方法已经不是Array对象中的原始方法了,而是经过vue加工的方法,也可以说是vue在push()方法中添加了解析模板的操作。当调用push()方法改变原始数组时,也顺便把模板给解析了。

由此我们知道,当我们调用了上面官网提到的7种方法操作数组后会使模板重新解析,那么除了调用这7种方法还有什么方式可以使模板重新解析呢?这就会提到filter等方法,这类方法操作数据后都会生成一个新的数组,不会直接覆盖原数组,我们看看官网描述:

也就是说,我们可以通过filter()这类返回新数组的方法,将返回的新数组替换掉旧数组,这样也是可以触发模板的重新解析。

特殊:使用Vue.set()去变更数组中元素也可以使模板重新解析

数据劫持概念

在data变成_data的过程(给data中的属性添加get和set方法),用于监测data数据是否变化,这个过程就是数据劫持。

例如:当我们修改data中的某个属性,就会调用set方法,set方法就相当于是劫持了修改的这个动作,获取修改的值进行属性修改。

收集表单数据

vue收集<input>各种类型的的信息。例如输入框,单选框,复选框等等。

基本使用

<div id="root">
	账号<input type="text" v-model="id"><br>
	密码<input type="password" v-model="password"><br>
	性别: 男<input type="radio" name="gender" value="male" v-model="male"> 
		女<input type="radio" name="gender" value="female" v-model="female">
</div>
<script>
	new Vue({
		el:"#root",
		data:{
			id:"",
			password:"",
			gender:""
		}
	})
</script>

说明:上方代码仅演示基本输入框和单选框,其他的如多选框,下拉框等用法都是HTML的基础知识,只不过使用vue后,都需要使用指令v-model来接收值即可。

v-model.number、v-model.lazy和v.model.trim 

v-model.number

输入框为数字类型:type=”number” 一般配合v-model.number ,第一个type='number'的作用是限制用户的输入,仅可以输入number类型,而第二个v-model.number是将收集到的数据自动做转换,转换成数字类型。

v-model.lazy

作用:一般在textarea标签中使用,textarea标签一般是收集用户的反馈等信息,字符长度较长,使用lazy后就不会做数据实时收集,当焦点从textarea消失后,再进行信息收集。

v.model.trim

去掉前后空格

  用法简单举例  

<!--当用户的输入前后存在空格,前后空格将被忽略-->
账号<input type="text" v-model.trim="id"><br>

过滤器

概述:将需要显示的数据进行格式化后再显示,一般适用于简单的逻辑处理。

作用-用法 :

需求:将vue实例data中的属性timestamp(时间戳)转换成格式化后的时间再向页面中展示。

 由于需要用到时间的格式化,我们引入一个JS库来调用现成的API即可。

//此库用于处理时间和日期
//有兴趣可以了解一下,CDN地址:https://www.bootcdn.cn/dayjs/
<script src="../dayjs.min.js"></script>

页面展示 

代码 

<div id="root">
	<span>时间戳为:{{timeStamp}}</span><br/><br/>
	<!--将时间戳通过管道符"|"传入自定义过滤器进行处理-->
	<span>格式化后的时间:{{timeStamp | timeFilter}}</span>
</div>
<script>
	
	new Vue({
		el:"#root",
		data:{
			timeStamp:1675309115512
		},
		filters: {
			timeFilter(value) {
				return dayjs(this.timeStamp).format('YYYY-MM-DD HH:mm:ss');
			}
		}
	})
</script>

说明:在其中,比较陌生的应该是{{timeStamp | timeFilter}}写法,timeStamp是我们data中定义的属性,而timeFilter也是我们自定义的过滤器,而中间的"|"符号,称为管道符,将timestamp传入过滤器中,过滤器中就可以接收到此参数用于操作了。
页面会将过滤器返回值作为数据在页面展示。

全局过滤器和局部过滤器

在上面,我们举例的格式就是一个局部过滤器的写法,因为他写在vue实例中,此过滤器仅作用于vue绑定的容器范围内,在绑定的容器外将访问不到局部的过滤器,那么全局的过滤器如何定义呢?

 在配置项中(局部过滤器),一次可以书写多个过滤器,而使用Vue.filter则一次只能绑定注册一个过滤器。

过滤器接收参数说明:过滤器始终能收到管道符左边的变量,并且将之放在过滤器方法参数的第一位,要是在管道符右边在添加其他参数,那么也是可以接收到的(从第二个参数开始)。

多重过滤器

<span>格式化后的时间:{{timeStamp | timeFilter1 | timeFilter2}}</span>

 特点:将前一个过滤器的返回值交给后一个过滤器作为参数。

自定义指令及内置常用指令

指令:v-text

作用:向其所在的节点中添加文本内容,如果节点内已有内容,会将原内容替换掉。

用法:在标签属性中添加v-text="属性值 "指令。

特点:不支持标签解析:类似当属性值中存在<h1></h1>时,直接显示。

指令:v-html

作用:向指定节点中渲染包含html结构的内容。

用法:与v-text一致

特点:会替换节点原内容,可以解析标签。

值得注意:v-html有安全问题,容易导致XSS攻击(用户恶意使用<>标签提交从而获取非法数据)
所以要避免在可输入节点属性中添加v-html。

 指令:v-cloak

 作用:可以将未经解析的模板进行隐藏,当vue介入后会将v-cloak属性删除,将解析后的模板节点显示。

注意:使用时需要配合上样式的设置(实现原理过程)。

 

在h2标签中添加v-cloak指令,当模板未被vue解析时,该h2节点将不被显示,怎样做到的呢?看如下样式设置: 

 

此样式设置在<style>中,代表为DOM结构中属性带有v-cloak的节点,显示为隐藏,当vue解析完模板后,会将模板中所有节点的v-cloak属性给移除,那么样式也就失效了。

指令:v-once

作用:使节点只做一次动态渲染。
描述:在加了v-once指令的节点上,例如存在{{n}},那么当初次模板解析时,会将n附上值(动态渲染)显示在页面,当n发生改变的时,只要加了指令v-once,那么在{{n}}将不会二次改变,依然显示第一次动态渲染的值。

指令:v-pre

作用:跳过该节点编译过程,加快整体编译速度。

 描述:当我们明确某一个节点不需要vue动态渲染时(没有指令语法和插值语法),也就是vue直接用不需要进行编译,我们就可以在此节点上添加v-pre指令,当vue解析到该节点时,将跳过该节点的编译,使整体的编译熟读加快。

自定义指令

 对象式 

<div id="root">
	<div v-mydirec="n">{{n}}</div>
</div>
<script>
	new Vue({
		el:"#root",
		data:{
			n:1
		},
		//关键字directives(指令),在其内部定义自定义指令
		directives:{
			mydirec:{
				//节点和指令绑定时调用
				bind(element,binding){
					console.log("节点和指令绑定成功!");
				},
				//指令所在元素被插入页面时调用
				inserted(element,binding){
					console.log("数据展示成功!");
				},
				//指令所在模板被重新解析时调用
				update(element,binding){
					console.log("数据更新成功!");
				}
				
			}
		}
	})
</script>

参数说明

第一个参数element接收的是指令绑定的节点,我们可以使用此参数操作节点,例如element.innerHTML去修改节点的内容等等。
第二个参数binding接收的是绑定指令时的一些数据,例如指令的名字,指令的值等等。

参数输出演示

所用代码段 如下

 输出:

测试

当页面加载好后,控制台输出:

当我们通过n值时,控制台输出:

 函数式 

directive:{
	direc(element,binding){
		console.log("指令被调用!");
	}
}

函数调用时机:当函数被绑定成功时,和模板被重新解析时调用。

说明:如上的定义方式都是局部的定义方式,想要定义全局的自定义指令,跟设置全局过滤器一样,需要使用内置Vue对象进行设置。例如:

//在vue实例之外定义(全局自定义指令)

//======对象式======//
Vue.directive("自定义指令名",{
	//节点和指令绑定时调用
	bind(element,binding){
		console.log("节点和指令绑定成功!");
		console.log(element,"====",binding);
	},
	//指令所在元素被插入页面时调用
	inserted(element,binding){
		console.log("数据展示成功!");
	},
	//指令所在模板被重新解析时调用
	update(element,binding){
		console.log("数据更新成功!");
	}
})

//======函数式======//
Vue.directive("自定义指令名",function(element,binding){
	//指令处理体
})

命名注意点

当指令名为多个单词构成时,在自定义指令名时不能使用驼峰命名法,因为当vue解析节点上的指令时,会自动的将所有大写转换成小写字母,所以可能会导致指令匹配不上的情况。

 推荐使用:当指令名由多个单词构成时,我们应该使用烤肉串的格式进行编写,例如a-b-c,那么在编写的时候就应该加上引号:"a-b-c"即可。

 编写演示: 

 Vue生命周期

概述:vue生命周期描述的是vue的从创建到销毁的执行过程。
在vue生命周期的某些时刻会调用某些特定的方法,这使得我们可以控制vue在某些时刻做一些事情。

官网描述:

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。


执行流程:vue的整体执行流程大致可以分为挂载,更新和销毁。
执行到这些流程中会调用特定的函数,我们称这些函数为:生命周期函数或钩子函数

在下方的流程介绍中,会截取官网流程图进行解析说明。

挂载流程

 此图包含两个钩子函数,beforeCreate()和created(),两者之间是初始化数据代理和数据监测操作,也就是解析到了vue实例中的属性和方法这些。

beforeCreate:初始化生命周期和事件,没有数据监视和数据代理及方法。

created:生命周期函数前后:是数据监测和数据代理的创建。

如图,是判断我们vue实例中是否写有el选项,如果有就会接着判断是否有template选项,如果没有el选项那么就会找是否有全局定义的Vue.$mount(el),总之就是想要找到DOM容器。因为接下来将要去向容器中解析模板了。

 

如图,此判断是vue实例中是否有template选项,有的话就使用template中的内容作为容器,替换掉el所绑定的容器,如果没有template选项,那么就会直接使用el中所绑定的容器,此容器包含根节点。

 此图仅看左边即可,在钩子函数beforeMount(在挂载之前),在此生命周期,并没有将虚拟DOM转为真实DOM。当执行到钩子函数created()挂载流程完毕。

更新流程

 当数据修改的时候,就会触发更新流程,首先执行钩子函数beforeUpdate(),在此时内部数据虽然已经更新,但是页面上的数据依然是旧的数据,经过DOM的对比算法对比后,进行页面的渲染成功后,就会调用钩子函数updated()。

销毁流程

 

 当我们手动调用销毁方法vm.$destroy()时触发销毁流程。先触发的是钩子函数beforeDestroy(),这时如果我们修改数据,也不再会触发更新流程,一般在此钩子函数中做一些收尾工作。接着执行钩子函数destroyed(),值得注意的是:销毁自定义事件会失效,但是已经绑定过的原生DOM事件依然有效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mao.O

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值