美文网首页
vue2.0中的组件通信:v-model、作用域插槽、事件总线等

vue2.0中的组件通信:v-model、作用域插槽、事件总线等

作者: 李向_c52d | 来源:发表于2018-11-28 22:52 被阅读0次

    前言

    一篇小总结,组件间的通信问题,把v-model、作用域插槽也归入了。

    通信场景

    1. 父传子
    2. 子传父
    3. 父子同步
    4. 非父子

    父传子

    父传子也可以分为两种情况

    1. 传数据:props
    2. 传html:slot

    传数据

    这个是最基本的一般就是父组件用v-bind动态赋值,props在子组件内相当于在子组件内新建了一个data,props可以为字符串数组,也可以是对象,为对象时则可以设置类型检查和默认值,如果想在子组件更改传进来的数据可以通过data引用或计算属性来转换。

    传html

    也就是插槽,基础的html标签中是可以写html或字符的,而在如果自定义组件标签内写,就会--什么都不会发生。因为在子组件内没有定义插槽,如果在子组件内有slot,则传入的内容就会显示在插槽处。传的多的话就要有name来区分
    例子

    -----子组件---------
    <template>
      <div class="child">
        <p>这是子组件</p>
        <slot name='first'>我是默认内容</slot>
        <slot name='second'>我是默认内容</slot>
        <slot name='third'>我是默认内容</slot>
      </div>
    </template>
    
    ---------父组件-----------
    <template>
      <div class="parent">
       <my-child>
         <p slot='first'>我在父组件写但是在子组件显示</p>
         <template slot="second">
           <h1>我是父组件写的标题</h1>
           <p>我是父组件写的文章</p>
         </template>
         <h1 slot='third'>标题是{{title}}</h1>
         </my-child>
       <p>这是父组件</p>
      </div>
    </template>
    

    渲染结果


    父传子html

    总之就是花样传进去html,更复杂的作用域插槽在子传父写

    子传父

    这个都是传数据,方法有以下几种

    1. 通过事件向父组件发送消息
    2. 作用域插槽

    事件传信

    在父组件的子组件标签上监听事件,就像监听一个click一样,监听一个自定义事件,而这个事件的触发却在子组件内,例子,子组件的按钮会发出事件信号add,在父组件中的子组件标签上注册监听,监听到则触发。

    ----------------子组件--------
     <p>这是子组件</p>
        <button @click="$emit('add')">子组件</button>
    ----------------父组件-------------
    <my-child v-on:add ='count += 1'></my-child >
         <p>{{count}}</p>
       <p>这是父组件</p>
    
    事件
    根据上面的例子进一步,$emit的第二个参数可以通过事件传值,在父组件中通过访问$event接收 例子这样就是点一下加3了。如果事件是函数那值会称为函数的第一个参数,无需$event
    ----------------子组件--------
     <p>这是子组件</p>
        <button @click="$emit('add',3)">子组件</button>
    ----------------父组件-------------
    <my-child v-on:add ='count += $event'></my-child >
         <p>{{count}}</p>
       <p>这是父组件</p>
    

    作用域插槽

    这个作用域插槽是勉强可以放到子向父传数据,虽然还是要还给子组件,上面插槽可知,子组件内部的slot在父组件未向其传内容时是不显示或显示默认内容的,但是如果父组件指向向子组件传递html和css但是内容却由子组件自己提供呢?在父组件内不管{{}}写到哪,它能访问的都是父组件的作用域,现在我们需要在父组件的子标签内访问子标签的作用域

    ---------------------子组件-------------------------
    <template>
      <div class="child">
        <p>这是子组件</p>
        <slot :data='data'> </slot>
      </div>
    </template>
    
    <script>
      export default {
        data() {
          return {
            data: ['子数据1','子数据2']
          }
        },
      }
    </script>
    ----------------------父组件----------------------
    <template>
      <div class="parent">
       <my-child >
         <template slot-scope='scope'> // scope就是个名字代表着子组件作用域
           {{scope.data}}
         </template>
         </my-child >
       <p>这是父组件</p>
      </div>
    </template>
    

    子组件内slot通过bind绑定data,在父组件内给它取个名叫scope,slot-scope='scope'就可以访问了。懒得起名就用解构赋值slot-scope={data}

    父子同步

    也就是prop的双向绑定,单向数据流不可能双向绑定的,但是通过父通过props传子,子通过$emit传父,父在传回来可以实现同步

    -----------------子组件-------------------------
    <div class="child">
        <p>这是子组件</p>
        <button @click="$emit('update:title',childTitle)">更新标题</button>
        <p>{{title}}</p>
      </div>
    -----------------父组件---------------------
    <div class="parent">
       <my-child :title="title" v-on:update:title='title = $event'></my-child >
       <p>这是父组件</p>
      </div>
    
    简写
     <my-child :title.sync="title"></my-child >
    

    v-model

    v-model也是一个意思,一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。默认传递value进去又默认监听input事件,且监听后将传过来的值赋给value。

    <input
                    type="text"
                    v-model="something">
            <!--等价于-->
            <input
                    type="text"
                    v-bind:value="something"
                    v-on:input="something = $event.target.value">
    

    非父子

    也就是同级组件或孙子组件之类的,一种方法是用一个空的vue实例当作中央事件总线,当作中介。组件通过emit传递,总线通过on监听事件来接受,很好理解。
    一种就是使用vuex。虽然官方推荐项目比较大时才使用,但是vuex语法简单,可以塞异步方法进去,配合调试工具数据流清晰。不管大小直接就用。

    相关文章

      网友评论

          本文标题:vue2.0中的组件通信:v-model、作用域插槽、事件总线等

          本文链接:https://www.haomeiwen.com/subject/dribfqtx.html