vue父子组件通讯

1. 动态绑定/props 

例子:

父组件  Parent.vue

<template>
  <div>
    <div class="parent">
      <div>父组件</div>
      <br />
      <child :message="message" @changeMessage="message = $event" />
    </div>
  </div>
</template>

<script>
import Child from "./Child.vue";
export default {
  name: "parent",
  components: { Child },
  props: {},
  data() {
    return {
      message: "hello! 我是父组件消息",
    };
  },
  methods: {
    onHandle(e) {
      console.log(e);
    },
  },
};
</script>

子组件  Child.vue

<template>
  <div>
    <div class="child">子组件接收到的消息:{{ message }}</div>
    <button @click="handleClick">按钮</button>
  </div>
</template>

<script>
export default {
  name: "child",
  components: {},
  props: ["message"],
  data() {
    return {};
  },
  methods: {
    handleClick() {
      this.$emit("changeMessage", "在子组件中修改了message");
    },
  },
};
</script>

以上例子做了这几件事情:

1.父组件通过在子组件上绑定动态属性传值,

2.子组件通过 props 来注入接收到的值

3.子组件通过  this.$emit 注册自定义事件 ,

4.父组件通过@事件函数名 ,来监听这个自定义事件,$event则是自事件传递的值,$event赋值给了父组件的message

2.callback方式传值

例子:

父组件  Parent.vue

<template>
  <div>
    <div class="parent">
      <div>父组件值:{{ message }}</div>
      <br />
      {{ message2 }}
      <child :message="message" :changeMsgFn="changeMessage" />
    </div>
  </div>
</template>

<script>
import Child from "./Child.vue";
export default {
  name: "parent",
  components: { Child },
  props: {},
  data() {
    return {
      message: "hello! 我是父组件消息",
      message2: "1",
    };
  },
  methods: {
    changeMessage(chlidMessage2) {
      this.message2 = chlidMessage2;
      this.message = "message被修改了";
    },
  },
};
</script>

子组件  Child.vue

<template>
  <div>
    <div class="child">子组件接收到的消息:{{ message }}</div>
    <div>{{ chlidMessage2 }}</div>
    <button @click="changeMsgFn(chlidMessage2)">按钮</button>
  </div>
</template>

<script>
export default {
  name: "child",
  components: {},
  props: ["message", "changeMsgFn"],
  data() {
    return {
      chlidMessage2: 123,
    };
  },
  methods: {
    handleClick() {
      this.$emit("changeMessage", "在子组件中修改了message");
    },
  },
};
</script>

1.父组件中定义方法,方法接收形参

2.通过动态绑定传值 , 将父组件中定义的方法传入子组件 

3.子组件将父组件传入的方法调用,且传入形参

3.$parent+$children

例子:

父组件  Parent.vue

<template>
  <div>
    <div class="parent">
      <div>父组件值:{{ message }}</div>
      <br />
      <child />
      <br />
      <button @click="changeChildNum">按钮</button>
    </div>
  </div>
</template>

<script>
import Child from "./Child.vue";
export default {
  name: "parent",
  components: { Child },
  props: {},
  data() {
    return {
      message: "hello! 我是父组件消息",
    };
  },
  methods: {
    changeChildNum() {
      this.$children[0].num = 50;
    },
  },
};

子组件  Child.vue

<template>
  <div>
    <div class="child">子组件接收到的消息:{{ parentMessage() }}</div>
    <div>{{ num }}</div>
  </div>
</template>

<script>
export default {
  name: "child",
  data() {
    return {
      num: 10,
    };
  },
  methods: {
    parentMessage() {
      return this.$parent.message;
    },
  },
};
</script>

1.一个父组件可能有很多个子组件 , 父组件通过 this.$children[0] 找到子组件,

2.父组件通过改变this.$children[0] 上的属性,从而改变子组件内部的值

3.子组件通过this.$parent来获取父组件

4.子组件通过改变this.$parent的属性,从而改变父组件内部的值

4.provide+inject

父子组件通过属性层层冒泡来通信 , 兄弟之间通过事件的方式进行通信 , 成本高 , 毫无健壮性 , 非常脆弱

provide提供数据 , inject注入数据 , 解决了这个问题

例子:

父组件  Parent.vue

<template>
  <div>
    <div class="parent">
      <div>父组件值:{{ message }}</div>
      <child />
    </div>
  </div>
