Vue非Prop特性和监听子组件的事件
组件_非Prop特性
非Prop特性指的是,一个未被组件注册的特性。当组件接收了一个非Prop特性时,该特性会被添加到这个组件的根元素上。
替换/合并已有的特性
想象一下 <my-cmp>
的模板是这样的:
<input type="date" class="b">
为了给我们的日期选择器插件定制一个主题,我们可能需要像这样添加一个特别的类名:
<my-cmp
class="my-cmp"
></my-cmp>
在这种情况下,我们定义了两个不同的 class 的值:
- my-cmp,这是在组件的模板内设置好的
- b,这是从组件的父级传入的
对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值。所以如果传入 type=“text” 就会替换掉 type=“date” 并把它破坏!庆幸的是,class 和 style 特性会稍微智能一些,即两边的值会被合并起来,从而得到最终的值:my-cmp b。
禁用特性继承
如果不希望组件的根元素继承特性,那么可以在组件选项中设置 inheritAttrs: false
。如:
Vue.component('my-cmp', {
inheritAttrs: false,
// ...
})
在这种情况下,非常适合去配合实例的 $attrs 属性使用,这个属性是一个对象,键名为传递的特性名,键值为传递特性值。
{
required: true,
placeholder: 'Enter your username'
}
使用 inheritAttrs: false
和 $attrs
相互配合,我们就可以手动决定这些特性会被赋予哪个元素。如:
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`,
})
注意:inheritAttrs: false 选项不会影响 style 和 class 的绑定。
组件_监听组件事件
首先,我们来写一个博文组件,如:
Vue.component('blog-post', {
props: {
post: {
type: Object,
}
},
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button>放大字号</button>
<div>{{ post.content }}</div>
</div>
`,
})
<div id="app">
<div :style="{fontSize: postFontSize + 'em'}">
<blog-post
v-for="post in posts"
:key="post.id"
:post="post"
>
</blog-post>
</div>
</div>
const vm = new Vue({
el: '#app',
data: {
posts: [
{ title: '标题1', content: '正文内容', id: 0, },
{ title: '标题2', content: '正文内容', id: 1, },
{ title: '标题3', content: '正文内容', id: 2, },
],
postFontSize: 1
}
})
可以看到每一个博文组件中,都有一个按钮,可以去放大页面中字体的字号,也就是说,当点击这个按钮时,我们要告诉父组件改变postFontSize
数据去放大所有博文的文本。碰见这样的情况,该如何做呢?
Vue 实例提供了一个自定义事件来解决这个问题。父组件可以像处理原生DOM元素一样,通过 v-on
指令,监听子组件实例的任意事件,如:
<div id="app">
<div :style="{fontSize: postFontSize + 'em'}">
<blog-post
...
@enlarge-text="postFontSize += 0.1"
>
</blog-post>
</div>
</div>
那么,怎么样能够去监听到一个 enlarge-text
这么奇怪的事件呢?这就需要在组件内,去主动触发一个自定义事件了。
如何触发? 通过调用 $emit 方法 并传入事件名称来触发一个事件,如:
Vue.component('blog-post', {
props: {
...
},
template: `
<div class="blog-post">
...
<button @click="$emit('enlarge-text')">放大字号</button>
...
</div>
`,
})
这样,父组件就可以接收该事件,更新数据 pageFontSize
的值了。
使用事件抛出一个值
在有些情况下,我们可能想让 <blog-post>
组件决定它的文本要放大多少。这是可以使用 $emit 的第二个参数来提供这个值,如:
Vue.component('blog-post', {
props: {
...
},
template: `
<div class="blog-post">
...
<button @click="$emit('enlarge-text', 0.2)">放大字号</button>
...
</div>
`,
})
在父组件监听这个事件时,可以通过 $event 访问到被抛出的这个值:
<div id="app">
<div :style="{fontSize: postFontSize + 'em'}">
<blog-post
...
@enlarge-text="postFontSize += $event"
>
</blog-post>
</div>
</div>
或者,将这个事件处理函数写成一个方法:
<div id="app">
<div :style="{fontSize: postFontSize + 'em'}">
<blog-post
...
@enlarge-text="onEnlargeText"
>
</blog-post>
</div>
</div>
那么,这个值将会作为第一个参数,传入这个方法:
methods: {
onEnlargeText: function (enlargeAmount) {
this.postFontSize += enlargeAmount
}
}
最后
如果对您有帮助,希望能给个👍评论/收藏/三连!
博主为人老实,无偿解答问题哦❤
- 点赞
- 收藏
- 关注作者
评论(0)