数据变更检测

数据变更检测

vue的响应式系统:数据发生改变,则页面会自动渲染 (前提 vue检测到数据发生改变)
以下情况,vue无法检测到数据的改变

1 对象属性的添加和删除  对象.新属性=""  delete 对象.属性
2 操作数组的下标或长度  数组[下标] = ""  数组.length=值  

1 解决 对象属性添加

方式1: 民间方法


    methods:{
        addAttr(){
            this.user.age=18           
            this.user={...this.user};

方式2: 官方的

语法: this.$set(对象,‘属性’,属性值)
this.$set(this.user,"age",18)

2 解决对象属性的删除

语法: this.$delete(对象,"属性")
 this.$delete(this.user,"name")

3 解决操作数组的下标

方式1:民间方法

this.arr[0]="AA"
this.arr=[...this.arr]

方式2:官方

语法:this.$set(数组,下标,值)
this.$set(this.arr,0,"AA")

4 解决操作数组长度

 this.arr=[];

组件生命周期函数、

概念

生命周期:一个组件从创建到销毁的整个过程

在整个组件的生命周期过程中,拥有4个阶段, 并且每个阶段有各自的函数,伴随着生命周期的运转,这些函数会自动触发执行,因此,我们把这些生命周期函数也叫做钩子函数

每到达一个阶段,会自动执行对应的函数

4阶段 8函数

函数位置和data并列(不能写在methods中)

1 创建阶段:初始化data、methods等

	
    //创建前
    beforeCreate(){},
    //创建后   ----  用得多
    created(){
    	// 发送ajax获取初始数据
    	
    }	
 

2 挂载阶段 :渲染页面

    //挂载前
    beforeMount(){},
    //挂载后  ----用的多  
    mounted(){
    	//说明了页面的元素都已经渲染完毕,也就意味着可以获取页面的节点
    },

注意:前面两个阶段是加载页面必须会自动执行的

3 更新阶段 :只有更新元素时才会触发 — 用得非常不多,如果用的不好,很可能会递归

原因:如果元素更新,一般说明数据是更改了,既然是数据发生了改变,我们完全可以利用computed和watch去实现某些功能

    //更新前
    beforeUpdate(){
         console.log("beforeUpdate");
    },
    //更新后
    updated(){
        console.log("updated");
    },

4 销毁阶段:当离开组件时才会触发

    //销毁前
    beforeDestroy() {
        console.log("beforeDestroy");
    },
    //销毁后
    destroyed(){
    	收尾工作,清除数据(clearInterval)
        console.log("destroyed");
    }

面试题 什么是虚拟dom

传统: 数据改变---》操作真实dom---》视图更新

一个普通的节点其实里面是带有大量的属性的,如果我们频繁的操作该节点,则页面的性能开销变大,导致性能降低

    <script>
        let s=document.getElementById("s");
        let str="";
        for(let i in s){
            str+=i+" ";
        }
        console.log(str);
    </script>


vue: 数据改变---》虚拟dom(内存)-----》操作真实dom---》视图更新

概念:通过状态生成虚拟dom,每当数据发生改变时,会通过新旧虚拟dom来进行节点的对比,最终计算出一个最终的结果,只需要渲染一次真实dom实现页面的更新

具体:
1 当我们在template中写好布局之后,首次渲染时,vue会通过编译将代码转成render函数,执行该函数获得虚拟dom(vnode),最终页面是靠虚拟dom来进行渲染的(虚拟dom---》真实dom)

2 每当数据发生改变时,会产生一个新的虚拟dom(vnode),vue会让新的vnode和旧的vnode做对比
	2.1(尽管中间有大量的频繁的don操作,直到把最终结果用来做渲染)----->把更新真实dom的次数减少为1次  
	2.2 (由于是新旧对比,因此能够做到只把改变的那个节点用来刷新---局部刷新) 用到了patch函数(diff算法)



总结: 
	1 降低了页面性能消耗  、 提高了页面的渲染速度
	2 vue能够智能的计算出重新渲染组件的最小代价,并应用到dom操作上

vue中组件的通信问题

组件的通信指的就是组件之间如何传参

1 父子

父组件把参数传递给子组件

父组件:

<子组件标签  :自定义属性 ="变量" 

子组件

export default{
	props:["自定义属性"]
}

使用

props拿到的数据本质也是属性,因此和data、computed同地位的(也能够直接在tempalte渲染,以后在方法中也是通过this点出)

单向数据流

0 父组件通过props传参给子组件

1 子组件能否直接修改父组件传递过来的参数  --不能  

2 父组件更改传递的值时,子组件能否同步  --能

自定义事件:子组件把参数传递给父组件 (子组件如何调用父组件的方法,顺便传参)

虽然有单向数据流的约束,导致子组件不能直接修改父组件传递过来的参数,但是子组件能够把参数传递给父组件,让父组件自己来修改参数即可

父组件

<Son   @自定义属性="methods中定义的方法"/>


methods:{
  方法(参数){}	
}

子组件:

this.$emit("自定义属性",参数)

练习1:

 父组件提供一个name:张三  ,传递给儿子,儿子接受到后用于渲染,儿子拥有一个按钮,点击后能够修改传递过来

练习2: 父子组件同步文本框

方式1:data+watch的套餐

父:

<template>
    <div>
        Father <input type="text" v-model="t">
        <hr>
        <Son :t="t" @change="change"/>
    </div>
</template>

<script>
import Son from './Son.vue'
export default {
    components:{
        Son
    },
    data(){
        return{
            t:"111"
        }
    },
    methods:{
        change(t){
            this.t=t
        }
    }

}
</script>

<style>

</style>

子:

<template>
    <div>
        Son <input type="text" v-model="t2">
    </div>
</template>

<script>
export default {
    props:["t"],
    data(){
        return{
            t2:this.t
        }
    },
    watch:{
        t(newVal){
            console.log(newVal);
            this.t2=newVal
        },
        t2(newVal){
            console.log(newVal);
            //调用父组件的方法,把newVal传递过去
            this.$emit("change",newVal)
        }
    }
}
</script>

<style>

</style>

方式2:computed单人套餐

父组件:同上

子组件

<template>
    <div>
        Son <input type="text" v-model="t2">
    </div>
</template>

<script>
export default {
    props:["t"],

    computed:{
        t2:{
            get(){
                return this.t
            },
            set(val){
                console.log(val);
                this.$emit("change",val)
            }
        }
    }
    
}
</script>

<style>

</style>

2 事件总线(EventBus)-用于兄弟组件的传参(非父子)

目的:A组件调用B组件的方法,顺便传递参数 ,并且渲染该参数

A组件是调用者

B组件是被调用者

步骤

1 新建bus.js ,该js用于用于创建和暴露bus对象(vue实例)

import Vue from 'vue'
let bus =new Vue()
export default bus

2 在被调用的组件上通过bus来注册 (B组件)

<template>
    <div>
        B  -- {{name}}
    </div>
</template>

<script>
import bus from '../../bus.js'
export default {
    data(){
        return{
            name:""
        }
    },
    //页面挂载完毕后注册s
    mounted(){
        console.log(this);
        //存一个临时变量
        let that=this;
        bus.$on('xx',function(data){
            //自己的业务
            console.log(data);
            //赋值
            that.name=data
        })
    }
}
</script>

<style>

</style>

3 在需要调用的组件上通过bus来调用 (A组件)

<template>
    <div>
        A
        <button @click="ff">点击</button>
    </div>
</template>

<script>
import bus from '../../bus.js'
export default {
    methods:{
        ff(){
            bus.$emit('xx',"张三")
        }
    }
}
</script>

<style>

</style>

3 props扩展

1 props能够传递哪些数据类型

一切数据类型: Array 、Object 、String 、Number

2 props的完整语法

    props:{
        t:{
            //约束数据类型
            type:String,
            //是否必传
            required:false,
            //默认值
            default:"哈哈"
        }
    }

3 关于参数是对象和数组时对默认值的影响

默认值如果是对象或数组需要通过函数以及return来描述

default:function(){
       return {}
 }

default:function(){
	return []
}

 如果是箭头函数的简写,则对象类型需要添加()

 default:()=>({})
 default:()=>[] 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值