Vue中用props给data赋初始值遇到的坑

本文介绍了一种在Vue中通过父组件传递不同值给子组件,并利用这些值动态控制子组件内元素显示隐藏的方法。文章对比了两种实现方式,最终推荐了一种更优的方案,同时介绍了如何正确使用watch监听变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

情景:
我想在父组件用props传值给子组件几个值来控制子组件中对应的几个类目的显示和隐藏,几个类目是子组件中通过data里的一个数组的数据循环出来的,所以一开始我想在子组件那个数组中添加一个公共的属性名,值就取拿回来的props值,在dom里通过这个新增的属性的取值(也就是传回来的props值)动态的控制几个类目展示不展示即可,然后就掉坑里了。。。。。

父组件:
     <child 
		:first="first"			// 传值给子组件的值
		:second="second"
		:third="third"
		>
     </child>

	data(){
		return{
			first:1,			//data中初始化数据
			second:1,
			third:1
	}
}

	methods:{
		getData(params)				//请求接口数据给传的参赋值
		       .then((response)=>{
			this.first = response.first
			this.second = response.second
			this.third = response.third
})
}
子组件:
	//dom结构通过取到的props值来控制类目的隐藏显示
	<div v-for="(item,index) in sideData" :key="index">
		<div :style="{display:item.status==0 ? 'none': 'block'}">{{item.name}}</div>
	</div>
	
	props:{
		first:{
		  type:Number,
		  default:function(){
		    return 0
		  },
		},
		second:{			//second、third和first同理
		},
		third:{
		},
}
	data(){
	  return{
		 sideData:[
			{
				name:'1',
				status:first,			//新起的一个属性名,并且拿取到的props赋值
			},
			{
				name:'2',
				status:second,	
			},
			{
				name:'3',
				status:third,	
			},
				]
		}
	}

结果:

发现子组件的类目并不会随着props的变化而变化,结果并不能达到预期,是因为在data中声明局部变量,并用props初始化,局部变量不随着props更新而更新
我换了种方法实现并实现一些优化,亲测有效!!!

父组件:
	<child 
		:content="content"		//把多个数据放到一个数组中一起传
		>
     </child>

	data(){
		return{
			content:[{'1',isShow},{'2',isShow},{'3',isShow}]
	}
}

	methods:{
		getData(params)				
		       .then((response)=>{
			this.content.map((item,index)=>{	//遍历要传参的这个数组,满足对应条件给赋值
			  if('满足对应的条件'){
			  	this.content[index].isShow = false
			  }
			})
})
}

子组件:
	<div v-for="(item,index) in sideData" :key="index">
		<div :style="{display:item.isShow == true ? 'block': 'none'}">{{item.name}}</div>
	</div>
	
	props:{
		content:{
		  type:Array,
		  default:function(){
		    return []
		  },
		},
}
	data(){
	  return{
		 sideData:[
			{
				name:'1',
				isShow:true,			// 统一添加一个公共的属性名
			},
			{
				name:'2',
				isShow:true,,	
			},
			{
				name:'3',
				isShow:true,	
			},
				]
		}
	}

	watch:{
		handler(newVal){
			let arr = [...this.sideData];	//这步是为了避免修改新对象数组改变原对象数组
			arr.map((item)=>{
				newVal.map((_item)=>{
				  if(item.id == _item.id){
				     item = _item
				  }
				})
			})
			this.sideData = [...arr]
		},
		deep:true
		immediate:true
}

结论:

注意

  • 在data中声明局部变量,并用props初始化,局部变量不随着props更新而更新
  • 使用watch、computed 监听和计算,转换后输出
  • 赋值的时候,记得不要改变原数组
