zoukankan      html  css  js  c++  java
  • vue中8种组件通信方式

    一、props / $emit

    下面通过一个例子说明父组件如何向子组件传递数据:在子组件article.vue中如何获取父组件section.vue中的数据articles:['红楼梦', '西游记','三国演义']

    // section父组件
    <template>
      <div class="section">
        <com-article :articles="articleList"></com-article>
      </div>
    </template>
    
    <script>
    import comArticle from './test/article.vue'
    export default {
      name: 'HelloWorld',
      components: { comArticle },
      data() {
        return {
          articleList: ['红楼梦', '西游记', '三国演义']
        }
      }
    }
    </script>
    // 子组件 article.vue
    <template>
      <div>
        <span v-for="(item, index) in articles" :key="index">{{item}}</span>
      </div>
    </template>
    
    <script>
    export default {
      props: ['articles']
    }
    </script>

    总结: prop 只可以从上一级组件传递到下一级组件(父子组件),即所谓的单向数据流。而且 prop 只读,不可被修改,所有修改都会失效并警告。

    2. 子组件向父组件传值

    对于$emit 我自己的理解是这样的: $emit绑定一个自定义事件, 当这个语句被执行时, 就会将参数arg传递给父组件,父组件通过v-on监听并接收参数。 通过一个例子,说明子组件如何向父组件传递数据。 在上个例子的基础上, 点击页面渲染出来的ariticleitem, 父组件中显示在数组中的下标
    // 父组件中
    <template>
      <div class="section">
        <com-article :articles="articleList" @onEmitIndex="onEmitIndex"></com-article>
        <p>{{currentIndex}}</p>
      </div>
    </template>
    
    <script>
    import comArticle from './test/article.vue'
    export default {
      name: 'HelloWorld',
      components: { comArticle },
      data() {
        return {
          currentIndex: -1,
          articleList: ['红楼梦', '西游记', '三国演义']
        }
      },
      methods: {
        onEmitIndex(idx) {
          this.currentIndex = idx
        }
      }
    }
    </script>
    <template>
      <div>
        <div v-for="(item, index) in articles" :key="index" @click="emitIndex(index)">{{item}}</div>
      </div>
    </template>
    
    <script>
    export default {
      props: ['articles'],
      methods: {
        emitIndex(index) {
          this.$emit('onEmitIndex', index)
        }
      }
    }
    </script>

    二、 $children / $parent

    // 父组件中
    <template>
      <div class="hello_world">
        <div>{{msg}}</div>
        <com-a></com-a>
        <button @click="changeA">点击改变子组件值</button>
      </div>
    </template>
    
    <script>
    import ComA from './test/comA.vue'
    export default {
      name: 'HelloWorld',
      components: { ComA },
      data() {
        return {
          msg: 'Welcome'
        }
      },
    
      methods: {
        changeA() {
          // 获取到子组件A
          this.$children[0].messageA = 'this is new value'
        }
      }
    }
    </script>
    // 子组件中
    <template>
      <div class="com_a">
        <span>{{messageA}}</span>
        <p>获取父组件的值为:  {{parentVal}}</p>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          messageA: 'this is old'
        }
      },
      computed:{
        parentVal(){
          return this.$parent.msg;
        }
      }
    }
    </script>
    要注意边界情况,如在#app上拿$parent得到的是new Vue()的实例,在这实例上再拿$parent得到的是undefined,而在最底层的子组件拿$children是个空数组。也要注意得到$parent$children的值不一样,$children 的值是数组,而$parent是个对象

    三、provideinject

    provide/ injectvue2.2.0新增的api, 简单来说就是父组件中通过provide来提供变量, 然后再子组件中通过inject来注入变量。

    注意: 这里不论子组件嵌套有多深, 只要调用了inject 那么就可以注入provide中的数据,而不局限于只能从当前父组件的props属性中回去数据

    // A.vue
    
    <template>
      <div>
        <comB></comB>
      </div>
    </template>
    
    <script>
      import comB from '../components/test/comB.vue'
      export default {
        name: "A",
        provide: {
          for: "demo"
        },
        components:{
          comB
        }
      }
    </script>
    // B.vue
    
    <template>
      <div>
        {{demo}}
        <comC></comC>
      </div>
    </template>
    
    <script>
      import comC from '../components/test/comC.vue'
      export default {
        name: "B",
        inject: ['for'],
        data() {
          return {
            demo: this.for
          }
        },
        components: {
          comC
        }
      }
    </script>
    // C.vue
    <template>
      <div>
        {{demo}}
      </div>
    </template>
    
    <script>
      export default {
        name: "C",
        inject: ['for'],
        data() {
          return {
            demo: this.for
          }
        }
      }
    </script>

    四、ref / refs

    ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据, 我们看一个ref 来访问组件的例子:
    // 子组件 A.vue
    
    export default {
      data () {
        return {
          name: 'Vue.js'
        }
      },
      methods: {
        sayHello () {
          console.log('hello')
        }
      }
    }
    // 父组件 app.vue
    
    <template>
      <component-a ref="comA"></component-a>
    </template>
    <script>
      export default {
        mounted () {
          const comA = this.$refs.comA;
          console.log(comA.name);  // Vue.js
          comA.sayHello();  // hello
        }
      }
    </script>

    五、eventBus

    eventBus 又称为事件总线,在vue中可以使用它来作为沟通桥梁的概念, 就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件, 所以组件都可以通知其他组件。

    eventBus也有不方便之处, 当项目较大,就容易造成难以维护的灾难

    类似事件订阅与发布

    六、Vuex

    七、localStorage / sessionStorage

    八 $attrs与 $listeners

    vue2.4中,为了解决该需求,引入了$attrs$listeners , 新增了inheritAttrs 选项。 在版本2.4以前,默认情况下,父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外),将会“回退”且作为普通的HTML特性应用在子组件的根元素上。接下来看一个跨级通信的例子:
    // app.vue
    // index.vue
    
    <template>
      <div>
        <child-com1
          :name="name"
          :age="age"
          :gender="gender"
          :height="height"
          title="FE攻城狮从零到壹"
        ></child-com1>
      </div>
    </template>
    <script>
    const childCom1 = () => import("./childCom1.vue");
    export default {
      components: { childCom1 },
      data() {
        return {
          name: "ghui",
          age: "18",
          gender: "男",
          height: "183"
        };
      }
    };
    </script>
    // childCom1.vue
    
    <template class="border">
      <div>
        <p>name: {{ name}}</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: {
        name: String // name作为props属性绑定
      },
      created() {
        console.log(this.$attrs);
         // { "age": "18", "gender": "男", "height": "183", "title": "FE攻城狮从零到壹" }
      }
    };
    </script>
    // childCom2.vue
    
    <template>
      <div class="border">
        <p>age: {{ age}}</p>
        <p>childCom2: {{ $attrs }}</p>
      </div>
    </template>
    <script>
    
    export default {
      inheritAttrs: false,
      props: {
        age: String
      },
      created() {
        console.log(this.$attrs); 
        // { "gender": "男", "height": "183", "title": "FE攻城狮从零到壹" }
      }
    };
    </script>
  • 相关阅读:
    promise.all 发送多个请求
    解决分享里有中文,访问不了的问题
    elementui ztree 编辑的时候,回显半选状态的选项,用isLeaf判断
    倒叙数组查找数组对象中是否有该id值,将其去掉
    https强转
    Decorator学习(一)----- 基础知识
    MySQL的权限系统
    vue-cli 3.0.1 详细入门教程
    vue-cli4.5创建vue项目
    [记录] JavaScript 中的事件(Event对象、事件源对象、事件流、事件绑定)【转发】
  • 原文地址:https://www.cnblogs.com/baixiaoxiao/p/11981210.html
Copyright © 2011-2022 走看看