Vue组件的props配置
简单来讲: 让组件能够接收外部传来的数据
1. 简单案例
1.1 案例演示
现在有个需求,我定义了一个组件Table(将定义的allDatas展示为表格)
<template>
<div>
一个列表组件
<table>
<thead>
<tr>
<th colspan="3">{{ tableTitle }}</th>
</tr>
<tr>
<th v-for="tableHead in Object.keys(allDatas[0])">
{{ tableHead }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="tableRowData in allDatas" :key="tableRowData.id">
<td v-for="tableColData in Object.values(tableRowData)">
{{ tableColData }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: "User",
data() {
return {
tableTitle: "用户列表",
allDatas: [
{
id: 1,
name: '小明',
age: 20,
},
{
id: 2,
name: '张三',
age: 16,
},
{
id: 3,
name: '李华',
age: 19,
},
{
id: 4,
name: '王五',
age: 17,
},
]
}
},
}
</script>
<style>
table {
border-width: 6px;
border-collapse: collapse;
width: 200px;
text-align: center;
}
table th, table td {
border: solid 1px;
}
</style>
此时,渲染后的HTML是这样的
1.2 需求分析
现在我想做的是,把这个表格的显示,作为一个可变的引入,任何的Vue调用我这个组件,只要传入了这样的表格,就能够正常渲染,说白了就是,我现在写的是用户列表,你下次调用一个学校列表,只要把参数给我,我就能渲染
而Vue,为我们提供了props配置,让我们的组件,能够去接收外部的数据
2. 实现需求
2.1 定义一个School组件
现在我定义School组件
School.vue
<template>
<!-- 通过给List组件,绑定v-bind指令,即可实现数据的传参 -->
<List :tableTitle="tableTitle" :allDatas="allDatas"></List>
</template>
<script>
import List from "@/components/List.vue";
export default {
name: "School",
data() {
return {
tableTitle: "学校列表",
allDatas: [
{
id: 1,
name: '老八大学',
area: '50000m²',
},
{
id: 2,
name: '牛马大学',
area: '80000m²',
},
]
}
},
components:{List}
}
</script>
<style scoped>
</style>
2.2 定义List组件的props(精简定义)
原本的List组件,就不能把数据定义死了,而是要定义在props参数中
<template>
...省略
</template>
<script>
export default {
name: "List",
// 定义props就不要在data中再额外定义了,不然会报错
props:['tableTitle','allDatas']
// 这里需要定义需要接收的参数,这里需要是数组形式
}
</script>
2.3 注意事项
List组件,其实在这里类似于一个"抽象基类",可以给他继续喂东西,我们后续"继承"它的模板,但是不要将数据写死,所以我们尽量将用到的数据全部都放在props
2.4 props指定数据的类型
上面的数据,我们并没有涉及到数据的增加/变化,如果我们需求是这样的:
现在必须规定传入的参数是一个数字类型,传入其他类型,就报错
这个时候,我们简单的props就不行了,需要使用完整版props定义
<script>
export default {
name: "Demo",
props:{
num:Number, // 指定num的类型,必须是Number
name:String // 指定name的类型,必须是字符串
}
}
</script>
此时,如果我们数据的类型,传错,会出现什么情况呢?
<Demo num="10" :name="6"></Demo>
注意:我这里的num=10没有使用v-bind,但是name使用了v-bind,所以等同于传入了以下
- num = “10” // 字符串
- name = 6 // 数字
和要求的传入,刚好相反,所以控制台报错
但是数据还是能显示的,但是既然定义了类型就不要出这种小错误!!!
2.5 props的数据验证(完整配置)
如果我们还需要定义,参数必须传,或者参数的默认值,或者需要满足什么要求,可以使用完整配置
<script>
export default {
name: "Demo",
props:{
num:{
type:Number, // 数字类型
required:true, // 表明该参数必传!
validator:function(value){
return value <50? true :false // 约束传入的值,必须小于50
}
},
name:{
type:String, // 字符串类型
default:"未知姓名" // 定义默认值,不要和required同时出现
}
}
}
</script>
3. props的单向数据流(重中之重)
props传入的参数,本质上应该是只读类型,虽然可以更改,但是我们不要更改,否则会让Vue出现异常!
3.1 案例演示
我这样来实现案例:
- 定义一个组件,需要传入num
- 点击按钮会让传入的num+1
<template>
<div>
<div>num的值:{{ num }}</div>
<button @click="num++">点下加1</button>
</div>
</template>
可以发现,虽然值也确实增加了,但是一直报错
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "num"
意思就是,让我们不要直接修改组件传入的值,让我们用中转变量接着修改
3.2 中转变量实现修改数据
先看原本的方案:
<template>
<div>
<div>num的值:{{ num }}</div>
<button @click="num++">点下加1</button>
</div>
</template>
<script>
export default {
name: "Demo",
props: {
num: Number, // 指定num的类型,必须是Number
}
}
</script>
使用中转变量
<template>
<div>
<div>num的值:{{ myNum }}</div> // 这里使用中转变量
<button @click="myNum++">点下加1</button>
</div>
</template>
<script>
export default {
name: "Demo",
data() {
return {
myNum: this.num // 通过中转变量实现数据修改
,
}
},
props: {
num: Number, // 指定num的类型,必须是Number
}
}
</script>
此时,浏览器则不再报错!