一、prop(官方)
通过Prop向子组件传递数据: 我们可以在组件上注册一些自定义的属性, 值传给这个属性的时候,该属性就变成该组件实例的一个property,我们在组件实例中用props选项将这些属性包含在其中,然后我们就能在组件实例中访问这个值,就像访问data中的值一样。一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{
{ title }}</h3>'
})
<blog-post title="My journey with Vue"></blog-post>
prop的写法:
字符串形式:
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
对象形式:
希望每个 prop 都有指定的值类型时,可以以对象形式列出 prop,这些 property 的名称和值分别是 prop 各自的名称和类型:
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}
Prop在html与javascript的写法:
html中的属性名大小写不敏感,所以浏览器会把所有大写字符解释成小写字符,
所以在使用DOM的模板时,驼峰命名法的prop需要使用等价的短横线分隔命名。
Vue.component('blog-post', {
// 在 JavaScript 中是 驼峰式命名 的
props: ['postTitle'],
template: '<h3>{
{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 短横线分隔的 -->
<blog-post post-title="hello!"></blog-post>
传递静态或动态prop
(1)传递静态值:
<blog-post title="My journey with Vue"></blog-post>
(2)传递动态值(通过v-bind动态绑定):
<!-- 动态赋予一个变量的值 -->
<blog-post v-bind:title="post.title"></blog-post>
<!-- 动态赋予一个复杂表达式的值 -->
<blog-post
v-bind:title="post.title + ' by ' + post.author.name"
></blog-post>
任何类型的值都可以传给prop:
数字:
<!-- 即便 `42` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<blog-post v-bind:likes="42"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post v-bind:likes="post.likes"></blog-post>
布尔值:
<!-- 包含该 prop 没有值的情况在内,都意味着 `true`。-->
<blog-post is-published></blog-post>
<!-- 即便 `false` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post v-bind:is-published="false"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:is-published="post.isPublished"></blog-post>
数组:
<!-- 即便数组是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:comment-ids="post.commentIds"></blog-post>
对象:
<!-- 即便对象是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post
v-bind:author="{
name: 'Veronica',
company: 'Veridian Dynamics'
}"
></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:author="post.author"></blog-post>
传入一个对象的所有property:
post: {
id: 1,
title: 'My Journey with Vue'
}
<blog-post v-bind="post"></blog-post>
等价于:
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
二、父向子传值:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<blog-li v-for='item in blogs' v-bind:item='item'></blog-li>
</div>
<script>
Vue.component('blog-li',{
props:['item'],
//每个组件必须只有一个根元素
template:`
<div class='blog-li'>
<h3>{
{item.title}}</h3>
<h2>{
{item.id}}</h2>
</div>
`
})
const app = new Vue({
el: '#app',
data: {
blogs: [{
id: 1,
title: '第一篇博文'
},
{
id: 2,
title: '第二篇博文'
},
{
id: 3,
title: '第三篇博文'
}
]
}
})
</script>
</body>
</html>
运行效果:
子组件像父组件传值:(监听子组件事件)
子组件向父组件发射信号,父组件接收信号做出操作。
子组件去改变父组件的值(子组件向父组件传值,父组件再使用该值进行处理,再通过Prop作用于子组件);
子组件与父组件之间需要进行沟通,官方案例:子组件中添加一个按钮点击改变博文的字体大小。
思路:父组件添加一个blogFontSize数据,使用在子组件模板中控制子组件博文字体大小。每个模板需求里面有一个按钮可以控制博文大小。
Vue提供一个自定义事件系统,父级组件就可以通过v-on监听子组件实例的任意事件。 同时子组件可以通过调用内建的 $emit 方法并传入事件名称来触发事件:
子组件:v-on:click="$emit('enlarge-text')"
emit中文发射的意思,可以将其理解成子组件向父组件发射信号
父组件:v-on:enlarge-text="blogFontSize += 0.1" 监听器,父级组件就能接收并更新blogFontSize得值。
理解为 父元素接收信号
<!DOCTY<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- v-on:enlarge-text 理解为 父元素接收信号-->
<div class="box" :style="{fontSize:blogFontSize+'px'}">
<blog-li v-for='item in blogs' v-bind:item='item' v-on:enlarge-text='blogFontSize+=10' :size='blogFontSize'>
</blog-li>
</div>
</div>
<script>
Vue.component('blog-li', {
props: ['item', 'size'],
//每个组件必须只有一个根元素 emit中文发射的意思,可以将其理解成子组件向父组件发射信号
template: `
<div class='blog-li'>
<button v-on:click="$emit('enlarge-text')">点击字体变大{
{size}}</button>
<h3>{
{item.title}}</h3>
<h2>{
{item.id}}</h2>
</div>
`
})
const app = new Vue({
el: '#app',
data: {
blogFontSize: 16,
blogs: [{
id: 1,
title: '第一篇博文'
},
{
id: 2,
title: '第二篇博文'
},
{
id: 3,
title: '第三篇博文'
}
]
}
})
</script>
</body>
</html>