关于javascript:vue父子组件状态同步的最佳方式

42次阅读

共计 2003 个字符,预计需要花费 6 分钟才能阅读完成。

哈喽!大家好!我是木瓜太香,一位老牌儿前端工程师,平时咱们在应用 vue 开发的时候,可能会遇到须要父组件与子组件某个状态须要同步的状况,通常这个是因为咱们封装组件的时候有一个雷同的状态里面要用,外面也要用,明天咱们就来看看怎么优雅的解决这个问题吧!

一般来说咱们实现这个性能,只须要父组件通过 props 传递给子组件就好了,然而现实很饱满,事实很骨感,如果咱们间接在子组件更改传进来的 props,不出意外浏览器会给你一坨大红色的报错,因为在 vue 中咱们的数据流动是自上而下的,而子组件间接更改父组件传来的 props 则是自下而上的数据流动,这是 vue 不容许的。

所以通常咱们的解决办法是,父组件通过 props 传入状态给子组件,子组件通过 props 来初始化另外一个外部的状态,子组件每次更改状态之后都告诉父组件,而后由父组件来更改本人的状态,其实就是 props on emit 的利用,接下来咱们来上代码。

父组件 Father.vue

<template>
    <div class="father">
        <h1> 父组件保护的状态:{{food}}</h1>
        <son :food="food" @update:food="f => food = f"></son>
    </div>
</template>

子组件 Son.vue

<template>
    <div class="son">
        <h2> 子组件中保护的状态:{{innerFood}}</h2>
        <button @click="innerFood ='100 斤牛肉 '"> 点击更改子组件状态 </button>
    </div>
</template>
<script>
    export default {data () {
          return {innerFood: this.food}  
        },
        props: {food: String},
        watch: {innerFood (nv) {this.$emit("update:food",nv)
            }
        }
    }
</script>

能够看到咱们上述的写法,其实是保护了父子组件中的不同的两个状态,咱们做的工作只是将这两个状态同步了,这种写法没有任何问题,其实对于子组件的局部咱们也能够通过 computed 来实现,上面咱们来看一看另一种子组件内保护同步状态的办法:

子组件 Son.vue 的另一种写法

<template>
    <div class="son">
        <h2> 子组件中保护的状态:{{innerFood}}</h2>
        <button @click="innerFood ='100 斤牛肉 '"> 点击更改子组件状态 </button>
    </div>
</template>
<script>
    export default {
        props: {food: String},
        computed: {
            innerFood: {get () {return this.food},
                set (nv) {this.$emit("update:food",nv)
                }
            }
        }
    }
</script>

好了,两种写法咱们都曾经演示结束,当初咱们来优化一下父组件中的写法。

父组件中能够看到咱们之前在下面绑定了一个 update:food 事件,并且应用箭头函数做了一个赋值,其实这里咱们能够略微优化一下,不要箭头函数间接赋值,因为咱们触发的是自定义事件,而咱们触发的时候给的第一个参数就是新值,咱们能够间接通过 $event 拿到这个值,所以能够写成如下模式:

优化后的父组件

<template>
    <div class="father">
        <h1> 父组件保护的状态:{{food}}</h1>
        <son :food="food" @update:food="food = $event"></son>
    </div>
</template>

到这里你认为就完结了?其实咱们还能够更近一步,只有满足咱们以上的事件命名形式,咱们实际上能够应用 sync 修饰符代替事件的绑定,也就是咱们不必写事件绑定了,然而子组件外部的事件触发仍然不能少,最终优化的后果如下:

<template>
    <div class="father">
        <h1> 父组件保护的状态:{{food}}</h1>
        <son :food.sync="food"></son>
    </div>
</template>

到此咱们就真的实现了父子组件的同步,当然在子组件中保护一个状态不肯定是必须的,如果咱们只用父组件传给咱们的 props 做展现,而子组件没有对这个 props 间接更改的行为,那么咱们就不必在子组件创立另外一个状态,咱们子组件想改他的时候只须要在适合的机会提交适合的事件即可,然而有一种状况咱们不得不在子组件中创立另一个状态,就是咱们父组件传入的状态在子组件中用于 v-model 这种双向数据绑定的性能时,因为 v-model 会主动更改值所以间接填入从父组件承受的 props 就不适合了。

我本人建了一个 web 前端的交换裙有趣味的能够退出进来交换哦:237871108。当然你也能够通过哔哩哔哩搜寻木瓜太香找到我。

正文完
 0