<think>嗯,用户之前问过关于Vue 2中Element UI的el-form组件里ref的作用,现在又问Vue 3中使用ref引用组件后的用途。我需要先回顾一下之前的对话,确保这次回答保持一致,同时覆盖Vue 3的新特性。 用户可能已经了解Vue 2中的ref用法,现在想迁移到Vue 3或者学习Vue 3的新内容。Vue 3的Composition API引入了新的ref和reactive函数,但这里用户问的是模板中ref属性引用组件的情况,可能涉及到Options API和Composition API两种写法。 首先,要明确在Vue 3中,无论是使用Options API还是Composition API,模板中的ref属性仍然用于引用组件实例或DOM元素。不过,在Composition API中,声明ref的方式有所不同,需要使用ref函数来创建响应式引用。 需要解释在Vue 3中,用ref引用组件后,可以访问子组件的属性、方法,以及触发事件等。同时,Vue 3的组件实例可能暴露不同的属性,比如通过defineExpose显式暴露的内容,这和Vue 2有所不同,Vue 2默认暴露更多属性。 用户可能想知道在Vue 3中使用ref引用组件的具体应用场景,比如调用子组件方法、访问数据、或者与第三方库集成。需要举例说明,比如表单验证、触发子组件函数等。 另外,用户可能在之前的对话中提到过父组件和子组件中没有显式定义ref的变量名,所以需要强调ref是Vue管理的,不需要在data中声明,这在Vue 3中仍然适用。 还要注意Vue 3中的ref在Composition API中的使用方式,比如在setup函数中使用ref变量,并通过return暴露给模板。可能需要对比Options API和Composition API的写法差异。 用户可能有疑问,为什么有时访问不到子组件的方法或属性,这可能涉及到Vue 3中组件暴露的机制,即需要使用defineExpose来显式暴露,而Vue 2是默认暴露的。这部分需要详细说明,避免用户在使用时遇到问题。 最后,需要总结Vue 3中使用ref引用组件的主要用途,强调其重要性和常见应用场景,确保用户能够理解并应用到实际开发中。</think>在 Vue 3 中,使用 `ref` 引用组件或 DOM 元素的主要目的是**直接访问组件实例或 DOM 节的属性和方法**。通过 `ref`,你可以在父组件中操作子组件、调用子组件的方法,或者直接与 DOM 元素交互。以下是具体用途和示例: --- ### **核心作用** #### 1. **访问子组件的属性和方法** - 如果子组件通过 `defineExpose` 显式暴露了属性或方法,父组件可以通过 `ref` 直接调用它们。 - **示例**:父组件调用子组件的 `validate` 方法触发表单验证。 #### 2. **操作 DOM 元素** - 直接操作 DOM 元素(如聚焦输入框、修改样式等)。 - **示例**:通过 `ref` 让输入框自动聚焦。 #### 3. **集成第三方库** - 需要直接操作 DOM 或第三方库时(如地图、图表库),`ref` 可以获取 DOM 节的引用。 - **示例**:在 `canvas` 元素上绘制图表。 #### 4. **组件间通信** - 父组件通过 `ref` 直接调用子组件方法,替代 `props` 和 `$emit` 的间接通信。 - **示例**:父组件直接重置子组件的表单数据。 --- ### **Vue 3 中的 `ref` 使用方式** 在 Vue 3 中,`ref` 可以在 **Options API** 或 **Composition API** 中使用,语法略有不同: #### **Options API(传统写法)** ```vue <template> <!-- 引用子组件 --> <ChildComponent ref="childRef" /> <!-- 引用 DOM 元素 --> <input ref="inputRef" /> </template> <script> export default { mounted() { // 访问子组件实例 this.$refs.childRef.someMethod(); // 操作 DOM 元素 this.$refs.inputRef.focus(); } } </script> ``` #### **Composition API(推荐写法)** ```vue <template> <!-- 引用子组件 --> <ChildComponent ref="childRef" /> <!-- 引用 DOM 元素 --> <input ref="inputRef" /> </template> <script setup> import { ref, onMounted } from 'vue'; // 创建 ref(注意:变量名需与模板中的 ref 同名) const childRef = ref(null); // 子组件实例 const inputRef = ref(null); // DOM 元素 onMounted(() => { // 访问子组件实例 childRef.value.someMethod(); // 操作 DOM 元素 inputRef.value.focus(); }); </script> ``` --- ### **关键注意事项** #### 1. **子组件需显式暴露方法(Composition API)** - 在子组件中,如果使用 `<script setup>`,需要通过 `defineExpose` 暴露方法或属性,父组件才能访问。 ```vue <!-- 子组件 ChildComponent.vue --> <script setup> const validate = () => { console.log('子组件的验证方法被调用'); }; // 显式暴露方法 defineExpose({ validate }); </script> ``` #### 2. **`ref` 的初始值为 `null`** - 在组件挂载前(如 `setup` 或 `created` 阶段),`ref` 的值是 `null`,需在 `onMounted` 或之后访问。 #### 3. **避免滥用 `ref`** - 优先使用 `props` 和 `emit` 进行组件间通信,`ref` 应作为“逃生舱”在必要时使用。 --- ### **常见场景示例** #### 1. **调用子组件方法** ```vue <!-- 父组件 --> <template> <ChildComponent ref="childRef" /> <button @click="callChildMethod">触发子组件方法</button> </template> <script setup> import { ref } from 'vue'; const childRef = ref(null); const callChildMethod = () => { childRef.value.validate(); // 调用子组件的 validate 方法 }; </script> ``` #### 2. **DOM 元素操作** ```vue <template> <input ref="inputRef" placeholder="自动聚焦" /> </template> <script setup> import { ref, onMounted } from 'vue'; const inputRef = ref(null); onMounted(() => { inputRef.value.focus(); // 输入框自动聚焦 }); </script> ``` #### 3. **集成第三方库(如图表)** ```vue <template> <canvas ref="chartRef"></canvas> </template> <script setup> import { ref, onMounted } from 'vue'; import { Chart } from 'chart.js'; const chartRef = ref(null); onMounted(() => { new Chart(chartRef.value, { /* 图表配置 */ }); }); </script> ``` --- ### **总结** - **`ref` 的核心用途**:直接操作子组件或 DOM 元素。 - **Vue 3 的改进**:在 Composition API 中通过 `ref()` 函数声明引用,子组件需通过 `defineExpose` 暴露内容。 - **适用场景**:表单验证、DOM 操作、集成第三方库等需要直接控制的场景。 合理使用 `ref` 可以简化代码,但过度依赖可能导致组件耦合,建议优先使用 Vue 的响应式数据流(`props`/`emit`)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值