学习Vue框架第四天心得

1.虚拟DOM

  • 在vue的内部的化,其实又虚拟dom的存在,虚拟dom其实是里面内存形对象存数据 真实dom的一种映射
  • 虚拟dom:当数据发生变化的时候大量操作的是虚拟dom,而虚拟dom属于内存数据,操作起来性能要高于操作真实的dom,虚拟dom只有在追加的那一刻才会操作真实dom,大大提升了性能

浏览器加载一个html文件的大致流程是这样的:

  1. 在内存中生成一颗虚拟dom树
  2. 将内存中的虚拟dom树初始化渲染成真实的dom树
  3. 当我们修改data里面的数据的时候
  4. 将之前的虚拟dom树结合新的数据生成一个新的虚拟dom树
  5. 将此次生成好的新的虚拟dom树与上一次的虚拟dom树结构进行对比,对比差异(diff算法)
  6. 将对比出来的差异的部分进行重新真实dom结构的渲染

2.Diff算法

在虚拟dom中,在dom的状态发什么变化时,虚拟dom会进行diff运算,来更新只需要被替换的DOM,而不是全部重绘。
在diff算法中,只有平层的比较前后dom树的结点,没有进行深度的遍历。

  1. 如果系欸但类型改变,直接将旧节点卸载,喜欢新节点
  2. 节点类型不变,属性或者属性值改变,不会卸载节点,执行节点更新的操作
  3. 文本改变,直接修改文字内容
  4. 移动,增加,删除子节点时:
    在这里插入图片描述
    如果想在中间插入节点F,简单粗暴的做法就是卸载c,装载f,卸载d,装载c,卸载e,装载d,装载e
    在这里插入图片描述
    写代码时,如果没有给数组或枚举类型定义一个key,就会采用上面简单粗暴的方法
    如果为元素增加key以后,Vue会根据key,直接找到具体的位置进行操作,效率比较高,如下图:
    在这里插入图片描述

问题:什么是虚拟dom?与key值的关系?

  • 当用传统的方式操作DOM的时候,浏览器会从构建DOM树开始从头到尾执行一遍流程,效率很低。而虚拟DOM是用javascript对象表示的,而操作javascript是很简便高效的。虚拟DOM和真正的DOM有一层映射关系,很多需要操作DOM的地方都会去操作虚拟DOM,最后统一一次更新DOM。因而可以提高性能
  • 在虚拟dom中,移除 增加 删除子节点的时候,如果没有添加key值,他会采用我们上面所说的简单粗暴的做法,当然如果给元素添加了key属性之后,就不会出现这样的问题了。key属性一方面可以提高虚拟dom的对比性,一方面也会避免出错,还可以避免元素的复用。

3.父子之间的通信传值是如何实现的

  1. 父组件在调用子组件的时候,可以通过v-bind来为子组件传递数据,父组件数据变化子组件数据也会变化
  2. 子组件可以通过props的属性接收父组件传递过来的数据
  3. 如果子组件没有通过props属性接收数据,这个数据就会被挂在子组件模板的根节点。看下图。
    在这里插入图片描述
<div id="app"> 
        <father></father>
 </div>
 
 <template id="father">
   	<div>
         <p>这是father组件!---> {{pMsg}}</p>
         <son :msg="pMsg"></son><!--父组件在调用子组件的时候 绑定一个属性 可以通过props接收 --> 对应第一步
     </div>
 </template>
Vue.component("father",{
	template:"#father",
	data:()=>{
		return{
			pMsg:"hello father"
		}
	},
	components:{
		son:{
			template"<div>这是son子组件</div>",
			props:["msg"] //接收父组件传递来的属性  ->对应第二不
		}
	}
})

let vm = new Vue({
	el:"#app",
	data:{
		msg:"hello app!"
	}
})

问题:为什么组件中data必须是一个函数返回对象的形式呢?

  • 目的是让每一个实例可以维护一份被返回对象的独立拷贝。(每个组件使用到的地址不一样)
  • 换言之:内部必须要返回一个对象的写法,这样就可以保证每个组件里面用到的数据对象都是唯一的。

4.子父之间的通信传值是如何实现的?

  1. 在父组件内部声明一条数据
  2. 在父组件内部再写一个改变自身数据的方法
  3. 父组件在调用子组件的时候,给其自身绑定一个自定义事件 change <son @change=“changeMsg”>
  4. 当子组件触发这个事件的时候,相当于父组件的方法被执行了… (this.$emit(自定义事件,参数))
  5. 子组件就通过$emit将数据传递给了父组件
    在这里插入图片描述

