代碼在文末,均可直接復制使用
本文主要描述,父子組件傳值、調用等問題
文章目錄
- 問題1:子組件接收不到父組件傳值
- 問題2:子組件接受的值,修改后,發現父組件值也改變了
- 問題3:子組件接受值,修改后頁面不更新
- 問題4:子傳父事件,父組件接受值,賦值無效
- 5、子傳父
- 6、父調用子
- 7、代碼
問題1:子組件接收不到父組件傳值
如果父組件的值,在onMounted時候賦值,或者是接口等異步賦值,那子組件直接拿不到修改的值。子組件需要使用watch監聽。
搜索子組件son.vue的watch查看
問題2:子組件接受的值,修改后,發現父組件值也改變了
如果不想改變,需要在子組件接受時候,進行深拷貝賦值。建議都是以深拷貝,如果想改父組件的值,就單獨子傳父事件修改
問題3:子組件接受值,修改后頁面不更新
在子組件接受簡單數據類型時候,改成ref接受,生成響應式數據
具體查看: let num1VALUE = ref(props.num1) // 生成響應式數據 否則修改數據 頁面不變化
問題4:子傳父事件,父組件接受值,賦值無效
這是因為你父組件的那個變量,是使用reactive聲明的。reactive 不要直接變量data=賦值!!!會丟失響應式的。如果用ref就不會 非要賦值要不就使用單個屬性一個個賦值 obj.屬性 = 屬性值 、要不就給原對象多包裹一層對象
由此可見:聲明盡量用ref。。。。
5、子傳父
搜索
update:obj
查看。
6、父調用子
搜索
sonRef.value.childMethod()
查看
7、代碼
父組件far.vue
<template><div><div>父:{{ state.str1 }}--{{ state.data1 }}--{{ obj1 }} -- {{ num1 }}</div><button style="border: 1px solid cyan;" @click="callChildMethod">父調子事件</button><hr><son ref="sonRef" :str1="state.str1" :data1="state.data1" :obj1="obj1" :num1="num1" @update:obj="getObj" /></div>
</template><script>
import { defineComponent, onMounted, reactive ,toRefs,ref} from 'vue'
import Son from './son.vue'export default defineComponent({components: {Son},setup() {const state = reactive({str1: '',data1: {}})let obj1 = reactive({a:1,})let num1 = ref(1)// 父接受子function getObj(val){obj1.a = val.a // reactive 不要直接data=賦值!!!會丟失響應式的,如果用ref就不會 非要賦值要不就使用 obj.屬性 = 屬性值 要不就給原對象多包裹一層對象// obj1 = val// obj1 = reactive({...val})console.log('父接受子',val,obj1);}// 父調用子事件const sonRef = ref(null)function callChildMethod() {sonRef.value.childMethod()}onMounted(() => {// 對于在onMounted或異步的數據 傳遞給子組件 子組件應該使用watch監聽接受 否則拿不到數據setTimeout(() => {state.str1 = '二次賦值!'state.data1 = {name: 'Alice',age: 25}}, 1000);})return {state,obj1,num1,sonRef,getObj,callChildMethod}}
})
</script>
子組件son.vue
<template><div><div>子:{{ state.str1VALUE }}--{{ state.data1VALUE }}--{{ obj1VALUE }} -- {{ num1VALUE }}</div><button style="border: 1px solid cyan;" @click="setVal">按鈕該值</button><button style="border: 1px solid cyan;" @click="setFarVal">子傳父</button></div>
</template><script>
import { defineComponent, reactive, watch,toRefs,toRef,ref } from 'vue'export default defineComponent({props: {str1: String,data1: Object,obj1: Object,num1: Number,},emits: ['update:obj'],setup(props, { emit }) {const state = reactive({str1VALUE: '',data1VALUE: {}})let obj1VALUE = JSON.parse(JSON.stringify(props.obj1)) // 復雜數據類型obj如果不用深拷貝賦值 修改對象obj.name單一屬性時候(state.data1VALUE.age = 33) 會導致父組件的源值改變 也會導致監聽事件再次執行let num1VALUE = ref(props.num1) // 生成響應式數據 否則修改數據 頁面不變化// 同時監聽str1和data1 對于在onMounted或異步的數據 傳遞給子組件 子組件應該使用watch監聽接受 否則拿不到數據watch([() => props.str1, () => props.data1], ([str1, data1]) => {console.log('監聽',str1,data1);state.str1VALUE = JSON.parse(JSON.stringify(str1)) // 復雜數據類型obj如果不用深拷貝賦值 修改對象obj.name單一屬性時候(state.data1VALUE.age = 33) 會導致父組件的源值改變 也會導致監聽事件再次執行state.data1VALUE = JSON.parse(JSON.stringify(data1))}, { deep:true })// setTimeout(() => {// state.str1VALUE = 'str1'// }, 2000);function setVal(){state.str1VALUE = '三次修改賦值'// state.data1VALUE = {// name: '張三',// age: 11// }state.data1VALUE.age = 33obj1VALUE.a = 3num1VALUE.value = 3}// 子傳父function setFarVal(){let obj = {a: 123456}emit('update:obj', obj);console.log('子傳父',obj);}function childMethod(){console.log('子事件');}return {state,obj1VALUE,num1VALUE,setVal,setFarVal,childMethod}}
})
</script>