props
可以是 string[]
/ Object
的形式
sreing[]
写法
<template>
<div>
<Son
name="superman"
age="21"
/>
div>
template>
<script>
import Son from './components/Son.vue';
export default {
name: 'App',
components: { Son },
};
script>
<template>
<div>
<h2>姓名: {{ name }}h2>
<h2>年龄: {{ age }}h2>
div>
template>
<script>
export default {
name: 'Son',
// 编写 props 配置项 (接收数据)
props: ['name', 'age'],
};
script>
对象式写法(推荐)
<template>
<div>
<Son
name="superman"
:age="21"
/>
div>
template>
<script>
export default {
name: 'Son',
// 配置 props 属性 (接收数据)
props: {
name: String, // 限制 name 的属性值为 string 类型
age: Number, // 限制 age 的属性值为 number 类型
},
};
script>
:prop-name="XXX"
/ :propName="XXX"
传递数据props: ["propName"]
接收数据// 假设有一个 post 对象
const post = {
id: 1,
title: 'My Journey with Vue',
};
<BlogPost v-bind="post" />
<BlogPost
:id="post.id"
:title="post.title"
/>
<template>
<div>
<h1>{{ showApp() }}h1>
<button @click="num++">修改 agebutton>
<hr />
<Son :age="num" />
div>
template>
<script>
import Son from './components/Son.vue';
export default {
name: 'App',
components: { Son },
data() {
return { num: 21 };
},
methods: {
showApp() {
console.log('showApp');
return 'App';
},
},
};
script>
<template>
<div>
<h2>{{ showSon() }}h2>
<h2>年龄: {{ age }}h2>
<button @click="age++">修改 agebutton>
div>
template>
<script>
export default {
name: 'Son',
props: ['age'],
methods: {
showSon() {
console.log('showSon');
return 'Son';
},
},
};
script>
在子组件中 修改父组件传递过来的数据:控制台抛出警告、子组件的数据可以被成功修改、重新渲染子组件
参与子组件数据显示的方法 showSon
,在页面完成时被调用一次;子组件修改数据后,重新渲染子组件,被调用一次
此时我们再在父组件中修改原数据,则子组件的数据也会被修改,就是说,子组件之前修改的数据会被覆盖
参与页面数据显示的方法 showApp
、showSon
,在页面完成时依次被调用一次;父组件修改数据后,页面重新渲染,再依次被调用一次
props
中的数据赋值到 data
中<template>
<div>
<h2>{{ showSon() }}h2>
<h2>年龄: {{ sonAge }}h2>
<button @click="sonAge++">修改 sonAgebutton>
div>
template>
<script>
export default {
name: 'Son',
data() {
return { sonAge: this.age }; // 将接收到的数据设置为组件自己的数据
},
props: ['age'],
methods: {
showSon() {
console.log('showSon');
return 'Son';
},
},
};
script>
此时,子组件渲染的是 data 中的数据 sonAge
更新子组件 data 中的数据,子组件会被重新渲染、showSon
被调用
更新父组件的数据,父组件会被重新渲染、showApp
被调用;此时子组件不会被重新渲染
注意:自己的数据不要与接收的数据同名,否则会报错(页面会优先显示 props
的数据
<template>
<div>
<h1>{{ showApp() }}h1>
<button @click="sonObj.num++">修改 agebutton>
<hr />
<Son :ageObj="sonObj" />
div>
template>
<script>
import Son from './components/Son.vue';
export default {
name: 'App',
components: { Son },
data() {
return { sonObj: { num: 21 } };
},
methods: {
showApp() {
console.log('showApp');
return 'App';
},
},
};
script>
<template>
<div>
<h2>{{ showSon() }}h2>
<h2>年龄: {{ ageObj.num }}h2>
<button @click="ageObj.num++">修改 ageObjbutton>
div>
template>
<script>
export default {
name: 'Son',
props: ['ageObj'], // 接收对象数据
methods: {
showSon() {
console.log('showSon');
return 'Son';
},
},
};
script>
可以发现,页面初始化时,showApp
、showSon
依次被调用
不论在子组件还是在父组件中修改数据,都能成功修改数据、并重新渲染子组件模版,showSon
被调用
父组件给子组件传递函数,子组件给函数传入参数,从而实现子组件给父组件传递数据
props
属性接收该函数<template>
<div>
<p>父组件数据:{{ msg }}p>
<hr />
<Son :parentFun="parentFun" />
div>
template>
<script>
import Son from './components/Son.vue';
export default {
name: 'App',
components: { Son },
data() {
return { msg: 'father' };
},
methods: {
parentFun(val) {
console.log('val', val);
this.msg += val;
},
},
};
script>
<template>
<div class="son">
<button @click="parentFun(sonMsg)">点击将子组件的数据传递给父组件button>
div>
template>
<script>
export default {
name: 'Son',
props: ['parentFun'], // 设置 props 属性,接收方法
data() {
return { sonMsg: 'son' };
},
};
script>
{
// 基础类型检查
propA: Number, // 给出 `null` 和 `undefined` 值则会跳过任何类型检查
// 多种可能的类型
propB: [String, Number],
// 必传, 且为 String 类型
propC: {
type: String,
required: true
},
// Number 类型的默认值
propD: {
type: Number,
default: 100
},
// 对象类型的默认值
propE: {
type: Object,
// [对象] / [数组] 的默认值, 必须从一个工厂函数返回
// 该函数接收组件所接收到的原始 prop 作为参数
default(rawProps) {
return { message: 'hello' }
}
},
// 自定义类型校验函数
propF: {
validator(value) {
// The value must match one of these strings
// return false 则抛出警告 (开发模式下)
return ['success', 'warning', 'danger'].includes(value)
}
},
// 函数类型的默认值
propG: {
type: Function,
// 不像对象或数组的默认, 这不是一个工厂函数. 这会是一个用来作为默认值的函数
default() {
return 'Default function'
}
}
}
一些个细节
required: true
undefined
;Boolean 类型的未传递 prop 将被转换为 false
default: undefined
将与非布尔类型的 prop 的行为保持一致undefined
时,无论 prop 是未被传递还是显式指明的 undefined
,都会改为 default 值prop 的类型
type
也可以是自定义的类或构造函数,Vue 将会通过 instanceof
来检查类型是否匹配// 假设有 Person 类
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
defineProps({
author: Person, // 使用 Person 类约束类型
// Vue 会通过 instanceof Person 来校验 author prop 的值是否是 Person 类的一个实例
});
Boolean 类型转换
// 假设组件设置如下 props
defineProps({
disabled: Boolean,
});
<MyComponent disabled />
<MyComponent />
defineProps({
disabled: [Boolean, Number],
});