千锋教育-做有情怀、有良心、有品质的职业教育机构

400-811-9990
手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

上海
  • 北京
  • 郑州
  • 武汉
  • 成都
  • 西安
  • 沈阳
  • 广州
  • 南京
  • 深圳
  • 大连
  • 青岛
  • 杭州
  • 重庆
当前位置:太原千锋IT培训  >  技术干货  >  Vue中常见的组件间通信方案及典型应用场景

Vue中常见的组件间通信方案及典型应用场景

来源:千锋教育
发布人:qyf
时间: 2023-01-31 17:45:05

  什么是组件通信

  所谓组件通信,就是组件之间的数据交互,也就是把一个组件A里面的数据传递到另一个组件B,并能够让组件B根据这个数据更新界面。

  在 Vue中,可用的通信方案有很多,下面给大家描述几个常用的组件通信方案及其典型的应用场景。

  1、父子组件通信场景

  父子组件通信是最典型的组件通信场景,没有之一,他们之间通信主要使用自定义属性或者ref。

  第一种是自定义属性,使用较为广泛,在子组件中使用 props 选项进行接收,子组件向父组件回传数据,使用自定义事件,在子组件中使用 $emit() 方法触发执行,并回传数据给父组件。

  // 定义组件h1-box

  Vue.component("h1-box", {

  // 通过props设置自定义属性title接收组件外传值

  props: ["title"],

  // 通过emits设置自定义事件向外部发送事件

  emits: ['give'],

  methods:{

  clickHandler(){

  // 通过$emit() 方法触发执行把当前组件数据带出去

  this.$emit('give',{name:'lucy'})

  }

  },

  mounted() {

  // 通过this.title可以获取外部传入组件的值

  console.log(this.title);

  },

  });

  第二种使用 ref 实现通信。我们知道,使用 ref 可以快速访问一个组件实例对象及其内部的数据和方法。这样的话,在父组件中借助 $refs 可以访问子级组件的数据,还可以借助 $refs 调用子级组件中的方法,并传递事件参数给子级组件。当然需要注意的是,在 Vue开发中,应该尽量减少对 ref 的使用。

<div id="app">

  <!-- 组件 -->

  <son ref="son"></son>

</div>

new Vue({

  el: "#app",

  mounted() {

    // 获取到组件实例,就可以任意操作组件实例

    console.log(this.$refs.son);

    let vm2 = this.$refs.son;

    // 修改son组件的响应式数据msg

    vm2.msg = "sz2111";

    // 调用son组件的changeMsg方法

    vm2.changeMsg("sz2116");

  },

  components: {

    // 定义组件son

    son: {

      data() {

        return {

          msg: "sz2114",

        };

      },

      methods: {

        changeMsg(val) {

          this.msg = val;

        },

      },

      template: `<h1>hello world</h1>`,

    },

  },

});

  2、兄弟组件通信场景

  这种场景使用状态提升,这个概念源自 React 中的状态提升思想。

  所谓状态提升,就是当两个组件希望共享一个数据时,我们可以找到这两个组件最近的父级组件,把这个要被共享的变量定义在最近的父组件中去,再通过 props 向下传递给子组件们。需要注意的是,状态提升适合应用在简单的兄弟组件之间通信。当遇到较为复杂的组件关系时,使用状态提升就显得麻烦了。

图片 1

  上图图中如果想点击Font按钮改变主题字体大小,也就是Title和Font两个组件字体大小都改变。

  如果Title和Font组件都维护自己组件的状态数据就不太好传递数据,就可以他他们的状态存储到共同的父组件状态中,也就是状态提升。

  <!-- 父组件app -->

  <div id="app">

    <!-- 子组件font -->

    <font :font="fontSize"></font>

    <!-- 子组件title -->

    <title :font="fontSize"></title>

  </div>

  // 父组件

  new Vue({

    el:'#app',

    data:{

      // 把子组件共同需要的数据存储在共同的父组件上

      fontSize:12

    }

  })

  // 子组件

  Vue.component('font',{

    // 通过自定义属性接受父组件传入的值

    props:['font'],

    template:`<div :style="{fontSize:font+'px'}">hello</div>`

  })

  // 子组件

  Vue.component('title',{

    // 通过自定义属性接受父组件传入的值

    props:['font'],

    template:`<div :style="{fontSize:font+'px'}">world</div>`

  })

  3、根组件和后代组件通信场景

  这种场景主要是provide/inject。使用 provide 选项,可以在任意组件中注入数据;使用 inject 选项,可以在后代组件中接受父级组件注入的数据。需要注意的是,provide/inject 这种通信方案是没有响应式的,即父组件注入的数据发生变化时,后代组件不会自动更新

