vue组件prop基础介绍

本文详细介绍了Vue2和Vue3中prop的使用规范,包括大小写转换、不同版本的组件注册、prop类型定义、动态绑定、验证机制以及单向数据流的实践示例。
摘要由CSDN通过智能技术生成

学习此内容前假定你已了解组件基础及注册,对组件的使用,组件全局注册,组件局部注册已有一定了解;

prop的大小写

HTML中的attribute(属性)名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用DOM中的模板时,camelCase(驼峰命名法)的prop名需要使用其等价的kebab-case(短横线分割法)命名;

vue2

//vue2 子组件 BlogPost.vue
<template>
<h3>{{postTitle}}</h3>
</template>
<script>
export default {
    props:['postTitle'],
    data(){
        return { }
    }
}
</script>

BlogPost为自定义子组件名;
postTitle为自定义prop属性名;
< blog-post post-title=“hello!”></ blog-post>;post-title属性设置静态数据hello!;如需设置动态值,可使用v-bind指令

//vue2 父组件index.vue
/*父组件*/
<template>
<div class="index-main">
	<blog-post post-title="hello!"></blog-post>
</div>
</template>
<script>
import blog-post from '../components/BlogPost';//普通组件
export default {
	components:{
	     'blog-post': blog-post
	},
	data(){
	   return {}
	}
}
</script>

vue3

//vue3子组件使用setup BlogPost.vue
<script setup>
defineProps(['postTitle'])
</script>
<template>
<h3>{{postTitle}}</h3>
</template>
//vue3 不使用setup
<script>
export default {
  props: ['postTitle'],
  setup(props) {
    console.log(props.postTitle)
  }
}
</script>
<template>
<h3>{{postTitle}}</h3>
</template>

传递给 defineProps() 的参数和提供给 props 选项的值是相同的,两种声明方式背后其实使用的都是 prop 选项

//父组件 index.vue
<script setup>
import {ref, reactive } from 'vue';
import BlogPost '@/components/BlogPost.vue'
</script>
<template>
<div class="index-main">
	<BlogPost post-title="hello!"></BlogPost>
</div>
</template>

prop类型及验证

当只定义prop名称,不定义类型时,我们常以数组的形式列出prop;

  • 一个组件可以有任意数量的prop
  • prop被注册后,就可以把数据作为一个自定义属性传递进来;例如父组件的title、num、show等
  • 父组件可以传递静态数据,也可以传递动态prop;
  • prop类型可以是原生构造函数中的一个(String、Number、Boolean、Array、Object、Date、Function、Symbol),还可以是一个自定义的构造函数;
  • 所有prop默认都是可选的,除非声明了required:true
  • 除 Boolean 外的未传递的可选 prop 将会有一个默认值 undefined
  • 当 prop 的校验失败后,Vue 会抛出一个控制台警告 (在开发模式下)

数组形式的多个prop

//vue2子组件 MyComponent.vue
props:['title','likes','isShow'...]

//vue3子组件 MyComponent.vue
defineProps(['btnColor','title','msg']);

//在父组件中使用
<my-component title="传递静态标题" :is-show="true"></my-component>

prop对象的形式指定单个类型

//vue2
props:{
	title: String,//字符串类型
	likes: Number,//Number类型
	isShow: Boolean,//布尔类型
	commentIds: Array,
    author: Object,
    callback: Function,
}
//vue3
<script setup>
defineProps({
	title: String,//字符串类型
	likes: Number,//Number类型
	isShow: Boolean,//布尔类型
	commentIds: Array,
    author: Object,
    callback: Function,
})
</script>

设置多个类型

//vue2
props:{
	title: [String, Number]
}
//vue3
defineProps({
	title: [String, Number]
})

设置必填

//vue2
props:{
	title: {
		type: [String, Number],
		required: true
	}
}
//vue3
defineProps({
	title: {
		type: [String, Number],
		required: true
	}
})

设置默认值

//vue2
props:{
	title: {
		type: [String, Number],
		default: '默认标题'
	}
	//对象或数组的默认值必须从一个工厂函数获取
	obj:{
		type: Object,
		detault: function(){
			return {
				message:'hello'
			}
		}
	}
}
//vue3
defineProps({
	title: {
		type: [String, Number],
		default: '默认标题'
	},
	//对象或数组的默认值必须从一个工厂函数获取
	obj:{
		type: Object,
		detault(){
			return {
				message:'hello'
			}
		}
	}
})

自定义检验函数

//vue2
props:{
	state: {
		validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].includes(value)
      }
	}
}
//vue3
<script setup>
defineProps({
	 // 在 3.4+ 中完整的 props 作为第二个参数传入
	state: {
		validator(value, props) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].includes(value)
      }
	}
})
</script>

type设置自定义构造函数

//vue2
function Person (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}
//来验证 author prop 的值是否是通过 new Person 创建的
props: {
    author: Person
}

布尔类型转换

当一个 prop 被声明为允许多种类型时,Boolean 的转换规则也将被应用。然而,当同时允许 String 和 Boolean 时,有一种边缘情况——只有当 Boolean 出现在 String 之前时,Boolean 转换规则才适用

//vue2 MyComponent.vue子组件
props:{
	isShow: Boolean,//布尔类型
}
//vue2 父组件
<!-- 等同于传入 :disabled="true" -->
<my-component disabled></my-component>

<!-- 等同于传入 :disabled="false" -->
<my-component></my-component>
//vue3 MyComponent.vue子组件
defineProps({
  disabled: Boolean
})
//vue3 父组件中使用子组件
<!-- 等同于传入 :disabled="true" -->
<MyComponent disabled />

<!-- 等同于传入 :disabled="false" -->
<MyComponent />
// disabled 将被转换为 true
defineProps({
  disabled: [Boolean, Number]
})
  
