vue3 parent-child component passes value; vue3 child component passes value to parent component; vue3 child component listens to parent component interface to pass value; parent-child component event call

代码在文末,均可直接复制使用

This article mainly describes issues such as value transfer and calling of parent-child components.


Problem 1: The child component cannot receive the value passed by the parent component

If the value of the parent component is assigned during onMounted, or is assigned asynchronously such as an interface , the child component will not be able to get the modified value directly. Subcomponents need to use watch monitoring . Search for the watch view
of the subcomponent son.vue

Question 2: After modifying the value accepted by the child component, it was found that the value of the parent component has also changed.

If you don't want to change, you need to perform deep copy assignment when the subcomponent accepts it . It is recommended to use deep copy. If you want to change the value of the parent component, pass the modification to the parent event separately.

Problem 3: The subcomponent accepts a value, but the page does not update after modification.

When the subcomponent accepts simple data types, change it to ref acceptance and generate responsive data
. For details, let num1VALUE = ref(props.num1) // Generate responsive data. Otherwise, the page will not change if the data is modified.

Problem 4: The child passes the parent event, the parent component accepts the value, and the assignment is invalid

This is because the variable in your parent component is declared using reactive. reactive Do not assign value directly to variable data=! ! ! Responsiveness will be lost. If you use ref, you don't have to assign values, or you have to use a single attribute to assign values ​​one by one. Obj. attribute = attribute value, or wrap an extra layer of objects around the original object.
由此可见:声明尽量用ref。。。。

5, child father

Search update:objView.

6. Parent calls child

Search sonRef.value.childMethod()View

7. Code

Parent component 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>

Subcomponent 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, immediate: true })

    // setTimeout(() => {
    
    
    //   state.str1VALUE = 'str1'
    // }, 2000);


    function setVal(){
    
    
      state.str1VALUE = '三次修改赋值'
      // state.data1VALUE = {
    
    
      //   name: '张三',
      //   age: 11
      // }
      state.data1VALUE.age = 33

      obj1VALUE.a = 3

      num1VALUE.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>

Guess you like

Origin blog.csdn.net/i_am_a_div/article/details/132191998