props配置
看个school.vue 学校的组件:
<template>
<div class="demo">
<h1>{{msg}}</h1>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<h2>办学时长:{{year}}</h2>
</div>
</template>
<script>
export default{
name:'schoolInfo',
data(){
return{
msg:'欢迎学习Vue',
schoolName:'51cto',
address:'北京',
year:20
}
}
}
</script>
要想复用 school.vue 组件,可以在 app.vue 中多写几个 school 组件标签:
<template>
<div>
<school/>
<school/>
</div>
</template>
<script>
//引入组件
import school from './components/school.vue'
export default{
name:'app',
components:{school}
}
</script>
在 app.vue 中复用了一次:

现在有个需求:即复用 school.vue ,还可以改变输出的内容?
props 简单声明接收
这就可以引入 props 配置了,具体改动两个地方:
app.vue 组件中:
<template>
<div>
<school schoolName="51cto" address="北京" year="21"/>
<school schoolName="baidu" address="上海" year="25"/>
</div>
</template>
提示:在 app.vue 组件中,给 school 标签添加数据,就像是在传参;
在 school.vue 组件中:
<template>
<div class="demo">
<h1>{{msg}}</h1>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<h2>办学时长:{{year}}</h2>
</div>
</template>
<script>
export default{
name:'schoolInfo',
data(){
return{
msg:'欢迎学习Vue',
}
},
props:['schoolName','address','year'] // 简单声明接收
}
</script>
引入 props 的数组写法,把各数据放到数组里面;
看效果:

这样即实现了组件的复用,还实现了不同数据的呈现;
看下 Vue Devtools :分别查看两个 school 组件的数据;


使用 Vue Devtools 是不能修改这里的属性值的;
props 限制数据类型
除了数组形式的简单接收,还有一种对象式限制数据类型的方式;
再改下 school.vue 组件:
<template>
<div class="demo">
<h1>{{msg}}</h1>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<h2>办学时长:{{year}}</h2>
</div>
</template>
<script>
export default{
name:'schoolInfo',
data(){
return{
msg:'欢迎学习Vue',
}
},
// props:['schoolName','address','year']
// 限制数据类型
props:{
schoolName:String,
address:String,
year:Number // 限制数据类型
}
}
</script>
提示:这里把 year 的数据类型改为 Number ,这就要求 app.vue 传来的 year 数据类型是 Number,否则会报错:

Vue 报错了,无效属性:属性"year"的类型检查失败;预期是 Number 类型的值 21,得到的却是字符串类型的 "21"。
解决办法,在传数据的 app.vue 中,加一个 "v-bind" 指令:
<template>
<div>
<school schoolName="51cto" address="北京" v-bind:year="21"/>
<school schoolName="baidu" address="上海" :year="25"/>
</div>
</template>
v-bind:
也可以简写成 :
,效果一样;
加了绑定指令后,属性值将变成表达式,传递过去的类型也变成了 Number,效果也就正常了。
props 完整写法
props 还有个完整的写法:设置类型、必要性和默认值;
<template>
<div class="demo">
<h1>{{ msg }}</h1>
<h2>学校名称:{{ schoolName }}</h2>
<h2>学校地址:{{ address }}</h2>
<h2>办学时长:{{ year }}</h2>
</div>
</template>
<script>
export default {
name: "schoolInfo",
data() {
console.log(this);
return {
msg: "欢迎学习Vue",
};
},
// props:['schoolName','address','year']
// props:{
// schoolName:String,
// address:String,
// year:String
// }
// props 完整写法,带3个配置项
props: {
schoolName: {
type: String, // name 类型限制了字符串
required: true, // name 是必要的
},
year: {
type: Number,
default: 20, // 默认值
},
address: {
type: String,
required: false,
}
},
};
提示:完整写法,可以配置数据类型、必传项和默认值三个选项;
数据类型:如果不相符,会报错;
必传项:为 true 为必传数据,为 false 是可传可不传;
默认值:如果没有传数据,则数据为默认值;
required 和 default 两个选项,只写一个就行:意思是,如果是必传项了,就没必要再有默认值了,如果不是必传项的,就设置个默认值;
如果数据类型不对:数据类型跟限制的不相符,会报错;

报错,属性"year"的类型检查失败;预期是 Number 类型的值 21,得到的却是字符串类型的 "21"。
如果必传项没有数据:该传的不传,会收到报错;

报错,缺少必要的属性;
如果是有默认值的:即使不传数据,也会被赋为默认值;
props 传值属性一致性
是说在 app.vue 组件中,传递来的属性,在 school.vue 组件中接收时,要能对应的上;
避免出现传来的属性中, pops 没有声明或者声明了更多不存在的数属性:
props:['schoolName','address','year','leader','count']
比如:app.vue 中传来的只有前三个属性的话,后面的两个属性就不要再添加了,否则,可能导致 Vue 的混乱;
props 属性不能使用关键字
部分Vue的关键字,是不能使用的,比如: key 、 ref 都是被 Vue征用的;
<template>
<div>
<school schoolName="51cto" address="北京" year="20" key="1"/>
<school schoolName="baidu" address="上海" year="25" ref="school" />
</div>
</template>
这种是不行的;
操作传来属性值
props 声明的属性,接收到传来的值,是不能被修改的,上面也已经提到;
如果业务需求是需要操作这些属性值的话,该怎么处理呢?
可以在 data 中声明一个属性,再使用 methods 方法操作 props 属性值,并给 data 中的新属性就可以了;
先改下 app.vue 组件:
<template>
<div>
<school schoolName="51cto" address="北京" :year="20"/>
<school schoolName="baidu" address="上海" :year="25"/>
</div>
</template>
提示:组件的 script 一直没动,所以不写了,只绑定 year 属性,让传递的值变为表达式,参与累加计算;
再改下 school.vue 组件:
<template>
<div class="demo">
<h1>{{ msg }}</h1>
<h2>学校名称:{{ schoolName }}</h2>
<h2>学校地址:{{ address }}</h2>
<h2>办学时长:{{ count }}</h2>
<button @click="addCount">点击按钮累加办学时长</button>
</div>
</template>
<script>
export default {
name: "schoolInfo",
data() {
return {
msg: "欢迎学习Vue",
count: this.year
};
},
methods:{
addCount(){
this.count++
}
},
props:['schoolName','address','year']
};
</script>
提示1:使用了简易声明的 props ;
提示2:在 data 中新建了 count 来接收传来的属性值,同时模板插值中也要把 year 改成新属性 count;
提示3:新建 methods 方法,通过 addCount() 方法来实现累加;
看下效果:

这样就实现了,组件的复用,传递不同的数据,还能操作这些数据了;
【props 总结】
功能:让组件接收外部传过来的数据;
1) 传递数据 : <Demo name="xxx" />
2) 接收数据:
1、第一种方式(只接收):
2、第二种方式(限制类型):
3、第三种方式(限制类型、限制必要性、指定默认值)
props:{
name:{
type:String, // 类型
required:true, // 必要性
default:'jack' // 默认值
}
}
备注:props 是只读的,Vue 底层会监测你对 props 修改,如果进行了修改,就会发出警告,若业务需要确实需要修改,那么请复制 props 的内容到 data 中一份,然后再修改 data 中的数据 ;