Vue中子组件不能直接引用父组件的数据,需要通过props选项接收来自父组件的数据。
参考:https://cn.vuejs.org/v2/api/#props
props 可以是数组或对象
<template>
<div>
<child id="1" :openReading="article.openReading" :title="article.title" :tags="article.tags" :author="article.author" />
div>
template>
<script>
import Child from './components/Child'
export default {
components: { Child },
data () {
return {
article: {
id: 1,
openReading: true,
title: 'title',
tags: ['vue', 'js'],
author: {
name: 'Jack'
}
}
}
}
}
script>
本例中,如果希望将article对象的所有属性都作为 prop 传入,可以使用不带参数的 v-bind
<template>
<div>
<child v-bind="article" />
div>
template>
<template>
<div>
<div>{{id}} - {{openReading}} -{{title}}-{{tags}}-{{author.name}}div>
div>
template>
<script>
export default {
props: ['id', 'openReading', 'title', 'tags', 'author']
}
script>
给子组件prop 传入一个静态的值,该值将会是个字符串,如通过v-bind:(简写为:)传入则为一个表达式,通过这个方式即可为子组件传入动态的任意类型的值。
上例中,子组件得到的数据id为字符串1,openReading为布尔值true,title为字符串title,tags为数组[‘vue’, ‘js’],propE为对象{name: ‘Jack’}。
在合作开发中,为了组件的健壮和可读性等需求,通常我们希望每个 prop 都有指定的值类型,默认值甚至验证传入的值是否规范等等,如将props设置为对象,则允许配置高级选项,如类型检测、自定义验证和设置默认值。
通过这些设置,遇到错误时浏览器的 JavaScript 控制台将会提示用户.
将子组件的配置项
props: ['id', 'openReading', 'title', 'tags', 'author']
改为:
props: {
id: {
// 多个可能的类型
type: [String, Number],
required: true,
// 自定义验证函数
validator: (value) => {
return parseInt(value) >= 0
}
},
openReading: {
type: Boolean,
default: true
},
title: {
type: String,
default: ''
},
tags: {
type: Array,
default: () => [] // 对象或数组默认值必须从一个函数获取
},
author: {
type: Object,
default: () => {} // 对象或数组默认值必须从一个函数获取
}
}
如果组件位于HTML中,必须将驼峰命名法的prop名改写为其等价的 kebab-case (短横线分隔命名)
,其他情况下两种写法等价。
<div id="app">
<child parent-title="demo">child>
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
let Child = {
template: `{{parentTitle}}`,
props:['parentTitle']
}
new Vue({
el:"#app",
components: {Child}
});
script>
父组件
<child :id="1" :openReading.sync="article.openReading" :title="article.title" :tags="article.tags" :author="article.author" />
子组件
this.$emit('update:openReading', !this.openReading)
其中:openReading.sync="article.openReading"只是v-bind:openReading=“article.openReading” v-on:update:openReading="article.openReading= $event"的简写形式,并没有改变单向数据流
使用sync修饰符的时候,子组件传递的事件名必须为update:value,value必须与子组件中props中声明的名称完全一致(如上例中的openReading,不能使用open-reading
如果来自父组件的prop发生了变化,在子组件生命周期beforeUpdate、updated能够监听到,通常子组件监听数据变化用watch监听数据变化
如下,监听id的变化
watch: {
id: {
handler (nVal, oVal) {
console.log(nVal, oVal)
},
immediate: true // 该回调将会在侦听开始之后被立即调用
}
}
本例中,第一次打印出的数据是1 undefined
指传向一个组件,但是该组件并没有相应 prop 定义的 attribute。
<child v-bind="article" style="color:red" class="article" className="article-list"/>
class将会自动挂载到子组件组件的组件根元素上,组件可以接受任意的 attribute
组件内部的Attribute与外部提供的Attribute发生重名的情况时,值会发生替换或合并
子组件
<div>
<div style="font-size: 16px;" class="default" className="articleList">
{{id}} - {{openReading}} -{{title}}-{{tags}}-{{author.name}}
div>
div>
class 和 style和合并Attribute的值,其他的attribute ,父组件提供的值会替换掉组件内部设置好的值。
如果想禁用非 props 的 Attribute 属性的方法,可以给子组件增加配置项
inheritAttrs: false
inheritAttrs: false 选项不会影响 style 和 class 的绑定。
通过inheritAttrs: false 和 组件的$attrs,可以手动决定 attribute 被赋予哪个元素
子组件
<div>
<div v-bind="$attrs">
{{id}} - {{openReading}} -{{title}}-{{tags}}-{{author.name}}
div>
div>