文章目录
一、父组件给子组件传递非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会被映射到根元素上。
通过 this.$attrs
属性也可印证这一点:$attrs
可以访问所有的 非props的attribute,但是没有上述的title属性,因为它已被props接收。
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 了。
,
虽然禁止继承,this.$attrs
依然能拿到。
禁用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 如下:
二、子组件传递事件给父组件
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>