Vue: 通过prop向子组件传递数据,并且监听子组件事件
Prop 是你可以在组件上注册的一些自定义特性。当一个值传递给一个 prop 特性的时候,它就变成了那个组件实例的一个属性。为了给博文组件传递一个标题,我们可以用一个props选项将其包含在该组件可接受的 prop 列表中:Vue.component('blog-post', {props: ['title'],template: '<h3>{{ title }}...
Prop 是你可以在组件上注册的一些自定义特性。当一个值传递给一个 prop 特性的时候,它就变成了那个组件实例的一个属性。为了给博文组件传递一个标题,我们可以用一个 props
选项将其包含在该组件可接受的 prop 列表中:
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在上述模板中,你会发现我们能够在组件实例中访问这个值,就像访问 data
中的值一样。
一个 prop 被注册之后,你就可以像这样把数据作为一个自定义特性传递进来:
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>
然而在一个典型的应用中,你可能在 data
里有一个博文的数组:
new Vue({
el: '#blog-post-demo',
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
}
})
并想要为每篇博文渲染一个组件:
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post>
如上所示,你会发现我们可以使用 v-bind
来动态传递 prop。
重构一下这个 <blog-post>
组件,让它变成接受一个单独的 post
prop:
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
</div>
`
})
监听子组件事件:
在我们开发 <blog-post>
组件时,它的一些功能可能要求我们和父级组件进行沟通。例如我们可能会引入一个可访问性的功能来放大博文的字号,同时让页面的其它部分保持默认的字号。
在其父组件中,我们可以通过添加一个 postFontSize
数据属性来支持这个功能:
new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [/* ... */],
postFontSize: 1
}
})
它可以在模板中用来控制所有博文的字号:
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
</div>
</div>
现在我们在每篇博文正文之前添加一个按钮来放大字号:
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button>
Enlarge text
</button>
<div v-html="post.content"></div>
</div>
`
})
当点击这个按钮时,我们需要告诉父级组件放大所有博文的文本。我们使用v-on 监听子组件实例的任意事件:
<blog-post
...
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
同时子组件可以通过调用内建的 $emit
方法 并传入事件名称来触发一个事件:
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
完整示例代码:
<template>
<div class="hello">
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
v-on:enlarge-text="postFontSize+=0.1"
></blog-post>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue'
/* eslint-disable no-new */
Vue.component('blog-post', { // 通过 Prop 向子组件传递数据
props: ['post'],
template: // 子组件
`
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
</div>
`
})
export default {
name: 'HelloWorld',
data () {
return {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
],
postFontSize: 1,
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
我们来改造以下,可以用v-on添加一个缩小文本的方法:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<h1>
<router-link to="wangcan">跳转至HelloVue页面</router-link>
</h1>
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
v-on:enlarge-text="postFontSize+=$event"
v-on:smaller-text="postFontSize-=$event"
></blog-post>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue'
/* eslint-disable no-new */
Vue.component('blog-post', { // 通过 Prop 向子组件传递数据
props: ['post'],
template: // 子组件
`
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlarge-text', 0.1)">
放大这个文本
</button>
<button v-on:click="$emit('smaller-text', 0.1)">
缩小这个文本
</button>
</div>
`
})
export default {
name: 'HelloWorld',
data () {
return {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
],
postFontSize: 1,
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1,
h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
参考文档:组建基础——Vue.js
https://cn.vuejs.org/v2/guide/components.html
更多推荐
所有评论(0)