数据变更检测
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:()=>[]

被折叠的 条评论
为什么被折叠?



