Vue2--11种组件通信、Vue2处理响应式数据

第一种:Props

    props是vue当中最基本的常用的组件间通信方式    

    适用场景:父子之间 

    父可以给子传递 非函数和函数
    传非函数数据 就是父给子
    传函数数据  本质是父想要子的数据
    <MyButton haha="100">

props子组件声明接收属性三种写法    

1、[‘todos’]  
2、{ todos:Array}   
3、{ todos:{type:Array,default:100,validator:(value) => {return value > 100}}}

特殊:
    路由配置 props(三种)  路由组件之间没有标签,但是可以把参数通过路由映射为属性
    1、布尔值  true   把路径params参数映射为要显示的组件内属性
    2、对象   {name:'赵丽颖'}   只能映射传递额外的静态的数据 一般不用
    3、函数  props:(route) =>{}  自己手动映射params参数和query参数 成为要显示的组件内属性     
 如果不用props,那么组件内要用数据必须要写成 this.$route.params.xxx   this.$route.query.xxx

第二种: 自定义事件

组件通信的一种方式
    适用场合:子向父传递数据

怎么做
        在父组件当中给子组件标签绑定自定义事件,事件回调留在父组件当中
        在子组件当中触发它自己身上绑定的自定义事件,触发事件调用回调函数可以通过实参传递   

原生dom事件 (三要素:事件源  事件类型 回调函数)   
        事件类型  回调函数   谁调用   默认传递的实参是什么 

        1、事件类型       固定的几十个 
        2、回调函数       自己去定义的
        3、触发(分发、触发事件)了谁调用   系统调用  浏览器去调用 
        4、event事件对象  (浏览器在调用回调函数的时候,会把当前这一次触发事件相关的所有信息封装成一个对象
        传递给回调函数的第一个形参) $event
        box.onclick = function(){            
        }

自定义事件     
        事件类型  回调函数   谁调用   默认传递的是什么
        1、事件类型            无数个
        2、回调函数            自己去定义的
        3、谁调用              自己去调用   自己使用$emit触发调用的
        4、默认传递的是什么     默认传递的是自己给的参数 (有就有,没有就没有undefined)        
        this.$emit('haha',10,20)

 原生dom事件在html标签和组件标签上的区别 
        在html标签上添加就是原生的dom事件
        在组件标签上添加就是自定义事件,想成为原生的事件得添加修饰符.native,就是把原生dom事件添加到子组件根元素上    (事件委派)

 vue自定义的事件在html标签和组件标签上的区别 
        在html标签上添加自定义事件无意义,所以自定义事件是给组件标签添加的        
        添加给组件标签:事件名可以任意,也可以和原生的dom事件名相同,但是在组件标签身上即使添加原生dom事件也是自定义的        

 第三种:全局事件总线

所有场合

    全局事件总线的角色标准
    本质是一个对象
    1、所有的组件对象都可以看到它  
    2、可以使用$on和$emit方法

    
    怎么添加事件总线
    1、安装总线
    2、在接收数据的组件对象当中  获取总线给总线绑定自定义事件   回调函数的定义会留在本组件 this.$bus.$on
    3、在发送数据的组件对象当中  获取总线触发总线身上绑定的自定义事件   就可以调用回调函数,通过函数传参 this.$bus.$emit

第四种:v-model 

    element-ui表单相关项都使用到了v-model
    官方网站也提出了怎么去使用

    1、html input v-model的本质
        :value = “data”  //读取数据
        @input = "data = $event.target.value"  //写数据
        

    2、组件标签上 v-model本质
        :value = "data"  父组件传递属性给子组件,子组件需要接受
        @input = "data = $event" //父组件当中给子组件添加的自定义事件

        子组件当中必须这样写
        先接受props:['value']
        
        子组件表单类元素
            :value = "value"
            @input = "$emit('input',$event.target.value)"  

属性如果写在组件标签身上无论带不带冒号,都是在给组件内部传递属性

写在原生html标签身上是给标签绑定属性值,没有传递

