Vue3-你不知道的父子组件传递细节

文章目录

一、父组件给子组件传递非Prop的Attribute

何为非Prop的Attribute?
即:当传递给组件某项值时,如果没有在 props定义,那么则称呼为非Prop的Attribute。

当这种时候传递参数,会出现三种情况

App.vue

<template>
  <div id="home">
    <show-message id="show-id" class="show-class" title="show-title"></show-message>
  </div>
</template>

<script>
import ShowMessage from './ShowMessage.vue'
export default {
  components: {
    ShowMessage
  }
}
</script>

1.1 情况一 子组件有根元素

<template>
  <div></div>
</template>

<script>
export default {
  props: ['title'],
  mounted() {
    console.log('this.$attrs: ', this.$attrs)
  }
}
</script>

当有根元素时,非Prop的Attribute会被映射到根元素上。
Vue3-你不知道的父子组件传递细节
通过 this.$attrs属性也可印证这一点:
$attrs 可以访问所有的 非props的attribute,但是没有上述的title属性,因为它已被props接收。
Vue3-你不知道的父子组件传递细节

1.2 情况二 不希望继承 禁用继承

在子组件的 export default {}对象中,加入一个新属性:inheritAttrs:false

<template>
  <div></div>
</template>

<script>
export default {
  // 禁止继承
  inheritAttrs: false,
  props: ['title'],
  mounted() {
    console.log('this.$attrs: ', this.$attrs)
  }
}
</script>

此时,子组件的根元素上就没有了 父组件传递的 Attribute 了。
Vue3-你不知道的父子组件传递细节,
虽然禁止继承,this.$attrs依然能拿到。
Vue3-你不知道的父子组件传递细节
禁用attribute继承的 常见情况 是需要将attribute 应用于根元素之外的其他元素
也就是情况三。

1.3 情况三 将Attribute指定给其他标签

我们可以通过$attrs将父组件传递的 Attribute 传递给我们指定的标签。

<template>
  <div>
    <div v-bind="$attrs"></div>
    <div :class="$attrs.class"></div>
    <div :id="$attrs.id"></div>
  </div>
</template>

<script>
export default {
  // 禁止继承
  inheritAttrs: false,
  props: ['title'],
  mounted() {
    console.log('this.$attrs: ', this.$attrs)
  }
}
</script>

注:v-bind="obj"可直接将obj对象所有属性映射到该标签上。
DOM 如下:
Vue3-你不知道的父子组件传递细节

二、子组件传递事件给父组件

Vue官方文档:emits选项

这里Vue3与Vue2的差别是:Vue 3 现在提供一个 emits 选项,和现有的 props 选项类似。这个选项可以用来定义一个组件可以向其父组件触发的事件。

App.vue 父组件

<template>
  <div>
    <h2>当前计数: {{ counter }}</h2>
    <counter-item @add="add" @sub="sub" @addN="addN"></counter-item>
  </div>
</template>

<script>
import CounterItem from "./CounterItem.vue";
export default {
  components: {
    CounterItem,
  },
  data() {
    return {
      counter: 0,
    };
  },
  methods: {
    add() {
      this.counter++;
    },
    sub() {
      this.counter--;
    },
    addN(num) {
      console.log(num);
      this.counter += num;
    },
  },
};
</script>

CounterItem.vue 子组件

<template>
  <div>
    <button @click="increment">+1</button>
    <button @click="decrement">-1</button>

    <input type="text" v-model.number="num" />
    <button @click="incrementN">+n</button>
  </div>
</template>

<script>
export default {
  // emits: ["add", "sub", "addN"],
  // 对象写法的目的是为了参数验证,单验证不通过时,会在控制台抛出警告
  emits: {
    add: null,
    sub: null,
    // addN: (num, name, age) => {
    //   console.log("num, name, age: ", num, name, age);
    //   if (num > 10) {
    //     return true;
    //   } else {
    //     return false;
    //   }
    // },
    addN: (...args) => {
      console.log("args: ", args);
      if (args[0] > 10) {
        return true;
      } else {
        return false;
      }
    },
  },
  data() {
    return {
      num: 0,
    };
  },
  methods: {
    increment() {
      this.$emit("add");
      console.log("+1");
    },
    decrement() {
      this.$emit("sub");
      console.log("-1");
    },
    incrementN() {
      this.$emit("addN", this.num, "a", "v");
    },
  },
};
</script>

<style scoped></style>

上一篇:AttributeError: module ‘sha3‘ has no attribute ‘keccak_256‘


下一篇:virtualbox的Linux虚拟磁盘大小调整及注意事项