Vue01组件化实践-02组件通信边界情况

组件通信边界情况

demo github地址:feature/communicationOther 分支

  • $parent 、 $children 、$root 、$refs
  • 非Props特性(不需要Props)
    $attrs ( 祖先(定义属性名) --> 父(v-bind="$attrs") --> 子($attrs.祖先属性名) )
    $listeners ( 祖先(定义事件) --> 父(v-on="$listeners") --> 子($listeners.祖先事件) )
  • provide / inject (跨层传参)
  1. $parent 、 $children 、$root 、$refs
<!--- main.js -->
new Vue({
  router,
  store,
  render: h => h(App),
  methods : {
    handleRoot() {   <!-- 为子组件提供根组件方法 -->
      return 'event from root'
    }
  }
}).$mount('#app')
<!-- Parent.vue -->
<template>
  <div>
    <p>Parent</p>
    <button @click="getChildVal">获取子传给父的值(this.$children[0].toParent)</button><br/>
    <p v-if="childVal">{{childVal}}</p>
    <button @click="getChildByRefs">获取子传给父的值(this.$refs.child1.toParentRefs)</button><br/>
    <p v-if="childRefsVal">{{childRefsVal}}</p>
    <hr/>
    <Child ref="child1"></Child>
  </div>
</template>

<script>
  import Child from "../components/Child";
  export default {
    components: {
      Child
    },
    data() {
      return {
        childVal: '',
        childRefsVal: ''
      };
    },
    methods: {
      handleParent() {
        return "event for parent!";
      },
      getChildVal() {
        //children 是一个数组, 对于异步子组件或者按需加载子组件 children的下标 有可能不准
        this.childVal = this.$children[0].toParent();
      },
      getChildByRefs() {
        this.childRefsVal = this.$refs.child1.toParentRefs();
      }
    },
  };
</script>
<!-- Child.vue -->
<template>
  <div>
    <p>Child</p>
    <button @click="getParent">执行父组件方法(this.$parent.handleParent())</button><br/>
    <p v-if="parent">父组件方法的返回值 : {{parent}}</p>
    <button @click="getRoot">执行根组件方法(this.$root.handleRoot())</button>
    <p v-if="root">根组件方法的返回值 : {{root}}</p>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        parent: '',
        root: '',
        count: 1
      }
    },
    methods: {
      getParent() {
        this.parent = this.$parent.handleParent();
      },
      getRoot() {
        this.root = this.$root.handleRoot();
      },
      toParent() {
        return `children value to parent ${this.count++}`
      },
      toParentRefs(){
        return 'children refs value to parent'
      }
    },
  };
</script>
  1. $attrs 、$listeners 非Props特性
<!-- grandpa.vue -->
<template>
  <div>
    <h2>Grandpa</h2>
    <hr/>
    <Parent msg="把这个消息传送给我孙子" other="这个消息也别用props传了"  @testOne="test1" @testTwo="test2"></Parent>
  </div>
</template>
<script>
  import Parent from "../components/grandpa/Parent"
  export default {
    components:{
      Parent
    },
    methods: {
      test1() {
        alert('grandpa 传给 孙子的 第一个事件!');
      },
      test2() {
        alert('grandpa 传给 孙子的 第二个事件!');
      }
    },
  };
</script>
<!-- parent.vue -->
<template>
  <div>
    <h2>Parent</h2>
    <hr/>
    <Child v-bind="this.$attrs" v-on="this.$listeners"></Child>
  </div>
</template>

<script>
  import Child from "./Child";
  export default {
    components: {
      Child
    }
  };
</script>
<!-- child.vue -->
<template>
  <div>
    <h2>Child</h2>
    <p>这个是爷爷传给孙子的信息($attrs):<i>{{$attrs}}</i></p>
    <button @click="childOne">执行grandpa的test1()</button>
    <button @click="$listeners.testTwo()">执行grandpa的test2()</button>
    <button @click="$emit('testOne')">执行grandpa的test1()</button>
  </div>
</template>

<script>
  export default {
    methods: {
      childOne() {
        this.$listeners.testOne();
      }
    }
  };
</script>

3.provide / inject (跨层传参)

<!-- 第一层 grandpa.vue -->
<script>
    export default {
        provide() {
             return {
                grandpa:'提供跨层参数'
            }
        }
    }
</script>
<!-- 第三层 孙子辈儿 child.vue -->
<script>
<template>
<div>
      <p>{{grandpa}}</p>
</div>
</template>
 export default {
    //inject : ['grandpa'],
  inject: {
      grandpa: {
          type: String,
          default: "" 
      }
  }
}
</script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。