</template>

<script>
import Child from "./Child.vue";
export default {
  name: "parent",
  components: { Child },
  provide() {
    return {
      message: this.message,
    };
  },
  data() {
    return { message: "hello! 我是父组件消息" };
  },
};

子组件  Child.vue

<template>
  <div>
<!--还可以通过 injections.message接收 --> <div class="child">子组件接收到的消息:{{ message }}</div> </div> </template> <script> export default { name: "child", inject: ["message"], }; </script>

 

1.父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量

2.不论子组件有多深,只要调用了inject那么就可以注入provider中的数据

3.在这个父组件生效的生命周期内,所有的子组件都可以调用inject来注入父组件中的值

注意:

  1. provide  是一个对象,或者是一个返回对象的函数。当为一个对象时,访问不到this

  2.子孙层的provide会掩盖祖父层provide中相同key的属性值

  3.例如上述例子中的 message  并非响应式 , 当父组件改变message时 , 子组件接收到店message并不会改变 

需要 将整个this注入进去 , 此方法弊端在于 , 传递的不需要的东西太多

 

 

provide() {
    return {
      message: this,
    };
  },

 不推荐直接使用在应用程序代码中是因为数据追踪比较困难,不知道是哪一个层级声明了这个或者不知道哪一层级或若干个层级使用了。

vue2.6 提供了 Vue.observable这个API来优化provide

demo示例:   vue使用observable组件传值

5.$attr+$listeners

例子:

父组件  Parent.vue

<template>
  <div>
    <h1>父组件</h1>
    <div class="parent">
      <div>父组件值:{{ age }}</div>
      <child :age="age" :name="name" @changeAge="changeAge" />
    </div>
  </div>
</template>

<script>
import Child from "./Child.vue";
export default {
  name: "parent",
  components: { Child },
  data() {
    return {
      name: "joke",
      age: 20,
    };
  },
  methods: {
    changeAge(num) {
      this.age = num;
    },
  },
};
</script>

子组件  Child.vue

<template>
  <div>
    <h1>子组件</h1>
    <div class="child">子组件接收到的消息:{{ $attrs.age }}</div>
    <button @click="$listeners.changeAge(50)">按钮</button>
    <br />
    <grend-child v-bind="$attrs" />
  </div>
</template>

<script>
import GrendChild from "./GrendChild.vue";
export default {
  components: { GrendChild },
  name: "child",
};
</script>

孙组件  GrendChild.vue

<template>
  <div>
    <h1>孙组件</h1>
    <div class="container">
      {{ $attrs.name }}
    </div>
    <div>
      {{ $attrs.age }}
    </div>
  </div>
</template>

 

1.父组件动态传值给子组件 ,方法通过@事件监听器传递给子组件

2.子组件通过$attrs接收到父组件传递给子组件所有的值 

3.子组件通过在孙组件上v-bind=$attrs , 将子组件获取到的$attrs传递给孙组件,从而实现了父传孙

4.子组件通过$listeners获取到所有父组件在子组件上的定义的事件监听器@,通过调用$listeners.父方法 , 从而实现了子调用父的方法

5.子组件通过在孙组件上,v-on=$listeners , 将子组件获取到的$listeners 传递给孙组件,从而实现了孙调用父的方法

6.ref属性

例子

父组件  Parent.vue

<template>
  <div>
    <h1>父组件</h1>
    <div class="parent">
      <div>父组件值:</div>
      <child ref="childComp" />
      <button @click="changeAge">按钮</button>
    </div>
  </div>
</template>

<script>
import Child from "./Child.vue";
export default {
  name: "parent",
  components: { Child },
  methods: {
    changeAge() {
      this.$refs.childComp.changeAge();
      console.log(this.$refs.childComp);
    },
  },
};
</script>

子组件  Child.vue

<template>
  <div>
    <h1>子组件</h1>
    <div class="child">子组件接收到的消息:{{ age }}</div>
    <br />
  </div>
</template>

<script>
export default {
  name: "child",
  data() {
    return {
      age: 20,
    };
  },
  methods: {
    changeAge() {
      this.age = 50;
    },
  },
};
</script>

 1.父组件通过this.$refs获取到子组件实例,改变子组件内部变量,或调用子组件方法

 ....

posted @ 2021-06-05 13:01  混名汪小星  阅读(112)  评论(0)    收藏  举报