干了两件事  
        先绑定数据   只不过在html标签身上是绑定数据,在组件标签身上是传递属性  
        再绑定修改数据的事件   
        只不过在html和组件标签上绑定的@input事件不同   一个是原生的 一个是自定义的事件
    实现父子组件双向数据同步


    源码查看element-ui的input是不是使用了

    本质上还是自定义事件和props组合

<CustomInput :value="msg" @input="msg = $event"></CustomInput>

== <CustomInput v-model="msg"></CustomInput>

         1、通过:value="msg"把value传递给子组件,子组件内部可以接收

         2、子组件内部接收了value之后,可以在子组件内部去使用,但是不能修改

         3、父组件给子组件绑定自定义事件input,触发事件之后,会把子组件修改的数据赋值给父组件当中的msg

         4、子组件当中绑定input原生dom事件,一旦用户输入数据,触发子组件绑定的自定义事件,传递最新输入的值

         5、父组件接收数据之后赋值给msg,msg变为最新的数据,再次传递给子组件,子组件内部msg数据更新 -->

    <input type="text" :value="value" @input="$emit('input',$event.target.value)">

    <span>{{value}}</span>

 

第五种:sync属性修饰符  

    实现父子组件双向数据同步问题
    和 v-model 实现效果几乎一样
    v-model一般用于带表单项的组件
    sync属性修饰符一般用于不带表单项的组件
    
    父组件给子组件属性传递数据后面添加.sync
    子组件修改数据 需要分发事件@click = $emit("update:属性名",要更新的数据)

    本质上还是自定义事件和props组合
 

<template>
  <div>
    小明的爸爸现在有{{money}}元
    
    <h2>不使用sync修改符</h2>
    <Child :money="money" @update:money="money = $event"></Child>
    <h2>使用sync修改符</h2>
    <Child :money.sync="money"></Child>

    <h2>使用v-model修改符</h2>
    <!-- <Child2 :value="money" @input="money = $event"></Child2> -->
    <Child2 v-model="money"></Child2>
    <hr>

    <!-- v-model和.sync实现双向数据同步的区别
    其实都可以实现相同的效果
    只是约定成俗:
        如果是和表单类元素相关的使用v-model(子组件内部有input标签)
        如果没有表单类元素,那么使用.sync
    -->
  </div>
</template>

<script type="text/ecmascript-6">
  import Child from './Child.vue'
  import Child2 from './Child2.vue'
  export default {
    name: 'SyncTest',
    data(){
      return {
        money:1000
      }
    },  
    components: {
      Child,
      Child2
    }
  }
</script>

 child

<template>
  <div style="background: #ccc; height: 50px;">
    <span>小明每次花100元</span>
    <button @click="$emit('update:money',money-100)">花钱</button>
    爸爸还剩 {{money}} 元
  </div>
</template>

<script type="text/ecmascript-6">
  export default {
    name: 'Child',
    props:['money']
  }
</script>

child2

<template>
  <div style="background: #ccc; height: 50px;">
    <span>小明每次花100元</span>
    <button @click="$emit('input',value - 100)">花钱</button>
    爸爸还剩 {{value}} 元
  </div>
</template>

<script type="text/ecmascript-6">
  export default {
    name: 'Child2',
    props:['value']
  }
</script>

第六种:$attrs和$linsteners

$attrs是一个对象,里面包含了父组件传递的所有属性,但是不包含props接收的属性以及和样式相关的属性

$listeners是一个对象,里面包含了父组件给子组件绑定的所有事件监听

本质就是父组件中给 子组件传递的所有属性组成的对象及自定义事件方法组成的对象

$attrs 如果不声明props 那么子组件当中是可以看到
          如果声明了哪个属性,那么那个属性在$attrs当中看不到
          它会排除 props声明接收的属性 以及class style

可以通过v-bind 一次性把父组件传递过来的属性添加给子组件
可以通过v-on   一次性把父组件传递过来的事件监听添加给子组件

对一个组件进行二次封装

    element-ui的button添加click事件会触发,添加dblclick就不会触发的问题        
    element-ui的button  子组件内部触发了这个单击事件
    element-ui的button  子组件内部没有触发这个双击事件

    扩展双击点击触发element-ui button事件,使用原生.native

 第七种:$parent 和 $children以及$refs

    $children:所有子组件对象的数组
    $parent:代表父组件对象
    ref用在html标签身上,是用来获取真实dom元素,用在组件标签身上,获取的是组件对象

    父组件当中可以通过$children找到所有的子组件去操作子组件的数据(当然可以找孙子组件)
