一、生命周期
1、含义
- 生命周期:一个vue实例生命的周期,也就是vue实例从开始到结束的过程,从创建到销毁的过程;
2、生命周期图
3、生命周期阶段
创建阶段
beforeCreate 创建之前
作用:一般不使用,做一些需要在创建之前做的事情
注意:这里不能操作data里面的数据,因为data没有被初始化
created 创建之后
作用:一般在这里发送数据请求,开启定时器
注意:这里是最早操作data里面的数据的地方
在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
挂载阶段
beforeMount 挂载之前
注意:在这个函数里,页面没有真正渲染,只是有了虚拟dom(js对象)
mounted 挂载之后
作用: 把虚拟dom真正的渲染到页面上,页面上有了真实dom
从这里开始可以使用$refs获取dom节点
初始化一些插件相关的配置,也可以发送数据请求
在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
更新阶段
beforeUpdate 更新之前
作用:做一些判断 是否需要更新
updated 更新之后
销毁阶段
beforeDestroy 销毁之前
作用 销毁之前做一些保存
destroyed
作用 释放定时器相关的内容, 销毁之后,事件绑定都不存在了
- 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
{{msg}}
<button @click="fn">点击</button>
</div>
</body>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"it"
},
methods:{
fn(){
console.log(123)
}
},
//创建阶段
beforeCreate(){
//这里不能操作data里面的数据,因为data没有被初始化
console.log(this.msg);
console.log("创建之前");
console.log(document.querySelector("#app"));
},
created(){
// 一般在这里发送数据请求,开启定时器
console.log(this.msg);
console.log("创建之后");
console.log(document.querySelector("#app"));
},
//挂载阶段
beforeMount(){
console.log("挂载之前");
console.log(document.querySelector("#app"));
},
mounted(){
console.log("挂载之后");
console.log(document.querySelector("#app"));
},
//更新阶段
beforeUpdate(){
// 做一些判断 是否需要更新
console.log("更新之前");
console.log(document.querySelector("#app"));
},
updated(){
console.log("更新之后");
console.log(document.querySelector("#app"));
},
//销毁阶段
beforeDestroy(){
// 销毁之前做一些保存
console.log("销毁前");
},
destroyed(){
// 释放定时器相关的内容
// 销毁之后,事件绑定都不存在了
console.log("销毁后");
}
})
setTimeout(()=>{
app.$destroy(); //销毁vue实例
},10000)
</script>
</html>
二、监听器 watch
-
作用 :来监听data里面数据的变化,一旦数据变化了就会自动执行相关的函数
-
分类:
- 浅监听:监听基本数据类型
- 深监听:监听引用数据类型
var app=new Vue({
el:"#app",
data:{
a:2,
b:0
},
watch:{ //监听器
data中的变量(新值,旧值){ //浅监听
//变量的值发生变化,就会执行这里的代码
},
data中变量:{
deep:true, //深监听 【监听引用类型】
handler(新值){
//代码块
}
}
}
})
handler方法
:处理watch监听的变化值的逻辑函数immediate属性
:当父组件向子组件动态传值时,子组件props首次获取到父组件传来的默认值时,也需要执行函数,则将immediate设为true,true代表在 wacth 里声明了 firstName 之后,就会立即先去执行里面的handler方法,为 false就不会在绑定的时候就执行deep
:默认值是 false,代表是否深度监听
watch: {
firstName: {
handler(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
},
// 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
immediate: true
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model.number="a"/>
+
<input type="text" v-model.number="b"/>
=
<input type="text" v-model="c"/>
<hr/>
<p>姓名:{{user.name}}</p>
<p>年龄:{{user.age}} <button @click="ageadd">年龄增长</button></p>
</div>
</body>
<script>
var app=new Vue({
el:"#app",
data:{
a:0,
b:0,
c:0,
user:{
name:"小小",
age:25
}
},
methods:{
ageadd(){
this.user.age++;
}
},
watch:{
a(newv,oldv){
// console.log(123)
// console.log(newv) //变化之后的值
// console.log(oldv) //变化之前的值
this.c=newv+this.b
},
b(newv,oldv){
this.c=newv+this.a
},
user:{ //深度监听
deep:true,
handler(newv){
console.log(1);
console.log(newv)
}
}
}
})
</script>
</html>
三、computed计算属性
-
含义:计算 动词 属性 名词
- 计算属性本质是属性,这个属性需要计算(函数)得到
- 使用场景 :购物车
{{属性名}}
var app=new Vue({
el:"#app",
data:{ }, //定义默认数据的地方
computed:{ //通过计算得到属性
属性名:function(){ //值一定是一个函数,而且这个函数一定要有返回值
return 值;
}
}
}
})
- 注意
计算属性的值一定是一个函数,而且这个函数一定要有返回值 |
---|
计算属性的函数里面的this同样是当前vue实例 |
页面第一次加载时,计算属性的函数会执行,给属性赋初始值 |
依赖属性变化的时候,计算属性的函数会再次执行 |
计算属性可以直接在模板里渲染,说明他也是当前vue实例对象的属性 |
- watch和computed的区别?
watch | computed |
---|---|
监听data和computed中数据的变化 | 定义属性(该属性通过计算得到) |
可以进行异步操作 | 不能进行异步操作 |
- | 通过return 返回处理的数据 |
- computed的get和set
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model.number="a"/>
+
<input type="text" v-model.number="b"/>
=
<input type="text" v-model="c"/>
{{c}}
</div>
</body>
<script>
var app=new Vue({
el:"#app",
data:{
a:0,
b:0
// ,c:0
},
computed:{
// c(){
// // 页面第一次加载时,该函数会(第一次)默认执行,给属性赋初始值
// //依赖属性变化的时候,该函数会再次执行
// console.log("computed")
// return this.a+this.b //this同样是vue实例
// }
c:{
get(){ //c被获取时执行这里(直接读取c的值不会执行)
console.log("get");
return this.a+this.b;
},
set(v){ //c被设置时执行这里 v就是设置的值
console.log("set",v);
}
}
}
})
</script>
</html>
四、购物车Vue小案例
1、购物车思路
2、实现代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./js/vue.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.0/dist/css/bootstrap.min.css">
<style>
*{
padding: 0;
margin: 0;
}
p{
text-align: center;
color: blue;
font-size: 22px;
margin-top: 20px;
}
.number{
display: inline-block;
width: 20px;
height: 20px;
text-align: center;
margin: 0 10px;
}
</style>
</head>
<body>
<div id="app">
<p><span>购物车结算</span></p>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">全选 <input type="checkbox" @click='selectAll' v-model='selectAllChecked'></th>
<th scope="col">商品</th>
<th scope="col">单价</th>
<th scope="col">数量</th>
<th scope="col">小计</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<tr v-for='(item,index) in msgArr' :key='item.id'>
<th scope="row"><input type="checkbox" v-model='item.check' @click='selectOne(index)'></th>
<td>{{item.proname}}</td>
<td>{{item.price}}</td>
<td><button type="button" class="btn btn-primary" @click='reduce(index)'>-</button><span class="number">{{item.num}}</span><button type="button" class="btn btn-primary" @click='add(index)'>+</button></td>
<td>{{item.num*item.price}}</td>
<td><button type="button" class="btn btn-danger" v-on:click='del(index)'>删除</button></td>
</tr>
</tbody>
</table>
<h5>全计金额:{{moneyAll}}</h5>
</div>
</body>
</html>
<script>
var app=new Vue({
el:'#app',
data:{
msgArr:[{id:1,proname:'iphone11',price:5600,num:3,check:false},
{id:2,proname:'vivo',price:7800,num:1,check:false},
{id:3,proname:'华为',price:5660,num:12,check:false},
{id:4,proname:'魅族',price:2500,num:8,check:false},
{id:5,proname:'oppo',price:3500,num:2,check:false},
],
selectAllChecked:false//给全选--设置初始值--未选中
},
methods:{
selectAll(){//点击全选--则每个单项框都被选中--改变单选框的选中状态
//点击全选,切换选中状态
this.selectAllChecked=!this.selectAllChecked;
this.msgArr.forEach((item,index) => {//item--为每一条数据
//点击全选,让单选框的选中状态和全选的状态一样
item.check=this.selectAllChecked;
});
},
selectOne(ind){//点击单选--每个单选框都全中--则全选框也选中
//点击单选框时,单选框状态由初始--未选中--变选中
this.msgArr[ind].check=!this.msgArr[ind].check;
//给每个单项框标记选中状态
var flag=true;//标记为选中状态
//遍历每个单选框--若都选中--才全选
this.msgArr.forEach((item,index)=>{
if(item.check==false){
flag=false;
}
})
this.selectAllChecked=flag;
},
//点击-、+实现数量的加减
add(ind){//将数据的下标作为实参传入--表示点击的是哪条数据的数量-、+
//点击+号,商品数量增加
this.msgArr[ind].num++;
},
reduce(ind){
//点击-号,商品数量减少,小于0将数量设置为0
this.msgArr[ind].num--;
if(this.msgArr[ind].num<=1){
this.msgArr[ind].num=1;
}
},
//删除某一条数据
del(ind){
//点击选中的数据删除--从后台数据数组中删除--某一个数组项
this.msgArr.splice(ind,1);
}
},
computed:{
moneyAll(){//求全计金额
var sum=0;
this.msgArr.forEach((item,index)=>{
if(item.check==true){
sum +=item.price*item.num;
}
})
return sum;
}
}
})
</script>