5.兄弟之间的通信时如何实现的?

  1. 关系链+ref链可以实现兄弟之间的通信
  2. events bus 事件总线也可以实现

6.关系链(viewmodel链)

  • 组件 实例对象上有这样的属性: p a r e n t , parent, parent,children,$root
  • 这样的话就形成了viewmodel链,理论上来说
  • 任何两个组件之间的数据都可以相互调用,获取
  • 缺点:太乱了 this. r o o t . root. root.children[3].$children[4]…
set(val){
      console.log(val)
         //this.msg = val;  //对于父组件传递来的属性进行了更改
         this.$parent.msg = val  //相当于找到aaa组件。把滋生的msg赋值给aaa组件的msg
     }

7.ref链

  • 组件间可以通过 r o o t / root/ root/parent/$children来获取对应的组件
  • 父组件还可以主动的通过ref为子组件做标记 也可以给dom做标记
  • 也会形成ref链,也可以交互
<template id="aaa">  
        <div>
            <button ref="btn" @click="get">get</button>   //这样打标记
            <bbb ref="b"></bbb>
        </div>
    </template>
get(){
  // this.$children[0].msg = "get"   //是通过关系链(viewModel)去实现 this代表aaa 表示b组件得msg属性
    console.log(this.$refs)//{b:vueconponent}指向b组件,前期要做标记ref="b" 被标记的都会显示在这个对象里面
    this.$refs.b.msg = "get"     //通过ref链给组件做标记
}

8.事件总线

在这里插入图片描述

  • EventBus 又称为事件总线。在Vue中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护的“灾难”,因此才需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。

  • 事件总线可以实现兄弟之间的通信

  • 大致步骤
    • 创建一个公共的vue实例
    • 在mounted()生命周期钩子函数中绑定好事件
    • 触发事件 一旦触发所有地方都能接收到,这就是事件总线

9.slot槽口

  • 在组建标签内部写入的内容默认会被替换掉
  • 如果想要在组件的模板里使用这些内容
  • 就在对应位置的模板里写上solt标签,这个slot标签就代表着这些内容
  • 具名槽口
  • slot标签上通过name属性指定槽口名称 是在模板内
  • 然后使用的时候通过slot="槽口名称“ 是在标签内

vue2.6版本推荐的slot槽口的写法

  • v-slot在使用时,需要在template标签内,这点大家要注意
  • 刚开始还是在模板里面写一个slot标签,通过name属性指定槽口的名称
  • 在标签内先写一个template标签里面写内容,在template后面通过 v-slot:槽口名称
<div id="app">
   <hello>
        <template v-slot:a>
            联通卡
        </template>
        <template v-slot:b="info"><!-- 用作用域槽口 直接拿不到msg  -->
            <div>移动卡1</div> {{info.msg}}<!-- 拿到是是一个对象,要在组件上绑定一个属性 -->
            <div>移动卡2</div>
        </template>
    </hello>
</div>

<template id="hello">
   <div>
        <slot name="a"></slot>
        <slot name="b" :msg="msg"></slot> 
    </div>
</template>

10.prop验证

  • 我们可以为组件的 prop 指定验证规则。如果传入的数据不符合要求,Vue 会发出警告。这对于开发给他人使用的组件非常有用
  • 验证主要分为:类型验证、必传验证、默认值设置、自定义验证
  • prop的值可以是对象,在里面可以对父组件传递过来的数据进行验证
 son:{
  template:"#son",
   	props:["num"] //1.直接接收父组件传递过来的数据
    props:{
         num:Number  //2.传递过来的必须要是数字类型
        num:[Number,String]//3.传递过来的必须时数字 字符串类型
         num:{//4.必须时数字类型,默认1000,必填
             type:Number,
             default:1000,
            required:true  //必填
         }
         num:{//5.传递来的数据必须大于5
          		type:Number,
           		 validator(val){
                return val>5
             }
         }
    }
}

11.单项数据流

  • Vue/React单向数据流的体现:数据只能从父级组件流向子级组件
  • prop时单项绑定的:当父组件的属性变化时,将传递给子组件,但是反过来不会,这是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得难以理解。
  • 另外,每次父组件更新时,子组件的所有prop都会更新为最新值。这意味着你不应该在子组件内部改变prop,如果你这么做了,vue后台会给出警告。

注意在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。 message:{val:""}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值