1.生命周期
生命周期:一个vue实例从创建到消亡的整个过程。
生命周期图:
四个阶段:
创建阶段:
beforeCreate:创建前
data还没有初始化,不可以访问data里的数据和methods里的方法。
created:创建后
重要!!这个时候可以访问data里的数据和methods里的方法。
挂载阶段:
beforeMount:挂载前
不能操作DOM节点。
mounted: 挂载后 调接口
重要!!可以操作DOM节点。
更新阶段:
beforeUpdate:更新前
数据是更新之后的,页面还未更新
updated:更新后
重要!!页面更新。
销毁阶段:
beforeDestroy:销毁前
清除定时器、解绑事件等。。。。
destroyed:销毁后
vue实例被销毁,事件不能再使用。
销毁阶段需要通过vm.$destroy()方法来销毁实例。
完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器。
触发
beforeDestroy
和destroyed
的钩子
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<p>{{num}}</p>
<button @click="num++">增加</button>
<button @click="addNum">增加2</button>
<button @click="destroy">销毁</button>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
num: 1,
timer: null
},
// 创建前
beforeCreate() {
console.log(this.num, "创建前"); //undefined
// this.getNum(); //报错
},
// 创建后
created() {
console.log(this.num, "创建后"); //1
// this.getNum(); //可以正常方法
},
// 挂载前
beforeMount() {
// let p = document.querySelector('p');
// // console.log(p);
// p.innerHTML = "挂载前";
console.log("挂载前"); //不能操作DOM节点
},
// 挂载后
mounted() {
// let p = document.querySelector('p');
// // console.log(p);
// p.innerHTML = "挂载后";
console.log("挂载后"); //可以操作DOM节点
timer = setInterval(() => {
// console.log(this);
this.num++
}, 1000)
},
// 更新前
beforeUpdate() {
console.log("更新前");
// let p = document.querySelector('p');
// console.log(p.innerHTML);
},
// 更新后
updated() {
// debugger
console.log("更新后");
let p = document.querySelector('p');
console.log(p.innerHTML);
},
// 销毁前
beforeDestroy() {
clearInterval(timer);
console.log("销毁前");
},
// 销毁后
destroyed() {
this.addNum();
console.log("销毁后");
},
methods: {
getNum() {
console.log(this.num);
},
destroy() {
this.$destroy();
},
addNum() {
this.num++
}
},
})
</script>
</body>
</html>
8.补充
1.动态控制样式
把class和style改成变量。
v-bind绑定class:
<!-- 变量替换 -->
<p :class="className">1231</p>
<!-- 字符串拼接 -->
<p :class="className+'-bg'">1231</p>
<!-- 判断条件,对象形式 表达式为真,选择那个 -->
<p :class="{red:num>2,green:num<2}">1231</p>
<!-- 三元运算 -->
<p :class="[num>1?'red':'green']">1232123</p>
v-bind绑定style:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">绑定style</div>
<div v-bind:style="styleObject">绑定style</div>
2.设计模式:MVVM
model-view-viewModel(MVVM)
数据-视图-视图数据
3.Object.defineProperty()
参考网址:Object.defineProperty() - JavaScript | MDN
// Object.defineProperty的第三个参数都有哪些属性:
// value 属性值
// writable 属性值是否被修改
// configurable 属性是否可以被删除
// enumerable 属性是否可以被枚举
const obj = {};
// Object.defineProperty的第三个参数都有哪些属性:
// value 属性值
// writable 属性值是否被修改
// configurable 属性是否可以被删除
// enumerable 属性是否可以被枚举
// Object.defineProperty(obj, 'num', {
// value: 42, //给对象的属性名赋值
// writable: false, //属性值是否被修改 默认false 不可以被修改
// configurable: false, //属性是否可以被删除 默认为false 不可以被删除
// enumerable: false, //属性是否可以被枚举 默认为false 不可以被枚举
// });
// console.log(obj);
let n1 = 18;
Object.defineProperty(obj, 'age', {
get() {
console.log(1);
return n1;
},
set(newValue) {
console.log(2);
return n1 = newValue;
}
});
console.log(obj.age);
obj.age = 19;
console.log(obj);
// for (key in obj) {
// console.log(obj[key]);
// }
9.watch 侦听器
作用:对data里面的数据进行侦听处理。
使用:
浅监听:基础数据类型
watch:{
变量名(newVal,oldVal) {
}
}
深监听:复杂引用数据类型
watch:{
变量名:{
deep:true,
handler:function(newVal){
}
}
}
深度监听:
(1)Vue中的watch默认不监听对象内部的值的改变。
(2)配置deep:true可以实现深度监听(多层)。
<div id="app">
{{num}}{{str}}{{obj}}{{arr}}
<button @click="add">点击</button>
<button @click="change('小兰')">点击修改obj</button>
<button @click="changeArr('999')">点击修改arr</button>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
num: 2,
str: "侦听器",
obj: {
uname: "小红"
},
arr: [{
uname: "小红"
}]
},
methods: {
add() {
this.num++
},
change(username) {
this.$set(this.obj, "uname", username)
},
changeArr(num1) {
// this.arr.push(num1);
this.$set(this.arr[0], "uname", num1);
}
},
watch: {
// 浅监听
num(newVal, oldVal) {
console.log(newVal, oldVal);
},
str(newVal, oldVal) {
console.log(newVal, oldVal);
},
// arr(newVal, oldVal) {
// console.log(newVal, oldVal);
// },
// 深监听
obj: {
deep: true, //如果监听复杂数据类型,必须添加这个熟悉属性
handler: function(newVal) {
console.log(newVal);
}
},
arr: {
deep: true,
handler: function(newVal) {
console.log(newVal);
}
}
}
})
</script>
监听属性watch:
1.当被监视的属性变化时,回调函数自动调用,进行相关操作。
2.监视的属性必须存在,才能进行监视。
3.监视的两种写法:
(1)new Vue时传入watch配置
(2)通过vm.$watch监视
10.计算属性
含义:本质还是属性,用于在模板中显示。
计算属性其实和data地位相同,都是vue实例的属性,都可以在模板中使用。
一般在模板语法中使用表达式比较方便,模板也只是用于简单的运算,当表达式过于复杂的时候,难以维护,而且模板过重。
语法:
computed:{
属性名:function(){
return 值
}
}
{{属性名}}
<p>{{msg}}</p>
computed: {
msg: function() {
console.log(this);
return this.message.split('').reverse().join('');
}
}
注意:
要用的属性不存在,要通过已有的属性计算得来。
原理:
底层借助了Object.defineProperty中的setter和getter.
get函数什么时候执行?
(1)初次读取时会访问一次。
(2)当依赖的数据发生改变时会执行。
计算属性和方法区别:
-
计算属性依赖于缓存,效率更高,如果依赖的数据没有变化,他就不执行。
-
方法要执行必须要调用。
计算属性和侦听器的区别:
-
计算属性主要是为了简化模板里的操作,对数据处理后展示,侦听器主要目的是监听数据的变化,执行相对应的逻辑。
-
计算属性能做的处理,侦听器都可以。
-
侦听器能做的,计算属性不一定能完成。侦听器可以执行异步操作。
代码示例:
<body>
<div id="app">
<input type="text" v-model="msg"> {{msg1}}
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
msg: "hello world"
},
watch: {
msg() {
setTimeout(() => {
console.log(this);
console.log(this.msg);
}, 3000)
}
},
computed: {
msg1() {
setTimeout(() => {
console.log(this);
// console.log(this.newV);
return this.msg.split('').reverse().join('')
}, 3000)
}
}
})
</script>
</body>