Vue核心
Vue简介
Vue是什么
一套用于构建用户界面
的渐进式
JavaScript框架。
-
构建用户界面
把拿到的数据渲染成用户看见的界面。(不考虑是死数据、模拟数据、还是后端发送的数据)
-
渐进式:
- 开发简单应用,只需要一个轻量小巧的核心库
- 开发复杂应用,可以引入各式各样的Vue插件
谁开发
Vue的特点
-
采用
组件化
模式,提高代码复用率、且让代码更好维护。-
一个
.vue
就是一个组件 -
.vue
文件里面的内容可以写html、css、JavaScript
-
-
声明式
编码,让编码人员无需直接操作DOM,提高开发效率。命令式编码
:只能按照指令走,不给命令就不走。声明式编码
:
-
使用
虚拟DOM
+优秀的Diff
算法,尽量复用DOM节点。-
虚拟DOM内存中的数据;
- DIFF:增加了新数据后,新的虚拟DOM会和原来的虚拟DOM进行比对DIFF,不变的虚拟DOM的HTML页面中的内容直接复用。
- 流程:将原始数据→虚拟DOM→页面真实DOM
-
学习Vue之前掌握的JavaScript的基础知识
ES6语法规范、ES6模块化、包管理器、原型和原型链、数组常用方法、axios、promise
总结
- Vue的特点?
- 组件化模式
- 声明式编码
- 虚拟DOM+DIFF技术
Vue官网指南
-
教程:简单的Vue入门教程
-
API:字典
-
风格指南:在学习回了Vue后,再去看
-
CookBook:JS和Vue的一些技巧,用于进阶
-
团队下的Awesome:
github地址,官方整理的好用的第三方库。果想借助第三方库生成报表,可以点击charts,点击进去有很多好用的包。
-
官方文档中:
搭建Vue开发环境
https://v2.cn.vuejs.org/v2/guide/installation.html#%E7%9B%B4%E6%8E%A5%E7%94%A8-lt-script-gt-%E5%BC%95%E5%85%A5
- 安装Vue开发者工具:去谷歌应用商店安装
- 可能遇到的问题:
- 现在学的是vue2,最新的是vue3;开发者版本工具需要和Vue的版本对应
- 建议去网盘下载,下载好文件拖拽的拓展程序界面
- 下载后需要开启
允许访问文件网址
按钮
- 可能遇到的问题:
-
安装vue的两种方式:
-
scirpt标签引入
新手建议这么做
-
npm (一般都会结合命令行工具)
-
总结
开发环境搭建流程:
- 下载开发版本Vue
- 安装Vue开发者工具
- 设置Vue config,关闭提示
初识Vue
hello案例
live server 运行html文件,会在本地创建一个小服务器,端口是5050.
运行后,会自动发送一个浏览器图标的请求。
将数据存在Vue实例中不写死的好处:当数据发生变化,不需要操作DOM,DOM的内容会自动改变。
把数据交给绿色的框框。
总结
- 想让Vue工作,就必须创建Vue示例,且要传入一个配置对象。
- 容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法。
- 容器里的代码被称为【Vue模板】。
- Vue实例和容器是一一对应的。
- 真实开发中只有一个Vue实例,并且会配合几个组件一起使用。
- ``中的
xxx
需要写js表达式
,且xxx可以自动提取到data中的所有属性。 - 一旦data中的数据发生改变,那么模板中的
用到该数据地方就会自动更新
。
容器和实例的对应关系
只能一对一,一对多多对一均不行。
容器有很多数据,那实例数据需要自己就需要写100个吗?
容器``里包裹的是JS表达式
注意区分JS表达式和JS代码(语句):
-
表达式:一个表达式会生成一个值,可以放在任何一个需要值的地方,
可以复制
。a a+b demo(1) // 哪怕是undefined也可以赋值 x === y ? 'a':'b'
-
js代码(语句):不能用来赋值
JS表达式是特殊的JS代码,不能用来赋值,即不能写在赋值运算符右边
判断this指针是否指向实例对象的方法
this instanceof 构造函数
模板语法
Vue容器中的代码被称为【Vue模板】,那么就有对应的Vue模板语法
模板语法分两类:插值语法和指令语法
插值语法
-
功能:用于解析
标签体,即开始标签<>、结束标签</>之间
的内容 -
语法:``,
xxx
是js表达式,且可以直接读取到data中的所有属性
指令语法V-???
-
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件...)
-
举例:
v-bind单项数据绑定
` v-bind:href=’xxx’
、
:href=’xxx’`,xxx来自实例中data的属性,xxx要写成js表达式形式。将表达式的结果赋值给前面的属性。
-
备注:
Vue中有很多指令
,且形式都是v-???
,此处知识用v-bind
举例
举例
<!-- 标签内的内容依然需要符合html语法:url依然需要添加双引号-->
<a v-bind:href="url" >点我前往尚硅谷</a>
<script>
new Vue({
el:'#root',
data:{
url:'http://www.atguigu.com'
}
})
</script>
数据绑定
单项数据绑定
-
特点
- 开发者工具处修改数据,浏览器显示的内容会自动改变;
- 但是从浏览器修改数据,
Vue
中相应的变量不会发生变化.
即数据只能从
data
流向页面. -
语法
-
全写
v-bind:href='xxx'
-
简写
:href='xxx'
注意:将
xxx
的值与href
属性绑定,等号右侧必须有双引号.执行时:会将引号里面的内容当做
JS
表达式执行.
-
双向数据绑定
-
]特点:
-
开发者工具处修改数据,浏览器显示的内容会自动改变;
-
从浏览器修改数据,
Vue
中响应的变量也会发生变化.
即数据可以从
data
流向页面,还能从页面流向data
. -
-
语法
- 全写
v-model:value='xxx'
- 简写
v-model='xxx'
- 全写
-
注意
- 修改双向绑定数据,依赖于该数据的其他内容也会发生改变。
v-model
只能用于有value
值表单元素,输入类必有;非表单元素一律不可用
总结
Vue中有2中数据的绑定方式:数据绑定是写在容器中的,实例可能需要提供数据值.
-
单项绑定
v-bind
:数据只能从data
流向页面
-
双向绑定
v-model
:数据不仅能从data
流向页面
,还可以从页面
流向data
-
备注:
-
双向绑定一般用在表单元素上
(如input、select)
因为有value属性才能捕获到用户的输入,进而影响数据的变化
-
v-model:value
可以简写为v-model
,因为v-model
默认收集的就是value
值,不收集别的。 -
注意区分不同的简写方式:
v-bind
简写方式:
v-model:value
简写方式v-model
-
双向绑定一般用在表单元素上
el与data语法
vm的属性
-
Vue实例中带有
$
符号的属性给程序员使用-
挂在到实例对象上的
$
属性 -
挂载到实例构造者的原型对象
prototype
上的$
属性,实例通过__proto__
指向这些方法。
-
-
不带
$
符是Vue自己使用的.
el绑定容器
-
创建实例时
.new Vue()
创建实例时的配置参数el:‘css选择器’
el: "#root"
-
创建完实例
使用实例对象
v
调用静态方法:v.$mount('css选择器')
指定el
的值。v.$mount('#root')
第二种写法更灵活,声明容器后可以写在之后的任何地方。
data数据
-
对象式
data:{ name:'尚硅谷' }
-
函数式
data: function () { // this的调用者:指向实例对象 // 前提:data函数不能写成箭头函数,因为箭头函数没有this console.log('aaa', this); return { name: '尚硅谷' } } // 简写方法:去掉冒号和function data(){ return { name: '尚硅谷' } }
如何选择
目前使用哪种都可以,以后学习组件时,data必须用函数式,否则会报错。
重要原则
由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,
this就不再指向Vue实例
MVVM
-
MVVM是一种软件架构模型。
对应在Web前端开发中各个部分的含义是
-
M、模型Model:对应data中的数据
-
V、视图View:模板
-
VM、视图模型ViewModel:Vue实例对象
简单理解:MVVM模型就是把一堆东西分成三类,Vue是中间建立连接的桥梁。
-
因此,以后都将Vue实例对象命名为vm
总结
- MVVM模型
- M模型:data中的数据
- V视图:模板代码
- VM视图模型:Vue示例对象
- 观察发现
- data中的所有属性,最后都出现在vm身上
- vm身上的所有属性及Vue原型上的所有属性,在Vue模板中都可以直接使用
数据代理
Object.defineProperty方法
注意
通过defineProperty添加的属性默认不能遍历(枚举)
如果想遍历该属性,需要设置配置对象:
https://www.bilibili.com/video/BV1Zy4y1K7SH/?p=11&spm_id_from=pageDriver&vd_source=dde2f4dd432156027fedf9b1734ba705 重新看
数据代理
数据代理定义
-
定义:通过一个对象代理对另一个对象中属性的操作
(读/写)
Vue中数据代理
https://www.bilibili.com/video/BV1Zy4y1K7SH/?p=13&spm_id_from=pageDriver&vd_source=dde2f4dd432156027fedf9b1734ba705
注意: vm._data = data
-
Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
-
Vue中数据代理的好处:
更加方便的操作data中的数据
-
Vue数据代理基本原理:
- 通过Object.defineProperty()把data对象中所有属性添加到vm上
- 为每一个添加到vm上的属性,都指定一个getter/setter
- 在getter/setter内部去操作(读/写)data中对应的属性
事件处理
事件基本使用
https://www.bilibili.com/video/BV1Zy4y1K7SH/?p=14&spm_id_from=pageDriver&vd_source=dde2f4dd432156027fedf9b1734ba705
代码没写
事件的基本使用:
- 使用
v-on=xxx
或@xxx
绑定事件,其中xxx
是事件名。 - 事件的回调需要配置的
methods
函数中,最终会在vm上。 methods
中配置的函数,不要用箭头函数!否则this的指向就不是vm了。methods
中配置的函数,都是被Vue所管理的函数,this的指向都是vm或组件实例对象。
@click=’demo‘
和@click="demo($event)"
效果一致,但后者可以传参。
事件修饰符
Vue中的事件修饰符:
- 语法:
@事件.修饰符=‘回调函数’
-
prevent
:阻止默认事件,如点击a标签跳转 -
stop
:阻止事件冒泡 -
once
:事件只触发一次 -
capture
:使用事件捕获方式,即在事件捕获阶段触发事件,默认是在事件冒泡阶段触发。 -
`e.target`是不会随着冒泡改变的,只会是用户点击操作的那个元素。self
:只有event.target
是当前操作的元素时才触发事件使用:从某种程度来说也能阻止冒泡,但是用的不多。
-
passive
:事件的默认行为立即执行,无需等待事件回调操作。滚动事件补充:
-
scroll滚动事件:
滚动条滚动
,键盘上下按钮和鼠标滚轮滚动都算; -
wheel滚动事件:
鼠标滚轮滚动事件
,只要鼠标轮在动,就会触发;键盘上下操作滚动条不触发。- 当使用wheel事件时,首先执行回调函数,回调函数结束后,才执行默认事件:滚动条向下滑动
- 不是所有事件都存在这个问题,scoll就没有这个问题。所以也不会很常用。
事件默认行为与事件回调之间的执行关系
默认情况下:事件回调函数执行完,事件默认行为才会发生
- 适用场景:passive在移动端用的场景比较多。
-
键盘事件
-
键盘事件语法
-
keyup抬起键盘
-
keydown按下键盘
-
语法
@键盘事件=回调函数
,不区分按键@键盘事件.指定按键名/vue提供的别名=回调函数
,区分按键
// 当抬起回车键时,执行showInfo @keyup.enter="showInfo"
-
-
Vue中常见的按键别名
// Vue提供的别名,可以代替键盘原本的名字 回车:Enter 删除:delete(捕获"删除"和"退格") 退出:esc 空格:space 换行:tab //特殊:tab必须配合keydown使用;因为tab是切换走,如果keyup抬起来的时候已经离开了元素,检测不到。 上:up 下:down 左:left 右:rigjt
-
Vue中未提供的别名的按键,可以使用按键原始的Key值来绑定,但注意要转换为短横线命令
e.key // key获得键盘名 // 小驼峰的key,转换为短横线命名: @keydown.caps-lock=回调函数 //把按键字母小写,用-连接
-
用法特殊的键:系统修饰键
ctrl/alt/shift/meta
- 配合
keydown
使用:正常触发事件。 - 配合
keyup
使用:单按没用。按下修饰键的同时,再按下其他键,随后释放其他键,事件被触发。
- 配合
计算属性与监视属性
计算属性computed
-
场景
使用已有的属性,去加工、计算得到一个全新的属性。
-
在实例中定义
在名为
computed
的对象中定义计算属性 -
在容器中使用
在容器中使用``显示计算结果
-
初学者易犯错误
计算属性里面的函数,不需要调用方法里面的.get()方法。直接写get方法上的属性名字即可。
底层:
computed
里的属性,自动去找到get拿到get的返回值放在vm上,名字就是get所在的函数的名称。set不是必须写,如果你确定计算属性不会被修改可以不用写set
如果需要修改这个值,那么需要设置,不然修改回报错。如使用vm.属性命名=‘’的方法赋值修改就会报错。
函数是否写括号?
- 事件回调写函数,函数可以写不写小括号都代表调用函数.
- 插值语法写函数,
- 写小括号代表调用函数,结果是返回值;
- 不写小括号代表函数自身。
只要data中的数据发生改变,就一定会重新解析模板,模板各个方法重新调用一遍。
总结
-
定义:要用的属性不存在,要通过已有属性计算得来。
-
原理:底层借助了
Object.defineProperty
方法提供的getter和setter
。 -
计算属性中get函数什么时候执行?
-
初次读取时会执行一次;
如果后面还有且依赖数据没变化,会走缓存,不再重新调用。
-
当依赖的数据发生改变时会再次调用
<!-- fullName也在vm身上,直接使用插值语法获得 --> 全名:<span></span> <br /> 全名:<span></span> <br /> 全名:<span></span> <br /> 全名:<span></span> <br /> <!-- 以上有四个fullName,但是只调用了一次fullname -->
-
-
优势:
-
与
methods
相比,内部有缓存机制,实现复用,效率更高。methods方法没有缓存,写了几个就要调用几次
-
计算过程可见,调试方便。
-
-
备注:
-
计算属性最终会挂在在vm上,
直接写计算属性名字即可
。原因:底层会自动调用get,把get方法返回值返回给对应的计算属性
-
如果计算属性要被修改,那必须写set函数去响应修改;
且set要把接收到新值 反应到 所依赖的数据上!
-
监视属性watch
基础知识
监视属性watch
-
执行时机:当监视属性发生变化时,回调函数自动调用,执行相关操作
-
监视属性必须存在才能监视!!!不报错,但是不存在的属性新旧值都是
undefined
-
可监视的属性:
data中属性
和计算属性
都可以 -
监视属性的两种写法:
-
new Vue时传入watch配置
watch: { info: { // 初始化时让handler就调用一次 immediate: true, // 当info发生改变时,handler自动调用 // 第一个参数新值,第二个参数之前的值 handler(newValue, oldValue) { console.log('info被改变了', newValue, oldValue) } } }
-
通过
vm.$watch('属性名',{回调函数})
```js vm.$watch(‘isHot’, { // 回调函数的简写形式 handler(newValue, oldValue) { console.log(‘ishot被改变了’, newValue, oldValue) } })
-
配置项immediate: true
,初始化时执行一次。
深度监视
深度监视,配置项deep:ture
- Vue中的
watch
默认不监视对象内部值的改变(只监视一层) - 配置
deep:true
可以检测对象内部值的改变(监视多层)
备注
-
Vue自身可以检测对象内部值(多层)的改变,但Vue提供的Watch默认不监视;为了提高效率
-
使用watch监视数据时,可以根据数据的具体结构,决定是否采取深度监视
代码举例
const vm = new Vue({
el: "#root",
data: {
isHot: true,
numbers: {
a: 1,
b: 2,
}
},
// 监视
watch: {
// 监视多级对象结构中某个属性的变化
'numbers.a': {
handler() {
console.log('a改变了');
},
},
// 监视多级结构中所有属性的变化
numbers: {
deep: true,
handler() {
console.log('numbers里面的有东西改变了');
}
},
}
})
注意:
- 如果要监视多级对象中,某个属性的变化。需要写完整对象属性名、并且在外面用引号包裹
- 监视多级对象中的所有属性,使用
deep:ture
配置项即可。
监视简写
前提:没有配置项immediate: true
、deep:ture
时,监视属性可以简写。
1.在watch
属性中的简写
简写方法:函数名是监视的属性,(){}
里面按照原来的写法写
// 监视
watch: {
// 正常写法
isHot: {
handler(newValue, oldValue) {
console.log('isHot被改变了', newValue, oldValue)
}
},
// 简写形式
// 函数名:监视的是谁
isHot(newValue, oldValue) {
console.log('简写形式isHot被改变了', newValue, oldValue)
}
}
2.在Vue实例化后的简写vm.$watch()
简写方法:第二个参数写成匿名函数,(){}
里面内容按原来的方法写
// 正常写法
vm.$watch('isHot', {
handler(newValue, oldValue) {
console.log('ishot被改变了', newValue, oldValue)
}
})
// 简写
vm.$watch('isHot', function (newValue, oldValue) {
console.log('实例化方式ishot被改变了', newValue, oldValue)
})
区分计算属性和监视
有些需求计算属性和监视属性都能做,如根据姓和名拼出全名的案例。
-
当计算属性和监视属性都可以做的时候,优先选择计算属性
-
监视属性
watch
可以做到计算属性做不到的事,例如延迟几秒返回数据computed
计算属性不支持异步,需要return获得返回值,
// 计算属性fullName拿不到这个返回值,这个返回值给了setTimeout fullName(){ // 为什么用箭头函数?this代表的是Vue // 如果这里使用普通函数,那么this指向的是Window setTimeout(()=>{ return this.firstName + '-' + this.lastName },1000) }
watch
支持异步而且不依赖return
总结
computed
和watch
之间的区别:computed
能完成的功能,watch
都可以完成watch
能完成的功能,computed
不一定能完成。例如:watch
可以进行异步操作。
-
两个重要的小原则:
- **被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象**
-
**所有不被Vue所管理的函数,如定时器的回调函数、AJAX的回调函数、Promise的回调函数等,最好写成箭头函数**。
这样this的指向才是vm或者组件实例对象。
Vue绑定class与style
细节:
vue模板中,元素标签内的属性前添加了vue指令,如冒号:
,那么等号后面引号里面的内容就是JS表达式。引号的里面要用JS表达式去分析,是字符串还是变量
下面的两种写法就是完全不同的意义:
// []里面的东西被写死了,vue不会帮我们保存
<div class="basic" :class="['atguigu1','atguigu2','atguigu3']"></div> <br />
// []里面的东西是变量,会去data里面寻找变量对应的值
<div class="basic" :class="[atguigu1,atguigu2,atguigu3]"></div> <br />
条件渲染
template
结合v-if
列表渲染
遍历列表
key原理
key的原理
虚拟DOM的对比算法:对比的是虚拟DOM,不是换整个虚拟DOM,每个key下的虚拟DOM有哪部分没变,就可以继续复用,针对的单元很小,只要有不变就复用,
VUE的操作流程:初始数据 =>虚拟DOM =>真实DOM
用户接触到的是真实DOM
使用index作为key:如果对数据进行了破坏顺序的操作,如在最前面插入新数据(最后面插入新数据不会影响旧的数据),那么就会出问题。
新的数据会影响之前存在的数据的key,
不写key,那么vue会把遍历的索引值自动作为数据的key
。所以也可能出问题。
从后台请求过来的数据 不可能没有数据的唯一标识,不然后端不合格。
列表过滤
使用场景:筛选
p.name.indexOf(“”) //返回0
所有字符串都包含空字符串
监视属性可以直接使用参数获得用户输入的新值和旧值
计算属性需要使用data的数据属性中获得用户输入的新值
监视属性:默认当监视属性的值发生变化的时候执行,可手动设置刚开始就执行一次
计算属性handler调用时机:一开始的时候自动调用一次,当依赖的属性值发生变化的时候再执行
总结:监视属性和计算属性都能做,优先选择计算属性。
列表排序
升序和降序都是自上而下的:从上面到下面
数组方法
filter
sort 返回值,改不改变原数组,必须马上反应过来
https://www.bilibili.com/video/BV1Zy4y1K7SH?p=33&spm_id_from=pageDriver&vd_source=dde2f4dd432156027fedf9b1734ba705
Vue检测数据发生变化
检测对象改变
数据代理:
源代码中vue实例中的data属性,挂载在vm的_data上vm._data=data
,将_data
中的一级属性挂载在vm上
在进行vm._data=data
之前,底层还做一步操作:加工data。加工一下就可以做响应式了,getter和setter。
https://www.bilibili.com/video/BV1Zy4y1K7SH?p=34&spm_id_from=pageDriver&vd_source=dde2f4dd432156027fedf9b1734ba705 重看,没看懂 35-37都没看
检测数组发生改变
收集表单数据
<form action="">
<label for='demo'>账号:</label>
<input type="text" id="demo">
</form>
label for 作用:点击账号文字,用户也可以获得后面表单控件的焦点
禁止表单的自动提交:(自动提交会刷新页面,表单内容会消失)
1.button默认是submit类型,改成button类型,就不会提交了
<button type="button">提交</button>
2.阻止form的默认事件,给button添加不要给整个form添加否则会有意想不到的影响
<button type="submit" @click.prevent >提交</button>
过滤器
计算属性也能做,methods也能做,所以这个不是强制的。
BootCDN https://www.bootcdn.cn/ 这个网站里面有一些好用的JS库
过滤器就是一个函数
在模板中 传入的数据实参 | 过滤器函数名 |
<!-- 过滤器实现 -->
<!-- 底层:过滤器函数可以额外传入其他配置参数,但是在Vue实例中,第一个形参是过滤器函数左边的值;后面的参数才是传入的其他实参值 -->
<!-- 多个过滤器之间可以串联 -->
<h3 >现在是:</h3>
在Vue实例中,使用fileters属性,配置下面的函数
filters:{
// value:传入的参数值
timeFormater(value){
// 代码块,返回值会渲染到插值语法中
}
}
time实参传递的方式,先传给第一个过滤器函数,再将第二个过滤器的返回值传给下一次
谁可以使用Vue中的过滤器,只有这个Vue实例绑定的容器,才可以使用该实例中的过滤器。
全局作用器,配置了可以给任何一个容器使用
Vue.filter
Vue.filter('过滤器函数名',function(value){
return 返回值 // 返回值会被渲染到模板代码中
})
过滤器可以用在插值语法中和V-bind中,v-model不行
也可以用在下面的方法中
总结
复杂的应该用计算属性或methods
Vue指令
常用内置指令
常用指令如下:
-
更新标签中的元素内容
-
v-text
不解析html标签 -
v-html
解析html标签
-
-
条件渲染
只有符合条件时,标签才会渲染到页面
-
v-if
、v-else
动态控制节点是否存在 -
v-show
动态控制节点是否显示
-
-
编译数组/对象
可以遍历后生成指定个数的标签
v-for
-
绑定事件监听,一般简写为
@
v-on
-
数据绑定
-
v-bind
单向数据绑定 -
v-model
双向数据绑定
-
-
其他
v-cloak
防止闪现,与css配合[v-cloak]{dispaly:none}
v-text
v-text使用拿到的属性值,替换元素标签里的全部内容,不解析html标签,全部当做文字
插值语法也不会解析
<div id="root">
<div></div>
<div v-text="name"></div>
</div>
v-html
和v-text的区别是会解析html标签,可能会有安全问题
XSS攻击
v-cloak指令
这个指令没有值,只有名。
当Vue未开始渲染时,模板代码中的元素会有v-cloak属性,当Vue开始渲染时,v-cloak属性消失。
作用:和CSS结合,让未渲染的模板代码不显示。
不显示含有v-cloak的元素标签
[v-cloak]{
dispaly:none
}
https://www.bilibili.com/video/BV1Zy4y1K7SH/?p=42&spm_id_from=pageDriver&vd_source=dde2f4dd432156027fedf9b1734ba705
v-once指令
v-once
作用:
<!-- 准备好一个容器 -->
<div id="root">
<h2 v-once>初始化的n值是:</h2>
<h2>当前的n值是:</h2>
<button @click="n++">点我n++</button>
</div>
<!-- Vue实例 -->
<script>
new Vue({
el: "#root",
data: {
n: 1,
}
});
</script>
v-pre
v-pre可以给没有使用插值语法、指令语法的节点,可以加快速度。
注意和once区分
Vue中事件 使用@
自定义指令
用自定义指定的简写方式:其实就是指定了bind和update,没有指定inserted
// 写自定义指令
directives: {
// big函数什么时候被调用?1.指令与元素成功绑定时(一上来就执行)2.指令所在的模板被重新解析时。
// 第一个参数:真实dom元素
// 第二个参数:对象,里面有很多属性;元素和指令之间的绑定关系
// 使用JS语法简写
big(elemnet, binding) {
// console.log(elemnet, binding);
elemnet.innerText = binding.value * 10
},
// fbind不能写成函数,需要用最完整的对象写法
fbind: {
// 指令与元素成功绑定时(一上来)
bind() {
},
// 指令所在元素被插入页面时
inserted(element, binding) {
element.focus()
element.value = binding.value
},
// 指令所在模板被重新解析时
update(element, binding) {
element.focus()
element.value = binding.value
},
}
}
注意事项
- 命名:不适用小驼峰,而是用-连接多个单词,要求全部小写
- 在Vue实例中,对函数名要用引号包裹
- this指向
-
配置全局自定义指令
Vue.directive.({自定义指令名v-后面的东东,{ bind(elemnet, binding){ // 代码块 }, inserted(elemnet, binding){ // 代码块 }, updated(elemnet, binding){ // 代码块 } })
生命周期
基础知识
<div id="root">
<h2 :style="{opacity}">欢迎学习Vue</h2>
// 会被重新解析无数次,change重新调用无数次
</div>
new Vue({
el: "#root",
data: {
opacity: 1,
},
methods: {
change() {
setInterval(() => {
this.opacity -= 0.01
if (this.opacity <= 0) {
this.opacity = 1
}
}, 16)
}
},
});
上面的是垃圾代码,模板会无数次解析,change会无数次调用,开启了无数个计时器
原因:每次data中的数据opacity
发生变化都会重新解析模板
重要思想
每次data中的数据发生改变,
Vue
就会重新解析模板
JS表达式代码 对象简写形式。
如果对象值和属性相同,那么可以只写属性,不写值。
别人访问这个属性名就会返回这个属性的值。
细节,1.定时器中用箭头函数 2.小数的判断条件 小于等于0而不是 等于0因为有可能错过=0这个点
变化的东西交给JS处理。
<script>
const vm = new Vue({
el: "#root",
data: {
opacity: 1,
},
methods: {
change() {
// 箭头函数没有自己的this,所以这里的this是change函数的this就是Vue
setInterval(() => {
this.opacity -= 0.01
// 写<=0是因为JS处理小数不灵活。可能没等于0,直接就跳到比0小的地方了
if (this.$listeners.opacity <= 0) {
this.opacity = 1
}
}, 16)
}
}
});
</script>
undefined不显示在页面上
Vue模板工作流程:代码解析为虚拟DOM,虚拟DOM转换成真实DOM,把真实DOM放在模板上。
// 什么时候调用?
// Vue完成模板解析 并把真实的DOM元素放入页面后(挂在元素)调用mounted
// 只调用一次,他是一个
mounted() {
setInterval(() => {
this.opacity -= 0.01
if (this.opacity <= 0) {
this.opacity = 1
}
}, 16)
}
总结
生命周期(其实是一个简称)
- 又名:生命周期回调函数、生命周期函数、生命周期钩子(程序员交流常用)
- 本质:函数,Vue在关键时刻帮程序员调用的一些特殊名称的函数。
- 生命周期函数的名字不可更改,但函数体的内容可以根据程序员需求编写的。
- 生命周期函数中的this指向的是vm或组件实例对象。
分析生命周期
红色方框里面的内容是生命周期;蓝色阴影的部分是Vue
实例化的环节.
挂载流程
-
beforeMount
-
可以对真实DOM进行操作修改内容
-
但是会被后面的Vue虚拟DOM生成的真实DOM覆盖,只会短暂存在,最终不生效.
-
-
mounted
-
调用时机:
完成模板解析,并把初始的真实
DOM
放在页面中(即挂载完毕),调用mounted
.即第一次把
真实DOM
放在页面;以后的操作其实是更新,不会再执行. -
注意 这一时期操作DOM有效,但是应该避免程序员自己手动操作DOM
-
-
vue
初始化时template
注意事项template
中的代码必须全部包裹在一个标签中,常用<div>
包裹- 在
html
的body
中写模板、template
中写模板的区别html
的body
中写模板写的是什么就是什么template
中的内容会完全替换html
中的容器,即html中原本的获得`el`的那一层会被代替消失
截止到mounted
就是挂载流程.
挂载流程时不涉及新旧虚拟DOM的比较,因为都是最新的,没有改变;在更细的时候才有虚拟DOM比较.
更新流程
只要data
数据改变就会更新
-
beforeUpdate
-
数据是新的,但是页面还没更新
-
在此生命周期中,页面和数据未保持同步
-
-
updated
- 数据是新的,页面也是新的
- 在此生命周期中,页面和数据保持同步
销毁流程
先调用vm.$destroy()
方法,才会走销毁流程;调用该方法后,vm就会自我销毁.
-
vm.$destroy()
-
完全销毁一个实例,清理它与其它实例的连接,解绑它的全部指令以及事件监听器(自定义事件).
-
触发
beforeDestroy
和destroyed
的钩子. -
注意:销毁
vm
后,vm
之前的工作渲染的页面还在.
-
-
beforeDestroy
-
此时
vm
中的data
,methods
,指令都处于可用状态,此处使用方法改变数据,此阶段数据改变**不会触发更新**,因此不会渲染到页面上
-
一般进行收尾操作
-
-
destroyed
- 移除监视、所有子组件、(自定义)事件监听器
生命周期小结
-
共讲了4对8个生命周期函数.
-
beforeCreate
、created
指的是数据代理和数据检测创建之前/创建完毕 -
挂载之前/挂载完毕
-
更新之前/更新完毕
-
销毁之前/销毁完毕
-
-
常用的生命周期钩子:
-
mounted
:发送ajax
请求,启动定时器,绑定自定义事件,订阅消息等初始化操作 -
beforeDestroy
:清除定时器、解绑自定义事件、取消订阅等收尾工作
-
- 关于销毁Vue实例
- 销毁后借助
vue
开发者工具看不到任何消息 - 销毁后自定义时间会失效,但原生DOM事件依然有效
- 一般不会在
beforeDestroy
操作数据,因为即便操作数据,也不会再出发更新流程了
- 销毁后借助
-
细节
-
需求 不同配置项之间共享一个变量
-
方法 将变量定义在
this.xxx
上
也可以通过全局变量,但是不推荐
-