大家好,又见面了,我是你们的朋友全栈君。
Vue 使用props从父组件向子组件传递数据
通过props实现正向传递数据:父组件正向的向子组件传递数据或参数,子组件接收到后根据参数的不同来渲染不同的内容或者执行操作。
props使得父子之间形成了单向下行绑定:父级传递的数据的更新会向下流动到子组件中,但是反过来则不行。
(1)props的值有两种类型
使用选项props来声名需要从父级接收的数据,props的值有两种类型,一种是字符串数组,另外一种是对象。
1.数组
以字符串数组的形式列出props:
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
2.对象
如果希望每个 props 都有指定的类型的值。可以以对象形式列出 props,这些属性的名称和值分别是 props 各自的名称和类型:
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object
}
关于传入的数据的类型,下面会详细介绍。
(2)传递动态或静态的props
给props传递一个静态的值:
<div id="app">
<test title="我来自父组件!"></test>
</div>
<script> Vue.component('test', {
props: ['title'], template: '<div>{
{ title }}</div>' }); var app = new Vue({
el: "#app", }) </script>
渲染的结果为:
<div id="app">
<div>我来自父组件!</div>
</div>
props中传递的数据与data函数return的数据的主要区别是:props的数据来自父级,而data中的数据是组件自己的数据,作用域是组件本身。
这两种数据都可以用在模板template、计算属性computed和方法methods中。
由于HTML特性不区分大小写,当使用DOM模板时,驼峰命名的props名称要转为短横分隔命名:
<div id="app">
<test title-one="我来自父组件!"></test>
</div>
<script> Vue.component('test', {
props: ['TitleOne'], template: '<div>{
{ TitleOne }}</div>' }); var app = new Vue({
el: "#app", }) </script>
还可以使用v-bind传递动态的props值。这样的话,当父组件的数据变化时,也会实时更新到子组件:
<div id="app">
<test v-bind:title="abc"></test>
</div>
<script> Vue.component('test', {
props: ['title'], template: '<div>{
{ title }}</div>' }); var app = new Vue({
el: "#app", data:{
abc:"我是标题!" } }) </script>
在上述两个示例中,我们传入的值都是字符串类型的,但实际上任何类型的值都可以传给props:
1.传入一个数字
静态传值,传入的值总会转化为字符串:
<div id="app">
<test title="12"></test>
</div>
<script> Vue.component('test', {
props: ['title'], template: '<div v-on:click="dd">{
{ title }}</div>', methods:{
dd:function(){
console.log(typeof this.title)//string } } }); var app = new Vue({
el: "#app", }) </script>
所以要想达到传数字的效果,要使用v-bind动态传值:
<div id="app">
<test v-bind:title="abc"></test>
</div>
<script> Vue.component('test', {
props: ['title'], template: '<div v-on:click="dd">{
{ title }}</div>', methods:{
dd:function(){
console.log(typeof this.title)//number } } }); var app = new Vue({
el: "#app", data:{
abc:12 } }) </script>
2.传入一个布尔值
静态传值,传入的值总会转化为字符串。
也就是说,即使是”false”也会被当作true来处理,因为会被转化为字符串:
<div id="app">
<test bool="false"></test><!--true-->
</div>
<script> Vue.component('test', {
props: ["bool"], template: '<div v-on:click="dd">我是:{
{ bool }}</div>', methods: {
dd: function () {
if (this.bool) {
console.log("true") }else{
console.log("false") } } } }); var app = new Vue({
el: "#app", }) </script>
所以要想传入正确的布尔值,要采用动态赋值:
<div id="app">
<test v-bind:bool="false"></test><!--传入的bool的值为 false-->
</div>
<script> Vue.component('test', {
props: ["bool"], template: '<div v-on:click="dd">我是:{
{ bool }}</div>', methods: {
dd: function () {
if (this.bool) {
console.log("传入的bool的值为 true") }else{
console.log("传入的bool的值为 false") } } } }); var app = new Vue({
el: "#app", }) </script>
3.传入一个数组
静态传值,传入的值总会转化为字符串:
<div id="app">
<test arr="[1,3,4]"></test>
</div>
<script> Vue.component('test', {
props: ["arr"], template: '<div v-on:click="dd">我是:{
{ arr }}</div>', methods: {
dd: function () {
console.log(typeof this.arr)//string } } }); var app = new Vue({
el: "#app", }) </script>
传入正确的数组值,要采用动态赋值:
<div id="app">
<test v-bind:arr="[1,3,4]"></test>
</div>
<script> Vue.component('test', {
props: ["arr"], template: '<div v-on:click="dd">我是:{
{ arr }}</div>', methods: {
dd: function () {
console.log(typeof this.arr)//object } } }); var app = new Vue({
el: "#app", }) </script>
对于数组进行typeof类型检测,结果为object。
4.传入一个对象
静态传值,传入的值总会转化为字符串:
<div id="app">
<test obj="{
'one':1,'two':2}"></test>
</div>
<script> Vue.component('test', {
props: ["obj"], template: '<div v-on:click="dd">我是:{
{ obj }}</div>', methods: {
dd: function () {
console.log(typeof this.obj)//string } } }); var app = new Vue({
el: "#app", }) </script>
传入正确的对象类型,要采用动态赋值:
<div id="app">
<test v-bind:obj="{
'one':1,'two':2}"></test>
</div>
<script> Vue.component('test', {
props: ["obj"], template: '<div v-on:click="dd">我是:{
{ obj }}</div>', methods: {
dd: function () {
console.log(typeof this.obj)//object } } }); var app = new Vue({
el: "#app", }) </script>
5.传入一个对象的所有属性
如果想将一个对象的所有属性都传入子组件,可以使用v-bind直接传入一个对象:
<div id="app">
<test v-bind:obj="obj111"></test>
</div>
<script> Vue.component('test', {
props: ["obj"], template: ` <div> <div>{
{ obj.one }}</div> <div>{
{ obj.two }}</div> </div>`, }); var app = new Vue({
el: "#app", data: {
obj111: {
"one": 1, "two": 2 } } }) </script>
渲染结果为:
<div id="app">
<div>
<div>1</div>
<div>2</div>
</div>
</div>
(3)单向数据流
父级组件的数据发生更新时,子组件中所有的 props 都将会刷新为最新的值。
一般来说,不应该在子组件内部改变props的值,但是也有两种常见的在子组件内改变props的情形:
A.这个 props 用来传递一个初始值。子组件将它作为初始值保存起来,在自己的作用域下可以随意使用和修改。在这种情况下,最好定义一个本地的 data 属性并将这个 props 用作其初始值:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
B.这个传入的值以原始值传入且需要进行转换。在这种情况下,最好使用这个传入的原始值来定义一个计算属性:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 props 来说,在子组件中改变这个对象或数组本身将会影响到父组件中的数据:
<div id="app">
<test v-bind:obj="obj111"></test>
<div>这是父级:{
{obj111.one}}</div>
</div>
<script> Vue.component('test', {
props: ["obj"], template: '<div>这是子组件:{
{changeone}}</div>', computed:{
changeone:function(){
return ++this.obj.one } } }); var app = new Vue({
el: "#app", data: {
obj111: {
"one": 1 } } }) </script>
渲染结果为:
<div id="app">
<div>这是子组件:2</div>
<div>这是父级:2</div>
</div>
在子组件中,通过计算属性,将传入的值增加了1,因为对象是通过引用传入的,父子组件中的数据指向同一个内存空间。所以也会改变父组件中的数据。采用的是前置递增,子组件和父组件中的值都变为了2。
(4)数据验证
之前提到过props选项的值还可以是一个对象,可以用来作为数据验证。
可以为传入组件的props指定类型验证,例如:
Vue.component('my-component', {
props: {
// 必须是数字类型
propA: Number,
// 必须是数字或者字符串类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return {
message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
注意那些 props 会在一个组件实例创建之前进行验证,所以实例的属性 (如 data、computed 等) 在 default 或 validator 函数中是不可用的。
type 可以是下列原生构造函数中的一个:
String
Number
Boolean
Array
Object
Date
Function
Symbol
type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认。
例如,给定下列的构造函数:
function Person (firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
你可以使用:
Vue.component('blog-post', {
props: {
author: Person
}
})
来验证传入的author的值是否是通过 new Person 创建的。
(5)非props特性
一个非 props 特性是指传向一个组件,但是该组件并没有相应的props定义的特性。
组件可以接受任意的特性,而这些特性会被添加到这个组件的根元素上。
传入的特性可能会替换或者合并已有的特性:
<test> 的模板是这样的:
Vue.component('test', {
template: '<input type="data" class="left">',
});
在使用的时候:
<test class="up"></test>
对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值。
所以如果传入 type=“text” 就会替换掉 type=“date” 。
但是class 和 style 特性会把两边的值合并起来,从而得到最终的值:class=“left up”。
参考:
1.Vue.js官方文档
2.《Vue.js实战》
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/128014.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...