精华内容
下载资源
问答
  • Vue组件间通信方式(详解)
    2021-09-28 10:36:44

    1. 组件之间的传值通信

    组件之间通讯分为三种: 父传子、子传父、兄弟组件之间的通讯

    (1)props/$emit

    • 父传子:父组件通过import引入子组件,并注册,在子组件标签上添加要传递的属性,子组 件通过props接收,接收有两种形式一是通过数组形式[‘要接收的属性’ ],二是通过对象形式{ }
    • 子传父:父组件向子组件传递事件方法,子组件通过$emit触发事件,回调给父组件

     

    1.父组件向子组件传值

    接下来我们通过一个例子,说明父组件如何向子组件传递值:在子组件Users.vue中如何获取父组件App.vue中的数据 users:["Henry","Bucky","Emily"]

    
    //App.vue父组件
    <template>
      <div id="app">
        <users v-bind:users="users"></users>//前者自定义名称便于子组件调用,后者要传递数据名
      </div>
    </template>
    <script>
    import Users from "./components/Users"
    export default {
      name: 'App',
      data(){
        return{
          users:["Henry","Bucky","Emily"]
        }
      },
      components:{
        "users":Users
      }
    }
    //users子组件
    <template>
      <div class="hello">
        <ul>
          <li v-for="user in users">{{user}}</li>//遍历传递过来的值,然后呈现到页面
        </ul>
      </div>
    </template>
    <script>
    export default {
      name: 'HelloWorld',
      props:{
        users:{           //这个就是父组件中子标签自定义名字
          type:Array,
          required:true
        }
      }
    }
    </script>

    总结:父组件通过props向下传递数据给子组件。注:组件中的数据共有三种形式:data、props、computed

    2.子组件向父组件传值(通过事件形式)

    接下来我们通过一个例子,说明子组件如何向父组件传递值:当我们点击“Vue.js Demo”后,子组件向父组件传递值,文字由原来的“传递的是一个值”变成“子向父组件传值”,实现子组件向父组件值的传递。

    // 子组件
    <template>
      <header>
        <h1 @click="changeTitle">{{title}}</h1>//绑定一个点击事件
      </header>
    </template>
    <script>
    export default {
      name: 'app-header',
      data() {
        return {
          title:"Vue.js Demo"
        }
      },
      methods:{
        changeTitle() {
          this.$emit("titleChanged","子向父组件传值");//自定义事件  传递值“子向父组件传值”
        }
      }
    }
    </script>
    // 父组件
    <template>
      <div id="app">
        <app-header v-on:titleChanged="updateTitle" ></app-header>//与子组件titleChanged自定义事件保持一致
       // updateTitle($event)接受传递过来的文字
        <h2>{{title}}</h2>
      </div>
    </template>
    <script>
    import Header from "./components/Header"
    export default {
      name: 'App',
      data(){
        return{
          title:"传递的是一个值"
        }
      },
      methods:{
        updateTitle(e){   //声明这个函数
          this.title = e;
        }
      },
      components:{
       "app-header":Header,
      }
    }
    </script>

    总结:子组件通过events给父组件发送消息,实际上就是子组件把自己的数据发送到父组件。

    (2)$eimt/$on

    • 这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。当我们的项目比较大时,可以选择更好的状态管理解决方案vuex。。

     具体实现方式:

      var Event=new Vue();
       Event.$emit(事件名,数据);
       Event.$on(事件名,data => {});
    // 假设兄弟组件有三个,分别是A、B、C组件,C组件如何获取A或者B组件的数据
    // 组件A、B通过Event.$emit(事件名,数据)将数据传递,组件C通过 Event.$on(事件名,data => {})接受

    (3) $parent / $children与 ref

    • ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
    • $parent / $children:访问父 / 子实例
    • 需要注意的是:这两种都是直接得到组件实例,使用后可以直接调用组件的方法或访问数据。
    • $parent :访问父实例,如果当前实例有的话。
    • $children:当前实例的直接子组件。需要注意 $children并不保证顺序,也不是响应式的。如果你发现自己正在尝试使用 $children来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源。
    • 这两种方法的弊端是,无法在跨级或兄弟间通信。
    // component-a 子组件
    export default {
     data () {
       return {
         title: 'Vue.js'
       }
     },
     methods: {
       sayHello () {
         window.alert('Hello');
       }
     }
    }
    /***********************************/
    // 父组件
    <template>
     <component-a ref="comA"></component-a>
    </template>
    <script>
     export default {
       mounted () {
         const comA = this.$refs.comA;
         console.log(comA.title);  // Vue.js
         comA.sayHello();  // 弹窗
       }
     }
    </script>

    (4)provide/inject

    • provide/inject:vue2.2.0 新增API,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
    • 总而言之:祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。
    • provide / inject API主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。

    // A.vue
    export default {
     provide: {
       name: 'nora'
     }
    }
    /**************************************/
    // B.vue
    export default {
     inject: ['name'],
     mounted () {
       console.log(this.name);  // nora
     }
    }
    
    • 需要注意的是:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的----vue官方文档
      provide与inject 怎么实现数据响应式?
      使用2.6最新API Vue.observable 优化响应式 provide(推荐)

    • 我们来看个例子:孙组件D、E和F获取A组件传递过来的color值,并能实现数据响应式变化,即A组件的color变化后,组件D、E、F会跟着变(核心代码如下:)

    //A组件
    <div>
         <h1>A 组件</h1>
         <button @click="() => changeColor()">改变color</button>
         <ChildrenB />
         <ChildrenC />
    </div>
    ......
    // provide() {
     //   return {
     //     theme: {
     //       color: this.color //这种方式绑定的数据并不是可响应的
     //     } // 即A组件的color变化后,组件D、E、F不会跟着变
     //   };
     // },
    
    // 方法二:使用2.6最新API Vue.observable 优化响应式 provide
    provide() {
       this.theme = Vue.observable({
          color: "blue"
        });
        return {
          theme: this.theme
        };
      },
      methods: {
        changeColor(color) {
          if (color) {
            this.theme.color = color;
          } else {
            this.theme.color = this.theme.color === "blue" ? "red" : "blue";
          }
        }
      }
    /******************************************************************/
    // F 组件 
    <template functional>
     <div class="border2">
       <h3 :style="{ color: injections.theme.color }">F 组件</h3>
     </div>
    </template>
    <script>
    export default {
     inject: {
       theme: {
         //函数式组件取值不一样
         default: () => ({})
       }
     }
    };
    </script>

    详解原文请看:https://segmentfault.com/a/1190000019208626

    更多相关内容
  • 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。这篇文章主要介绍了vue组件间通信六种方式,需要的朋友可以参考下
  • 主要介绍了vue组件之间通信方式,结合实例形式总结分析了vue.js的8种组件通信方式与相关操作注意事项,需要的朋友可以参考下
  • 一、组件通信的概念开始之前,我们把组件通信这个词进行拆分组件通信都知道组件是vue最强大的功能之一,vue中每一个.vue我们都可以视之为一个组件通信指的是发送者通过某种媒体以某种格...

    一、组件间通信的概念

    开始之前,我们把组件间通信这个词进行拆分

    • 组件

    • 通信

    都知道组件是vue最强大的功能之一,vue中每一个.vue我们都可以视之为一个组件

    通信指的是发送者通过某种媒体以某种格式来传递信息到收信者以达到某个目的。广义上,任何信息的交通都是通信

    组件间通信即指组件(.vue)通过某种方式来传递信息以达到某个目的

    举个栗子

    我们在使用UI框架中的table组件,可能会往table组件中传入某些数据,这个本质就形成了组件之间的通信

    二、组件间通信解决了什么

    在古代,人们通过驿站、飞鸽传书、烽火报警、符号、语言、眼神、触碰等方式进行信息传递,到了今天,随着科技水平的飞速发展,通信基本完全利用有线或无线电完成,相继出现了有线电话、固定电话、无线电话、手机、互联网甚至视频电话等各种通信方式

    从上面这段话,我们可以看到通信的本质是信息同步,共享

    回到vue中,每个组件之间的都有独自的作用域,组件间的数据是无法共享的

    但实际开发工作中我们常常需要让组件之间共享数据,这也是组件通信的目的

    要让它们互相之间能进行通讯,这样才能构成一个有机的完整系统

    二、组件间通信的分类

    组件间通信的分类可以分成以下

    • 父子组件之间的通信

    • 兄弟组件之间的通信

    • 祖孙与后代组件之间的通信

    • 非关系组件间之间的通信

    关系图:

    三、组件间通信的方案

    整理vue中8种常规的通信方案

    1. 通过 props 传递

    2. 通过 $emit 触发自定义事件

    3. 使用 ref

    4. EventBus

    5. root

    6. attrs 与 listeners

    7. Provide 与 Inject

    8. Vuex

    props传递数据

    • 适用场景:父组件传递数据给子组件

    • 子组件设置props属性,定义接收父组件传递过来的参数

    • 父组件在使用子组件标签中通过字面量来传递值

    Children.vue

    props:{
        // 字符串形式
     name:String // 接收的类型参数
        // 对象形式
        age:{  
            type:Number, // 接收的类型为数值
            defaule:18,  // 默认值为18
           require:true // age属性必须传递
        }
    }
    

    Father.vue组件

    <Children name:"jack" age=18 />
    

    $emit 触发自定义事件

    • 适用场景:子组件传递数据给父组件

    • 子组件通过$emit触发自定义事件,$emit第二个参数为传递的数值

    • 父组件绑定监听器获取到子组件传递过来的参数

    Chilfen.vue

    this.$emit('add', good)
    

    Father.vue

    <Children @add="cartAdd($event)" />
    

    ref

    • 父组件在使用子组件的时候设置ref

    • 父组件通过设置子组件ref来获取数据

    父组件

    <Children ref="foo" />
    
    this.$refs.foo  // 获取子组件实例,通过子组件实例我们就能拿到对应的数据
    

    EventBus

    • 使用场景:兄弟组件传值

    • 创建一个中央时间总线EventBus

    • 兄弟组件通过$emit触发自定义事件,$emit第二个参数为传递的数值

    • 另一个兄弟组件通过$on监听自定义事件

    Bus.js

    // 创建一个中央时间总线类
    class Bus {
      constructor() {
        this.callbacks = {};   // 存放事件的名字
      }
      $on(name, fn) {
        this.callbacks[name] = this.callbacks[name] || [];
        this.callbacks[name].push(fn);
      }
      $emit(name, args) {
        if (this.callbacks[name]) {
          this.callbacks[name].forEach((cb) => cb(args));
        }
      }
    }
    
    // main.js
    Vue.prototype.$bus = new Bus() // 将$bus挂载到vue实例的原型上
    // 另一种方式
    Vue.prototype.$bus = new Vue() // Vue已经实现了Bus的功能
    

    Children1.vue

    this.$bus.$emit('foo')
    

    Children2.vue

    this.$bus.$on('foo', this.handle)
    

     root

    • 通过共同祖辈$parent或者$root搭建通信侨联

    兄弟组件

    this.$parent.on('add',this.add)
    

    另一个兄弟组件

    this.$parent.emit('add')
    

    listeners

    • 适用场景:祖先传递数据给子孙

    • 设置批量向下传属性$attrs$listeners

    • 包含了父级作用域中不作为 prop 被识别 (且获取) 的特性绑定 ( class 和 style 除外)。

    • 可以通过 v-bind="$attrs" 传⼊内部组件

    // child:并未在props中声明foo
    <p>{{$attrs.foo}}</p>
    
    // parent
    <HelloWorld foo="foo"/>
    
    // 给Grandson隔代传值,communication/index.vue
    <Child2 msg="lalala" @some-event="onSomeEvent"></Child2>
    
    // Child2做展开
    <Grandson v-bind="$attrs" v-on="$listeners"></Grandson>
    
    // Grandson使⽤
    <div @click="$emit('some-event', 'msg from grandson')">
    {{msg}}
    </div>
    

    provide 与 inject

    • 在祖先组件定义provide属性,返回传递的值

    • 在后代组件通过inject接收组件传递过来的值

    祖先组件

    provide(){
        return {
            foo:'foo'
        }
    }
    

    后代组件

    inject:['foo'] // 获取到祖先组件传递过来的值
    

    vuex

    • 适用场景: 复杂关系的组件数据传递

    • Vuex作用相当于一个用来存储共享变量的容器

    • state用来存放共享变量的地方

    • getter,可以增加一个getter派生状态,(相当于store中的计算属性),用来获得共享变量的值

    • mutations用来存放修改state的方法。

    • actions也是用来存放修改state的方法,不过action是在mutations的基础上进行。常用来做一些异步操作

    小结

    • 父子关系的组件数据传递选择 props  与 $emit进行传递,也可选择ref

    • 兄弟关系的组件数据传递可选择$bus,其次可以选择$parent进行传递

    • 祖先与后代组件数据传递可选择attrslisteners或者 ProvideInject

    • 复杂关系的组件数据传递可以通过vuex存放共享的变量

    参考文献

    • https://juejin.cn/post/6844903990052782094#heading-0

    • https://zh.wikipedia.org/wiki/%E9%80%9A%E4%BF%A1

    • https://vue3js.cn/docs/zh

    面试官VUE系列总进度:5/33

    面试官:说说你对vue的理解?

    面试官:说说你对SPA(单页应用)的理解?

    面试官:说说你对双向绑定的理解?

    面试官:说说你对Vue生命周期的理解?

    展开全文
  • vue可以是要组件复用的,而组件实例的作用域是相互独立,这意味着不同组件之间的数据无法互相引用 一般来说,组件之间可以有几种关系:A 和 B、B 和 C、B 和 D 都是父子关系,C 和 D 是兄弟关系,A 和 C 是隔代...

    引入

    用vue可以是要组件复用的,而组件实例的作用域是相互独立,这意味着不同组件之间的数据无法互相引用
    一般来说,组件之间可以有几种关系:
    请添加图片描述
    如上图所示,A 和 B、B 和 C、B 和 D 都是父子关系,C 和 D 是兄弟关系,A 和 C 是隔代关系(可能隔多代)。

    方法一:props/ $emit(父子间传递常用方式)

    父组件A通过props的方式向子组件B传递
    B向A通过在B组件中$emit,A组件中v-on的方式实现

    1. 父组件向子组件传值
    //App.vue父组件
    <template>
      <div id="app">
        <users v-bind:users="users"></users>//前者自定义名称便于子组件调用,后者要传递数据名
      </div>
    </template>
    <script>
    import Users from "./components/Users"
    export default {
      name: 'App',
      data(){
        return{
          users:["Henry","Bucky","Emily"]
        }
      },
      components:{
        "users":Users
      }
    }
    
    //users子组件
    <template>
      <div class="hello">
        <ul>
          <li v-for="user in users">{{user}}</li>//遍历传递过来的值,然后呈现到页面
        </ul>
      </div>
    </template>
    <script>
    export default {
      name: 'HelloWorld',
      props:{
        users:{           //这个就是父组件中子标签自定义名字
          type:Array,
          required:true
        }
      }
    }
    </script>
    

    方法二:子组件向父组件传值(通过事件形式)

    // 子组件
    <template>
      <header>
        <h1 @click="changeTitle">{{title}}</h1>//绑定一个点击事件
      </header>
    </template>
    <script>
    export default {
      name: 'app-header',
      data() {
        return {
          title:"Vue.js Demo"
        }
      },
      methods:{
        changeTitle() {
          this.$emit("titleChanged","子向父组件传值");//自定义事件  传递值“子向父组件传值”
        }
      }
    }
    </script>
    
    // 父组件
    <template>
      <div id="app">
        <app-header v-on:titleChanged="updateTitle" ></app-header>//与子组件titleChanged自定义事件保持一致
       // updateTitle($event)接受传递过来的文字
        <h2>{{title}}</h2>
      </div>
    </template>
    <script>
    import Header from "./components/Header"
    export default {
      name: 'App',
      data(){
        return{
          title:"传递的是一个值"
        }
      },
      methods:{
        updateTitle(e){   //声明这个函数
          this.title = e;
        }
      },
      components:{
       "app-header":Header,
      }
    }
    </script>
    

    方法三:$emit/ $on(巧妙的方式同族跨级通信)

    这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。当我们的项目比较大时,可以选择更好的状态管理解决方案vuex。

    <div id="itany">
        <my-a></my-a>
        <my-b></my-b>
        <my-c></my-c>
    </div>
    <template id="a">
      <div>
        <h3>A组件:{{name}}</h3>
        <button @click="send">将数据发送给C组件</button>
      </div>
    </template>
    <template id="b">
      <div>
        <h3>B组件:{{age}}</h3>
        <button @click="send">将数组发送给C组件</button>
      </div>
    </template>
    <template id="c">
      <div>
        <h3>C组件:{{name}}{{age}}</h3>
      </div>
    </template>
    <script>
    var Event = new Vue();//定义一个空的Vue实例
    var A = {
        template: '#a',
        data() {
          return {
            name: 'tom'
          }
        },
        methods: {
          send() {
            Event.$emit('data-a', this.name);
          }//发送name,给空的父组件,事件名叫data-a
        }
    }
    var B = {
        template: '#b',
        data() {
          return {
            age: 20
          }
        },
        methods: {
          send() {
            Event.$emit('data-b', this.age);
          }//发送age,给空的父组件,事件名叫data-b
        }
    }
    var C = {
        template: '#c',
        data() {
          return {
            name: '',
            age: ""
          }
        },
        mounted() {//在模板编译完成后执行
         Event.$on('data-a',name => {
             this.name = name;//箭头函数内部不会产生新的this,这边如果不用=>,this指代Event
         })//通过父组件传name值过来,通过$on来监听data-a事件
         Event.$on('data-b',age => {
             this.age = age;
         })//通过父组件传age值过来,通过$on来监听data-a事件
        }
    }
    var vm = new Vue({
        el: '#itany',
        components: {
          'my-a': A,
          'my-b': B,
          'my-c': C
        }//新建一个空的父组件,用来传递A、B的值给C(将ABC都设为这个父组件的子组件)
    });    
    </script>
    

    $on 监听了自定义事件 data-a和data-b,因为有时不确定何时会触发事件,一般会在 mounted 或 created 钩子中来监听。

    方法四:Vuex(跨级组件之间传递)

    请添加图片描述

    介绍一下Vuex原理

    Vuex实现了一个单向数据流,在全局拥有一个State存放数据,当组件要更改State中的数据时,必须通过Mutation进行,Mutation同时提供了订阅者模式供外部插件调用获取State数据的更新。而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走Action,但Action也是无法直接修改State的,还是需要通过Mutation来修改State的数据。最后,根据State的变化,渲染到视图上。

    简介各模块在流程中的功能

    • Vue Components:Vue组件。HTML页面上,负责接收用户操作等交互行为,执行dispatch方法触发对应action进行回应。
    • dispatch:操作行为触发方法,是唯一能执行action的方法。
    • actions:**操作行为处理模块,由组件中的$store.dispatch(‘action 名称’, data1)来触发。然后由commit()来触发mutation的调用 , 间接更新 state。**负责处理Vue Components接收到的所有交互行为。包含同步/异步操作,支持多个同名方法,按照注册的顺序依次触发。向后台API请求的操作就在这个模块中进行,包括触发其他action以及提交mutation的操作。该模块提供了Promise的封装,以支持action的链式触发。
    • commit:状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。
    • mutations:状态改变操作方法,由actions中的
    • commit(‘mutation 名称’)来触发。是Vuex修改state的唯一推荐方法。该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些hook暴露出来,以进行state的监控等。
    • state:页面状态管理容器对象。集中存储Vue components中data对象的零散数据,全局唯一,以进行统一的状态管理。页面显示所需的数据从该对象中进行读取,利用Vue的细粒度数据响应机制来进行高效的状态更新。
    • getters:state对象读取方法。图中没有单独列出该模块,应该被包含在了render中,Vue Components通过该方法读取全局state对象。

    Vuex与localStorage

    vuex 是 vue 的状态管理器,存储的数据是响应式的。但是并不会保存起来,刷新之后就回到了初始状态,具体做法应该在vuex里数据改变的时候把数据拷贝一份保存到localStorage里面,刷新之后,如果localStorage里有保存的数据,取出来再替换store里的state。

    let defaultCity = "武汉"
    try {   // 用户关闭了本地存储功能,此时在外层加个try...catch
      if (!defaultCity){
        defaultCity = JSON.parse(window.localStorage.getItem('defaultCity'))//在Vuex里保存的状态都是数组,而localStorage只支持字符串,所以需要用JSON转换
      }
    }catch(e){}
    export default new Vuex.Store({
      state: {
        city: defaultCity
      },
      mutations: {
        changeCity(state, city) {
          state.city = city
          try {
          window.localStorage.setItem('defaultCity', JSON.stringify(state.city));
          // 数据改变的时候把数据拷贝一份保存到localStorage里面
          } catch (e) {}
        }
      }
    })
    

    这里我没咋看懂,是一个比较高级的用法,大致意思是vue框架的内部是使用Vuex这种单向数据流,我们的数据可以借助Vue框架的数据流传递。
    主要是调用vue框架提供的API:actions,由组件中的$store.dispatch(‘action 名称’, data1)来触发,然后由commit()来触发mutation的调用 , 间接更新 state。
    这种方式常用于大型项目,和框架的数据流一起管理我们的数据,将数据放到store中,借助Vue的响应性渲染和单向数据流,将我们的数据跨级传输到其他组件,一般都是需要将数据做深层的处理才用的。

    方法五:$attrs/ $listeners(在同族跨级组件数据传输,比Vuex简单)

    多级组件嵌套需要传递数据时,通常使用的方法是通过vuex,但仅仅是传递数据,而不做中间处理,使用vuex处理就有点大材小用了。
    为此Vue2.4版本提供了另一种方法$$attrs/ l i s t n e r s listners listners

    • $attrs: 包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=" $attrs" 传入内部组件。通常配合 interitAttrs 选项一起使用。
    • $listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=" $listeners" 传入内部组件
    // index.vue
    <template>
      <div>
        <h2>albertos</h2>
        <child-com1
          :foo="foo"
          :boo="boo"
          :coo="coo"
          :doo="doo"
        ></child-com1>
      </div>
    </template>
    <script>
    const childCom1 = () => import("./childCom1.vue");
    export default {
      components: { childCom1 },
      data() {
        return {
          foo: "Javascript",
          boo: "Html",
          coo: "CSS",
          doo: "Vue"
        };
      }
    };
    </script>
    
    // childCom1.vue
    <template class="border">
      <div>
        <p>foo: {{ foo }}</p>
        <p>childCom1的$attrs: {{ $attrs }}</p>
        <child-com2 v-bind="$attrs"></child-com2>
      </div>
    </template>
    <script>
    const childCom2 = () => import("./childCom2.vue");
    export default {
      components: {
        childCom2
      },
      inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
      props: {
        foo: String // foo作为props属性绑定
      },
      created() {
        console.log(this.$attrs); // { "boo": "Html", "coo": "CSS", "doo": "Vue"}
      }
    };
    </script>
    
    // childCom2.vue
    <template>
      <div class="border">
        <p>boo: {{ boo }}</p>
        <p>childCom2: {{ $attrs }}</p>
        <child-com3 v-bind="$attrs"></child-com3>
      </div>
    </template>
    <script>
    const childCom3 = () => import("./childCom3.vue");
    export default {
      components: {
        childCom3
      },
      inheritAttrs: false,
      props: {
        boo: String
      },
      created() {
        console.log(this.$attrs); // {"coo": "CSS", "doo": "Vue" }
      }
    };
    </script>
    
    // childCom3.vue
    <template>
      <div class="border">
        <p>childCom3: {{ $attrs }}</p>
      </div>
    </template>
    <script>
    export default {
      props: {
        coo: String,
        title: String
      }
    };
    </script>
    

    方法六:provide/inject(新增的同族跨级传输API)

    • 这是vue2.2新增的API,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效
    • 祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。
    • provide / inject API主要解决了跨级组件间的通信问题,它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
    // 祖先.vue
    export default {
     provide: {
       name: 'albertos'
     }
    }
    /**************************************/
    // 子孙.vue
    export default {
     inject: ['name'],
     mounted () {
       console.log(this.name);  // albertos
     }
    }
    

    可以看到,在父组件里,我们设置了一个 provide: name,值为 albertos,它的作用就是将 name 这个变量提供给它的所有子组件。
    而在子孙中,通过 inject 注入了从 A父组件中提供的 name 变量,那么在子孙中,就可以直接通过 this.name 访问这个变量了,它的值也是albertos。这就是 provide / inject API 最核心的用法。
    provide/inject因为这个API不是响应式的,主要用于高阶插件和组件库,要实现响应式需要挂载很多没必要的东西

    方法七:$parent/ $children与ref(直接得到组件实例)

    • ref:如果在普通的DOM元素上使用,引用指向的就是DOM元素;如果用在子组件上,引用就指向组件实例
    • $parent/ $children: 访问父/子实例

    注: 这种方法是直接得到组件实例,用面向对象的方法来解释就像,创建一个指针对象将整个类对象映射到调用组件的对象中;使用后可以直接调用组件的方法或访问数据(这样用虽然方便,但是增加了对象之间的耦合度,项目大或者有后续的需求变化不建议使用)

    ref来访问组件:

    // component-a 子组件
    export default {
      data () {
        return {
          title: 'Vue.js'
        }
      },
      methods: {
        sayHello () {
          window.alert('Hello');
        }
      }
    }
    
    // 父组件
    <template>
      <component-a ref="comA"></component-a>
    </template>
    <script>
      export default {
        mounted () {
          const comA = this.$refs.comA;//拿到comA这个引用对象
          console.log(comA.title); 
          comA.sayHello();  // 调用comA中的方法
        }
      }
    </script>
    

    方法八: EventBus(针对安卓优化的发布/订阅事件总线)

    EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。
    请添加图片描述
    注:这是一个基于观察者模式的事件总线框架,对于一对多发消息来说方便很多,具体做法我没有看到在电脑端Vue框架中的具体应用,因为是针对安卓开发的框架,框架代码体积还是很小的,做手机端开发可以专门关注一下

    总结

    常见使用场景可以分为三类:

    • 父子通信:
    1. 父向子传递数据是通过 props,子向父是通过 events($ emit)
    2. 通过父链 / 子链也可以通信($ parent / $ children);
    3. ref 也可以访问组件实例;
    4. provide / inject API;
    5. $attrs/ $listeners
    • 兄弟通信:
    1. Bus
    2. Vuex
    • 跨级通信:
    1. Bus;
    2. Vuex;
    3. provide / inject API
    4. $attrs/ $listeners

    参考

    Vue组件间的通信六种方式
    我看的是这个大佬写的博客,我在博客里面加了一些自己的理解,例子很多也是大佬写的~互相学习

    Vuex的方法我后来在vue官方文档中看懂了,有视频讲解,Vue官方yyds 仙人指路☞

    Bus的方法是一个针对安卓开发的类库, 比Vuex的开销小,是一个观察者模式的总线框架,在一对多的情况下很合适
    EventBus 使用(全面分析,细节提醒)

    展开全文
  • 1.常用的父子组件通讯方式:props,emit 父组件传入属性,子组件通过props来接收,在子组件中就可以用this.xxx方式使用。 子组件通过$emit(事件名,参数)向外弹出一个自定义事件,在父组件中的属性监听事件,可以...

    1.常用的父子组件通讯方式:props,emit

    父组件传入属性,子组件通过props来接收,在子组件中就可以用this.xxx方式使用。

    子组件通过$emit(事件名,参数)向外弹出一个自定义事件,在父组件中的属性监听事件,可以获得子组件中传出来的值

    //	父组件
    <hello-world msg="hello world!" @confirm="handleConfirm"><hello-world>
    //	子组件
     props: {
        msg: {
          type: String,
          default: ''
        }
      },
      methods:{
      	handleEmitParent(){
      		this.$emit('confirm', list)
      	}
      }

    2.$parent,$children

    通过 $parent,$children 来访问组件实例,进而去获取 或者 改变父子组件的值。 (仅限于父子组件之间,不推荐使用,因为不利于维护,一旦组件层次发生了变化,就需要更改其中的层次关系)

    需要注意边界,最外层的#app 的$parent得到的是Vue实例,在Vue实例上再去取$parent 就是undefined了。 在最底层的组件中 $children是[]。

    3.$ref

    通过引用的方式获取子节点,常用于父组件中调用子组件的方法或者获取子组件的属性。

    注意:如果绑在的是v-for的节点上,那么获取到的是一个数组。

    4.provide/inject

    依赖注入,常见于插件或者组件库里。

    多个组件嵌套时,顶层组件provide提供变量,后代组件都可以通过inject来注入变量。

    缺陷:传递的数据不是响应式的,inject接收到数据后,provide中的数据改变,但是后代组件中的数据不会改变。所以 建议传一些常量或者方法。

    5.EventBus 事件总线 (任意两个组件通讯)

    用 $emit去监听,用$on去触发,注意需要$off来取消监听,否则可能会造成内存泄漏。

    6.$attrs、$listener

    适用于多级组件嵌套,但是不做中间处理的情况。比如祖先组件向孙子组件传递数据。

    $attrs 可以获取父组件传进来,但是没有用props接收的属性。

    可以通过v-bind="$attrs"传入内部组件。

    搭配inheritAttrs使用,这个只是用来控制attrs是否在DOM中渲染。

    $listeners 包含父作用域中的(不包含.native的) v-on时间监听器。

    可以通过v-on="$listeners"来传入内部组件。

    7.Vuex 状态管理器

    集中式存储管理所有组件的状态。

    可以解决 多个视图依赖同一个状态 或者是 来自不同视图的行为需要变更同一个状态 的问题。

    8.localStorage/sessionStorage

    持久化存储。

    展开全文
  • 主要介绍了八种Vue组件间通讯方式合集(推荐),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • Vue组件间通信方式都有哪些?

    千次阅读 2020-12-07 16:32:25
    组件间通信即指组件(.vue)通过某种方式来传递信息以达到某个目的 举个栗子 我们在使用UI框架中的table组件,可能会往table组件中传入某些数据,这个本质就形成了组件之间通信 二、组件间通信解决了什么 在古代...
  • vue组件间通信的6种方式

    千次阅读 2022-01-22 17:46:30
    除了使用vuex外还有下面6种组件通信方式: 1、 props / $emit 父组件通过 props 向子组件传递数据,子组件通过 $emit 和父组件通信 (1)父组件向子组件传值(props的用法) props的特点: props只能是父组件向...
  • 记得面试的时候,被问到这个,当时...2) 实现通信方式 props vue自定义事件 消息订阅与发布 vuex slot 3) 方式1: props 通过一般属性实现父向子通信 通过函数属性实现子向父通信 缺点: 隔代组件和兄弟组件间通信...
  • vue组件间通信六种方式(完整版)

    千次阅读 2021-08-31 20:28:42
      组件vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。一般来说,组件可以有以下几种关系:                如上图所示,A 和 B、B 和 C...
  • vue组件间通信六种方式

    千次阅读 2021-10-07 19:10:17
    前言 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据...本文总结了vue组件间通信的几种方式,如props、$emit/$on、vuex、$parent / $children、$attrs/$listeners和.
  • 主要介绍了Vue组件之间通信的七种方式,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
  • 主要介绍了vue 组件间通信之子组件向父组件传值的方式总结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
  • 组件间通信即指组件(.vue)通过某种方式来传递信息以达到某个目的 举个栗子 我们在使用UI框架中的table组件,可能会往table组件中传入某些数据,这个本质就形成了组件之间通信 二、组件间通信解决了什么 ..
  • (1)**props / $emit**适用 父子组件通信 这种方法是 Vue 组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。 (2)**ref**与**$parent / $children**适用 父子组件通信 ·ref:如果在普通的 DOM ...
  • 这是我看完硅谷Vue2的个人总结,希望能帮助到大家 组件的自定义事件(绑定) v-on:名称="" 表示为该组件的实例对象绑定了一个自定义事件 想要触发该事件,那就需要去找到实例对象 需要在孩子的methods当中, ...
  • Vue 组件间通信六种方式(完整版)

    万次阅读 多人点赞 2019-05-27 11:15:41
    前言 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。一般来说,组件可以有以下几种关系: ...本文总结了vue组件间通信的几种方式,如pr...
  • Vue组件通信的六种方式

    千次阅读 2022-02-02 11:32:59
    前言 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法...本文总结了vue组件间通信的几种方式,如props、$emit/$on、vuex、$parent / $children、$attrs/$listen
  • vue组件通信的几种方式

    千次阅读 2021-04-24 20:39:22
    vue组件中的通信方式一共有3种,它们分别是: 1,父子组件通信 2,子父组件通信 3,兄弟组件通信 一,父子组件通信 //这是父组件 里面有一个num,把num传给子组件 <template> <div id="app"> &...
  • Vue组件,如何创建子组件,如何实例化一个vue的实例,如何进行组件之间的通信。这是重点。组件之间通信方式有多种。
  • Vue组件间通信6种方式

    2020-12-22 20:24:51
    前言组件vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。一般来说,组件可以有以下几种关系:如上图所示,A 和 B、B 和 C、B 和 D 都是父子关系,C 和 D ...
  • 面试官:Vue 中父子组件通信有哪些方式? 自己先想一分钟。 无可否认,现在无论大厂还是小厂都已经用上了Vue.js 框架,简单易上手不说,教程详尽,社区活跃,第三方套件还多。真的是前端开发人员必备技能。而且在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 27,735
精华内容 11,094
关键字:

vue组件之间的通信方式