图片 2

  上图在祖先组件通过provide传入的数据,在后代的所有组件中都可以通过inject获取到。

  下面是一个通过provide/inject传值的例子

 <div id="app">

    <three></three>

  </div>

 // 根组件

  new Vue({

    el: "#app",

    // provide用于在一个vue实例里面给后面的子孙实例传递数据

    provide: function () {

      return {

        a: 100,

        c: 300,

        d: this.obj,

      };

    }

  });

  // 定义组件one

  Vue.component("one", {

    // inject用于在子孙组件中接收祖先通过provide传入的变量c

    inject: ["a"],

    template: `

      <div>

        <h1>我是one组件---{{a}}</h1>

      </div>

    `,

  });

  // 定义组件two,里面有子组件one

  Vue.component("two", {

    // inject用于在子孙组件中接收祖先通过provide传入的变量c,并重名成myC

    inject: {

      myC: "c",

    },

    template: `

      <div>

        <h1>我是two组件---{{myC}}</h1>

        <one></one>

      </div>

    `,

  });

  // 定义组件three,里面有子组件two

  Vue.component("three", {

    // inject用于在子孙组件中接收祖先通过provide传入的变量b,并重名成bbb,同时设置默认值299999

    inject: {

      bbb: {

        from: "b",

        default: 299999,

      },

    },

    template: `

      <div>

        <h1>我是three组件---{{bbb}}</h1>

        <two></two>

      </div>

    `,

  });

  4、插槽通信场景

  在封装组件时,可以为组件添加自定义属性。使用这个组件时,在父级组件中使用 #slotName='scope' 指令可以接收到子组件插槽传递过来的数据。ElementUI 中的 Table 表格、VantUI 中的 Tabbar 组件,都用到了插槽通信。

  <div id="app">

    <child>

      <template #abc>

        <h1>sz2114</h1>

        <h2>sz2115</h2>

        <h3>sz2116</h3>

      </template>

      <template #cindy>

        <h1>sz2014</h1>

        <h2>sz2015</h2>

        <h3>sz2016</h3>

      </template>

    </child>

  </div>

  // 全局组件

  Vue.component("child", {

    template: `

        <div>

            <slot name='cindy'></slot>

            <h1>hello world</h1>

            <slot name='abc'></slot>

        </div>

    `,

  });

  let vm = new Vue({

    el: "#app",

  });

  5 无直接关系的组件通信场景

  在没有直接关联的组件之间通信可以使用事件总线。事件总线是一种基于订阅发布模式而设计的通信方案,在任意组件中订阅指定“频道”后,都能收到该“频道”上的消息。事件总线,它的强大之处在于:它是一种“一对多”的通信方案,还是一种“多频道”的通信方案,非常强大。

    <div id="app">

      <input type="text" v-model="duanxin1" />

      <button @click="clickHandler">给老师发消息</button>

    </div>

      // 中央事件总线: 类似一个事件对象

      // 就像一个电信局

      var bus = new Vue();

 

      // 每个人就收短信都需要一个号码 (事件名)

      // 想要接收短信要先去电信办个卡 -- 注册一个号码

      bus.$on("cyrevent", function (data) {

        console.log("短信内容是");

        console.log(data);

      });

 

      new Vue({

        el: "#app",

        data() {

          return {

            duanxin1: "",

          };

        },

        methods: {

          clickHandler() {

            // 别人想给我发消息

            bus.$emit("cyrevent", this.duanxin1);

          },

        },

      });

  6 大型项目中的复杂组件通信场景 - Vuex状态管理

  Vuex状态管理是借助状态管理工具,可以实现任意组件之间的数据通信。Vuex 提供了 state、mutations 等接口,可以方便地实现任意未知关系的组件之间的数据交互。因此,我们经常称 Vuex是 Vue开发中的终极通信方案。终极的意思,不是说它可以随意地替代其它通信方案,而是说 Vuex很好用,能够清晰地管理数据流。

图片 3

  7 其他的一些组件通信方案

  上面说到的是比较常用的组件通信方式,还有一些方式是上面通信方法不能使用的替代手段 第一个是:$parent/$children,借助这两个 API,可以实现在组件树之间任意穿梭。我们在当前组件的作用域中,可以访问到任意其它组件的内部数据,并调用它的方法。因此,这也是一种可用的通信方案。

  第二个是:$attrs/$listeners。使用 $attrs 可以访问到父组件传递过来的自定义属性(除 class 和 style 外),使用 $listeners 可以访问并调用父组件传递过来的自定义事件,通过对自定义事件的调用还能向父组件回传数据。这两个内置 API,在某种程度上可以看成是父子组件通信的替代方案。

  总结:虽然 Vue中可用的通信方案很多,但要注意的是“别滥用”。在同一个项目中,选择适合场景的通信方案很重要,不要使用过多的通信方式,这会导致代码很难维护。一个数据流不清晰的 Web应用,通常是很难得到持续发展的。

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。

猜你喜欢LIKE

React的遮羞布

2023-01-31

Local Storage的高阶用法

2023-01-31

javascript中如何将伪数组转换成真数组

2023-01-30

最新文章NEW

变量的预解析

2023-01-31

Vue中常见的组件间通信方案及典型应用场景

2023-01-31

VueJS中的动画菜单效果的实现

2023-01-31

相关推荐HOT

更多>>

快速通道 更多>>

最新开班信息 更多>>

网友热搜 更多>>