// disabled 将被转换为 true
defineProps({
  disabled: [Boolean, String]
})
  
// disabled 将被转换为 true
defineProps({
  disabled: [Number, Boolean]
})
  
// disabled 将被解析为空字符串 (disabled="")
defineProps({
  disabled: [String, Boolean]
})

prop应用实例及特点

prop使得父组件与子组件之间形成一个单项下行绑定;父组件绑定的属性值更新时会向下流动到子组件,但反过来不行;

外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

子组件中的prop仅用于展示,而不能更改;

注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。

注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的。

1.1、vue2

/*子组件*/
<template>
  <div class="test-child" title="标题">
       <p>字符串:{{tit}}</p> 
       <!-- 默认非prop属性在根元素继承,即div,如果其他标签想要继承,需要使用v-bind="$attrs" -->
       <p>数字:{{num}}</p>
       <p>布尔:{{show}}
           <span v-if="show">显示</span>
           <span v-else>隐藏</span>
       </p>
       <p>数组:{{arr}}</p>
       <p>对象:{{obj}}</p>       
  </div>
</template>
<script>
export default {
    inheritAttrs: true,  //禁用 Attribute 继承,如果为true,根元素的div的title="标题"会被父组件的值替换
    props:{
        title: {
            type: String,
            default: '字符串'
        },
        num: {
            type: Number,
            default: 1024
        },
        show:Boolean,
        arr: Array,
        obj: {
            type: Object,
            // 对象或数组默认值必须从一个工厂函数获取
            default: function () {
                return { message: 'hello' }
            }
        }
    },
    data(){
        return {
        
        }
    }
}
</script>
/*父组件*/
<template>
<div class="main">
	<P>组件的传值 父组件传值</P>
	<test-child title="标题">传递静态值</test-child> 
    <test-child :title="tit">传递data中动态值</test-child> 
    <test-child :num="100">传递静态值</test-child>
    <test-child :num="num">传递静态值</test-child>
    <test-child :show="false"></test-child>
    <test-child :show="isshow"></test-child>
     <!-- 传入数组和对象 -->
    <test-child title="标题" :num='1000' show :arr="['a','b']" :obj="{id:1,title:'标题'}">子组件</test-child>
    <!-- 传入一个对象的所有属性值,post中的属性对应子组件的prop -->
    <test-child v-bind="post"></test-child>
    <!--
    等价于
    <test-child v-bind:tit="post.tit" v-bind:num="post.num"></test-child>
    -->
</div>
</template>
<script>
import testChild from '../components/test-child';//普通组件
export default {
	components:{
	     'test-child': testChild
	},
	data(){
	   return {
		   	tit: '动态标题,可修改',
	   		num:520,
	   		isshow:true,
	   		post:{
	        	num: 1,
	        	tit: '标题'
	        }
	   }
	}
}
</script>

1.2、vue3

/*子组件*/
<template>
	<div class="test-child" title="标题">
	   <p>字符串:{{title}}</p> 
	   <p>数字:{{num}}</p>
	   <p>布尔:{{show}}
		   <span v-if="show">显示</span>
		   <span v-else>隐藏</span>
	   </p>
	   <p>数组:{{arr}}</p>
	   <p>对象:{{obj}}</p>       
	</div>
</template>

<script setup>
	const props = defineProps({
		title:{
			type: String,
			// required: true,
			default: "字符串"
		},
		num:{
			type: Number,
			default: 1024
		},
		show: Boolean,
		arr: Array,
		obj:{
			type: Object,
			default: ()=>{
				return { message: 'hello' }
			}
		}
	});
</script>
/*父组件*/
<script setup>
import {ref} from 'vue';

const tit = ref('动态字符串');
const num = ref(25421);
const isshow = ref(true);
const post = ref({
	title:'组件标题',
	num:987654321,
	show: true,
	arr:['12','34'],
	obj:{name:'张三',age:18}
});

onMounted(()=>{
	console.log('mounted生命周期');
})
</script>

<template>
	<div class="index-main">
		<!-- <TestChild title="标题">传递静态值</TestChild> -->
		<!-- <TestChild :title="tit">传递data中动态值</TestChild> -->
		<!-- <TestChild :num="100">传递静态值</TestChild> -->
		<!-- <TestChild :num="num">传递动态值</TestChild> -->
		<!-- <TestChild :show="false"></TestChild> -->
		<!-- <TestChild :show="isshow"></TestChild> -->
		 <!-- 传入数组和对象 -->
		<!-- <TestChild title="标题" :num='1000' show :arr="['a','b']" :obj="{id:1,title:'标题'}">子组件</TestChild> -->
		<!-- 传入一个对象的所有属性值,post中的属性对应子组件的prop -->
		<TestChild v-bind="post"></TestChild>
		<!--
		等价于
		<TestChild v-bind:tit="post.tit" v-bind:num="post.num"></TestChild>
		-->
	</div>
</template>

prop单向数据流举例

当子组件需要使用prop值并进行修改时,可在data中定义一个属性,将prop的值传递给本地属性修改本地属性值;

//vue2 错误写法
props: ['initialCounter'],
data: function () {
  return { }
},
methods:{
	btnHandle(){
		this.title = '修改title'
	},
},
//vue2 正确写法
props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
},
methods:{
	btnHandle(){
		//正确写法
		this.msg = '修改msg';
	},
},
//vue2 当需要使用原始传入值进行转换,建议使用计算属性
props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}
//vue3
<script setup>
const props = defineProps(['initialCounter'])
const counter = ref(props.initialCounter)
</script>
//vue3
const props = defineProps(['size'])
// 该 prop 变更时计算属性也会自动更新
const normalizedSize = computed(() => props.size.trim().toLowerCase())
  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值