文章目录
vue 实例的生命周期
- 什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!
- 生命周期钩子:就是生命周期事件的别名而已;
- 生命周期钩子 = 生命周期函数 = 生命周期事件
- 主要的生命周期函数分类:
- 创建期间的生命周期函数:
- beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
- created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
- beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
- mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
- 运行期间的生命周期函数:
- beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的
数据还是旧的,因为此时还没有开始重新渲染DOM节点 - updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
- beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的
- 销毁期间的生命周期函数:
- beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
- destroyed:Vue 实例销毁后调用。调用后,Vue
实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
- 创建期间的生命周期函数:
生命周期函数演示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="button" value="修改msg" @click="msg='No'">
<h3 id="h3">{{ msg }}</h3>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'ok'
},
methods: {
show() {
console.log('执行了show方法')
}
},
beforeCreate() {//这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它
// console.log(this.msg);
// this.show()
// 注意:在beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化
},
created() {//这是遇到的第二个生命周期
// console.log(this.msg);
// this.show()
// 在created中,data和methods都已经被初始化好了
// 如果要调用methods中的方法,或者操作data中的数据,最早,只能在created中操作
},
beforeMount() {//这是我们遇到的第3个生命周期,表示模板已经在内存中编辑完成了,但是尚未把模板渲染到页面中
// console.log(document.getElementById('h3').innerText)
// 在beforeMount执行的时候,页面中的元素,还没有被真正的替换过来,只是之前写的一些模板字符串
},
mounted() {//这是遇到的第4个生命周期,表示内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
// console.log(document.getElementById('h3').innerText)
// 注意:mounted是实例创建期间的最后一个生命周期函数,当执行完mounted就表示,实例已经被完全创建好了
// 此时,如果没有其他操作的话,这个实例就静静的 躺在我们的内存中,一动不动
},
// 接下来是运行中的两个事件
beforeUpdate() {//这时候,表示我们的界面还没有被更新, 【数据被更新了吗? 数据肯定被更新了】
// console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
// console.log('data中的msg数据是:' + this.msg)
// 得出结论:当执行 beforeUpdate 的时候,页面中的显示数据还是旧的,此时 data 数据是最新的,
// 页面尚未和最新的数据保持同步
},
updated() {//
console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
console.log('data中的msg数据是:' + this.msg)
// updated事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
},
beforeDestroy() {//当执行beforeDestroy钩子函数的时候,Vue实例就已经从运行阶段,进入到了销毁阶段
// 当执行beforeDestroy 的时候,实例身上所有的data 和所有的methods,以及过滤器、指令......都处于可用
// 状态,此时,还没有真正执行销毁的过程
},
destroyed() {//当执行到 destroyed 函数的时候,组件已经被完全销毁了,此时,组件内所有的数据、方法、指令、过滤器......,都已经不可用了
},
});
</script>
</body>
</html>
过滤器
概念:Vue.js 允许你自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两个地方:mustache 插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示;
<!-- 过滤器调用时候的格式 {{ name | nameope }} -->
1、私有过滤器
以下代码是获取当前的日期
私有 filters 定义方式:
(定义在 VM 对象中与 data
、methods
等同级,只能由当前 VM 对象控制的区域进行使用,例如:有一个 VM2 的对象,不能使用 VM 中定义的私有过滤器)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<p>{{dt | dataFormat('yyyy-mm-dd')}}</p>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
dt: new Date()
},
methods: {},
filters: { // 私有局部过滤器,只能在 当前 VM 对象所控制的 View 区域进行使用
dataFormat(input, pattern = "") { // 在参数列表中 通过 pattern="" 来指定形参默认值,防止报错
var dt = new Date(input);
// 获取年月日
var y = dt.getFullYear();
var m = (dt.getMonth() + 1).toString().padStart(2, '0');
var d = dt.getDate().toString().padStart(2, '0');
// 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日
// 否则,就返回 年-月-日 时:分:秒
if (pattern.toLowerCase() === 'yyyy-mm-dd') {
return `${y}-${m}-${d}`;
} else {
// 获取时分秒
var hh = dt.getHours().toString().padStart(2, '0');
var mm = dt.getMinutes().toString().padStart(2, '0');
var ss = dt.getSeconds().toString().padStart(2, '0');
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
}
}
}
});
</script>
</body>
</html>
<!-- 前一个参数是补多少位,后一个是用什么来补位 -->
<!-- 字符串的padStart() 方法用于头部补全:'x'.padStart(5, 'ab') // 'ababx'-->
<!-- 字符串的padEnd() 方法用于尾部补全:'x'.padEnd(5, 'ab') // 'xabab' -->
使用ES6中的字符串新方法 String.prototype.padStart(maxLength, fillString=‘’) 或
String.prototype.padEnd(maxLength, fillString=‘’)来填充字符串;
2、全局过滤器
(定义在 <script> ...... </script>
标签里面的 JS 代码,所有的 Vue 实例都可以使用,例如:有一个 VM2 的对象,可以使用定义的全局过滤器)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<p>{{dt | dataFormat('yyyy-mm-dd')}}</p>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
// 定义一个全局过滤器
Vue.filter('dataFormat', function (input, pattern = '') {
var dt = new Date(input);
// 获取年月日
var y = dt.getFullYear();
var m = (dt.getMonth() + 1).toString().padStart(2, '0');
var d = dt.getDate().toString().padStart(2, '0');
// 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日
// 否则,就返回 年-月-日 时:分:秒
if (pattern.toLowerCase() === 'yyyy-mm-dd') {
return `${y}-${m}-${d}`;
} else {
// 获取时分秒
var hh = dt.getHours().toString().padStart(2, '0');
var mm = dt.getMinutes().toString().padStart(2, '0');
var ss = dt.getSeconds().toString().padStart(2, '0');
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
}
});
var vm = new Vue({
el: '#app',
data: {
dt: new Date()
},
methods: {},
})
</script>
</body>
</html>
过滤前显示结果:
过滤后显示结果:(更加符合我们的日常生活场景)
注意:过滤器调用的时候,采用的是就近原则,如果私有过滤器和全局过滤器名称一致了,这时候 优先调用私有过滤器
键盘修饰符以及自定义键盘修饰符
通过Vue.config.keyCodes.名称 = 按键值
来自定义案件修饰符的别名:
Vue.config.keyCodes.f2 = 113;
使用自定义的按键修饰符:
<input type="text" v-model="name" @keyup.f2="add">
按键值参考网站:js键盘按钮keyCode及示例大全
自定义指令(自定义全局和局部的 自定义指令)
1、自定义全局指令
(定义在 <script> ...... </script>
标签里面的 JS 代码,所有的 Vue 实例都可以使用)
使用 Vue.directive()定义全局的指令 v-focus
其中:参数1:指令的名称,注意,在定义的时候,指令的名称前面不需要加v-前缀 但是:在调用的时候,必须 在指令的名称前 加上 v-
前缀来进行调用 参数2:是一个对象,这个对象上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作
// 自定义全局指令 v-focus,为绑定的元素自动获取焦点:
Vue.directive('focus', {
bind: function (el) {//每当指令绑定到元素上的时候,会立即执行这个bind函数,只执行一次
// 注意:在每个 函数中,第一个参数,永远是el,表示 被绑定指令的那个元素,这个el参数,是一个原生的JS对象
// 在元素 刚绑定指令的时候,还没有 插入到DOM中去,这时候,调用的focus方法没有作用
// 因为,一个元素,只有插入了DOM之后,才能获取焦点
// el.focus()
},
inserted: function (el) { //inserted表示元素 插入到DOM中的时候,会执行inserted函数【触发1次】
el.focus()
// 和JS行为有关的操作,最好在inserted中去执行,放置JS行为不生效
},
updated: function () {//当VNode更新的时候,会执行 updated,可能会触发多次
},
})
2、自定义局部指令
(定义在 VM 对象中与 data
、methods
等同级,只能由当前 VM 对象控制的区域进行使用)
// 自定义局部指令 v-color 和 v-font-weight,为绑定的元素设置指定的字体颜色 和 字体粗细:
directives: {
color: { // 为元素设置指定的字体颜色
bind(el, binding) {
el.style.color = binding.value;
}
},
'font-weight': function (el, binding2) { // 自定义指令的简写形式,等同于定义了 bind 和 update 两个钩子函数
el.style.fontWeight = binding2.value;
}
}
使用方法
2、自定义指令的使用方式:
<input type="text" v-model="searchName" v-focus v-color="'red'" v-font-weight="900">
补充(ES6)
ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准。 ES6 主要是为了解决 ES5
的先天不足,比如 JavaScript 里并没有类的概念,但是目前浏览器的 JavaScript 是 ES5
版本,大多数高版本的浏览器也支持 ES6,不过只实现了 ES6 的部分特性和功能。
ES6新特性总结
1. let const
let 表示申明变量。const 表示申明常量。
- 常量定义了就不能改了。对象除外,因为对象指向的地址没变。
- const在申明是必须被赋值。
- 两者都为块级作用域。
块级作用域与函数作用域。任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。函数作用域就好理解了,定义在函数中的参数和变量在函数外部是不可见的。
const a = 1
a = 0 //报错
2. 模块字符串``
可以使用反引号``来进行字符拼接。${}
输出模板通常是下面这样写的:
var a = 1
var b = 2
var sum = a + b
var res = a + '+' + b + '的和是' + sum
console.log(res)
// =====================================
var obj = { name: '张三', age: 21 }
var str = '姓名:' + obj.name + ' ' + '年龄:' + obj.age
console.log(str)
结果:
引入了模板字符串后,输出模板是下面这样写的:
var a = 1
var b = 2
var sum = a + b
var res = `${a}+${b}的和是${sum}`
console.log(res)
// =====================================
var obj = { name: '张三', age: 21 }
var str = `姓名:${obj.name} 年龄:${obj.age}`
console.log(str)
结果:
3. 解构
可以使用{}来对数组和对象进行解构。
// 创建数组
const foodList = ['西蓝花', '花菜', '辣椒', '肉']
// 数组解构
const [food1, food2, food3, food4] = foodList
// 结果为 food1=西蓝花 food2=花菜 food3=辣椒 food4=肉
// 创建对象
const person = {
name: '李四',
skill: '光头',
color: '黑色'
}
// 对象解构
const { name, skill, color } = person
注意:对象解构名称要与对象里面的名称相同
4. 函数的参数默认值
函数传参可以有默认值
// ES6;
function printText(text = 'default') {
console.log(text);
}
5. Spread / Rest 操作符…
Spread / Rest 操作符指的是 …,具体是 Spread 还是 Rest 需要看上下文语境。
- 当被用于迭代器中时,它是一个 Spread 操作符:迭代器 (Iterator)是按照一定的顺序对一个或多个容 器中的元素行进遍历的一种机制
function foo(x,y,z) {
console.log(x,y,z);
}
let arr = [1,2,3];
foo(...arr); // 1 2 3
- 当被用于函数传参时,是一个 Rest 操作符:当被用于函数传参时,是一个 Rest 操作符:
function foo(...args) {
console.log(args);
}
foo( 1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]
6. 箭头函数
- 不需要 function 关键字来创建函数
- 省略 return 关键字
- this始终指向函数申明时所在作用域下的this值
//es5
var fun = function() {
}
//es6
var fn = () => {
}
7. for of
- for of遍历的是键值对中的值
- for in遍历的是键值对中的键
8. class类
ES6 中支持 class 语法,不过,ES6的class不是新的对象继承模型,它只是原型链的语法糖表现形式。
class Student {
constructor() {
console.log("I'm a student.");
}
study() {
console.log('study!');
}
static read() {
console.log("Reading Now.");
}
}
console.log(typeof Student); // function
let stu = new Student(); // "I'm a student."
stu.study(); // "study!"
stu.read(); // "Reading Now."
9. 导入导出
- 导入improt
- 导出export default
10. promise
Promise 用于更优雅地处理异步请求。
<script>
new Promise((resolve,reject) => {
setTimeout(function() {
resolve('成功了!')
},1000)
// reject("失败了,wuwu")
}).then(data => {
console.log(data)
}).catch(err => {
console.log(err)
})
</script>
11. async/await
比promise更好的解决了回调地狱。
async function() {
awiat fn()
}
12. Symbol
新的基本类型,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。
let sy = Symbol("KK");
console.log(sy); // Symbol(KK)
typeof(sy); // "symbol"
// 相同参数 Symbol() 返回的值不相等
let sy1 = Symbol("kk");
sy === sy1; // false
13. Set集合
存储任何类型的唯一值,即集合中所保存的元素是不重复的。类数组结构。
arr = [1,2,3,1]
let arrNew = new Set(arr)
arrNew = [1,2,3]
类数组不是数组,要转化为数组Array.form(arrNew)这样arrNew才是数组了
推荐书籍
需要了解更多参考以下书籍:
书籍:《ECMAScript 6 入门教程》全面介绍 ECMAScript 6 新引入的语法特性。