vue父组件更新值后,子组件无法及时更新

发现问题:当父组件传值给子组件后,子组件通过赋值给另一个变量后,再使用这个值,这便会造成父组件更新值后,子组件无法更新的这个问题。

解决问题:可以使用watch、v-if、计算属性、provide/inject这几个方案解决

说明:此处用的是vue3做演示,但是下面演示的这些方法,在vue2同样适用(除provide/inject外)

演示

watch方案


父组件:
<template>
  <button @click="check">修改</button>
  <h3>父:{{ tableData }}</h3>
  <test2 :va="tableData"/>
</template>

<script>
import {ref} from 'vue'
import test2 from './test2'

export default {
  name: 'App',
  components: {test2},
  setup() {
    const tableData = ref('22222')

    function check() {
      tableData.value = 'wwww'
    }

    return {check, tableData}
  }
}
</script>
子组件:
<template>
  <h3>子直接使用{{ va }}</h3>
  <h3>子赋值后使用{{ rea.a }}</h3>
</template>

<script>
import {reactive, watch} from 'vue'

export default {
  props: ['va'],
  setup(props) {
    const rea = reactive({a: 0})

    watch(() => props.va, (newValue) => {
      rea.a = newValue
    },{immediate: true })

    return {rea}
  }
}
</script>

使用watch监听方法对于新手比较友好,也是最容易想到的。但是watch绝对不是最优解,使用watch甚至会造成代码后期维护困难以及可读性差的问题,但是目前来看,大部分人使用的仍是watch方法

v-if


父组件:
<template>
  <button @click="check">修改</button>
  <h3>父:{{ tableData }}</h3>
  <test2 v-if="isshow" :va="tableData"/>
</template>

<script>
import {ref,nextTick} from 'vue'
import test2 from './test2'

export default {
  name: 'App',
  components: {test2},
  setup() {
    const tableData = ref('22222')
    const isshow=ref(true)

    function check() {
      tableData.value = 'wwww'
      isshow.value=false
      nextTick(()=>{
        isshow.value=true
      })
    }

    return {check,isshow, tableData}
  }
}
</script>

子组件:
<template>
    <h3>子直接使用{{ va }}</h3>
    <h3>子赋值后使用{{ rea.a }}</h3>
  </template>
  
  <script>
  import {reactive} from 'vue'
  
  export default {
    props: ['va'],
    setup(props) {
      const rea = reactive({a: props.va})
  
      function dd() {
        console.log('qwe')
        rea.a = props.va
      }
  
      dd()
  
  
      return {rea,}
    }
  }
  </script>
  

使用v-if也可以解决该问题,即当值修改后,配合nextTick,让子组件重新渲染(这有点类似于react的方法),这样虽然可以解决问题,但是我认为这个不太好,首先增加了不必要的代码量,其次无端的渲染组件,这会造成性能的损耗。

使用计算属性(个人认为这应该是最优解)


父组件:
<template>
  <button @click="check">修改</button>
  <h3>父:{{ tableData }}</h3>
  <test2 :va="tableData"/>
</template>

<script>
import {ref} from 'vue'
import test2 from './test2'

export default {
  name: 'App',
  components: {test2},
  setup() {
    const tableData = ref('22222')

    function check() {
      tableData.value = 'wwww'
    }

    return {check, tableData}
  }
}
</script>
子组件:
<template>
  <h3>子直接使用{{ va }}</h3>
  <h3>子赋值后使用{{ computedVa }}</h3>
</template>

<script>
import {computed} from 'vue'

export default {
  props: ['va'],
  setup(props) {
    const computedVa = computed(() => props.va )

    return {computedVa}
  }
}
</script>

使用计算属性代码简单清晰,由于 计算属性 是基于依赖项的响应式数据计算得到的,所以它在性能方面也很高效,个人认为这是最佳方案

使用 provide/inject(该方法为vue3新增的,vue2不支持)


父组件:
<template>
  <button @click="check">修改</button>
  <h3>父:{{ tableData }}</h3>
  <test2/>
</template>

<script>
import {ref, provide} from 'vue'
import test2 from './test2'

export default {
  name: 'App',
  components: {test2},
  setup() {
    const tableData = ref('22222')

    function check() {
      tableData.value = 'wwww'
    }

    provide('getTableData', () => tableData.value)

    return {check, tableData}
  }
}
</script>
子组件:
<template>
    <h3>子赋值后使用{{ injectedTableData() }}</h3>
  </template>
  
  <script>
  import {inject} from 'vue'
  
  export default {
    setup() {
      const injectedTableData = inject('getTableData')
  
      return {injectedTableData}
    }
  }
  </script>
  

该方法在父组件中使用provide传递一个函数的方法,这样便很好的解决这个问题了

使用toRef(该方法为vue3新增的,vue2不支持


父组件:
<template>
  <button @click="updateData">更新数据</button>
  <child :data="data" />
</template>

<script>
import { reactive} from 'vue'
import Child from './test2.vue'

export default {
  components: { Child },
  setup() {
    const data = reactive({ count: 0 })

    function updateData() {
      data.count++
    }

    return { data, updateData }
  },
}
</script>
子组件:
<template>
    <div>
      <h3>{{ data.count }}</h3>
    </div>
  </template>
  
  <script>
    import { toRefs } from 'vue'
    export default {
        props: ['data'],
        setup(props) {
        const data = toRefs(props.data)
        return { data }
        },
    }
  </script>
  

这个方法实现起来很简单,但只能在vue3中使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值