不过$children拿到所有子组件数组内部顺序不定
    子组件当中可以通过$parent找到父组件(当然可以继续找爷爷组件)操作父组件的数据,
如果父组件有多个,没反应  
    $parent 和 $children用的时候注意(会出问题) 

扩展: 多个组件有部分相同的js代码

    html js  css 相同     封装组件

    单个组件js代码重复    封装函数

    不同的组件js代码重复  封装模块 (混入mixin)  


    实现组件之间js代码的复用  利用vue的mixin技术   参考官网

    比如多个组件的methods里面很多函数都是重复的 那么我们可以定义单独的模块去把这些相同的代码定义到外部    
    export const xxxMixin = {

        methods:{
            重复的代码写在这            
        }

    }

第八种:作用域插槽 

    适用:父子之间
    数据是在父组件当中的,数据是要给子组件去展示的(vfor)
    展示的过程当中,数据的结构 子组件说了不算,是由父组件决定的
    
    父组件要把需要子组件展示的数据传递给子组件
    子组件在展示的过程当中,如果需要额外的结构和样式,子组件说了不算,由父组件说了算,需要改变结构的数据传回给父组件,父组件再把结果和数据一并传回给子组件

第九种:vuex

    5个核心概念
    state   //共享状态数据,state的数据在每次打开项目和刷新项目的时候都要重新初始化
    mutations 直接修改state当中的数据
    actions // 提交mutations修改数据   响应组件dispacth异步发送请求
    getters  等价于组件内部的computed的getter
    modules //vuex的模块化开发  影响的是state 

第十种:消息的订阅和发布  pubsub-js

    PubSubJS是一个第三方包,本质引入是一个对象
    PubSub.publish()  方法是用来发布消息的    
    PubSub.subscribe() 方法是用来订阅消息的


    由于是第三方包使用的时候不需要在main当中注册

    在接收数据的组件当中,通过PubSub.subscribe(消息名,回调函数)去订阅消息,回调函数就留在当前组件

    在发送数据的组件当中,通过PubSub.publish(消息名,数据)去发布消息,可以调用函数传递数据

    它和全局事件总线用法很相似,有一个很大的区别: 回调函数的第一个形参
        全局事件总线事件回调的第一个参数就是我们传递的数据
        消息的订阅发布,回调的第一个参数是消息名,即使不用也要占位,第二个参数才是我们传递的数据

 

Vue2处理响应式数据

    Vue2在做响应式数据的时候针对的就是两种数据:对象  数组

    数组:响应式是通过7个重写的方法去实现的,只要是数组数据用这7个方法,数据一定是响应式的
    数组如果直接通过下标去操作,不是响应式

    对象:响应式是通过(数据代理)数据劫持,数据劫持做了两件事
        1、给data当中所有的属性,递归生成dep
        2、修改data当中所有的属性,为响应式属性,通过Object.defineProperty给每个属性添加get和set方法

        当访问this.xxx 访问的是vm.xxx 会触发vm身上的xxx get方法,它会最终返回data当中的同名属性值,
        要返回data当中同名属性值,就会触发data当中同名属性的get方法,最终读取data同名属性值进行返回

 
        当修改this.xxx 修改的是vm.xxx 会触发vm身上的xxx set方法,最终修改的是data当中的同名属性值,
        要修改data当中同名属性值,就会触发data当中同名属性的set方法

        在set方法当中做了以下三件事:
            1)判断新值和旧值是否相同,相同return 不相同更新
            2) 如果修改的新值又是一个对象,会递归给修改的新值也进行响应式处理
            3)通知让页面根据新数据进行更新


    补充:初始化的data数据一定是响应式,更新的data当中属性新数据也是一定响应式
    问 如果是后期(页面挂载完,点击按钮触发事件),给data当中添加属性,那么这个新添加的属性是不是响应式的属性数据?
    答:不是
    怎么办? $set
 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值