vue父子组件状态同步的最佳方式

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

通常来讲咱们实现这个功能,只须要父组件经过 props 传递给子组件就行了,可是理想很丰满,现实很骨感,若是咱们直接在子组件更改传进来的 props ,不出意外浏览器会给你一坨大红色的报错,由于在 vue 中咱们的数据流动是自上而下的,而子组件直接更改父组件传来的 props 则是自下而上的数据流动,这是 vue 不容许的。vue

因此一般咱们的解决办法是,父组件经过 props 传入状态给子组件,子组件经过 props 来初始化另一个内部的状态,子组件每次更改状态以后都通知父组件,而后由父组件来更改本身的状态,其实就是 props on emit 的应用,接下来咱们来上代码。web

父组件 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>

好了,两种写法咱们都已经演示完毕,如今咱们来优化一下父组件中的写法。this

父组件中能够看到咱们以前在上面绑定了一个 update:food 事件,而且使用箭头函数作了一个赋值,其实这里咱们能够稍微优化一下,不要箭头函数直接赋值,由于咱们触发的是自定义事件,而咱们触发的时候给的第一个参数就是新值,咱们能够直接经过 $event 拿到这个值,因此能够写成以下形式:code

优化后的父组件事件

<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。固然你也能够经过哔哩哔哩搜索木瓜太香找到我。

相关文章
相关标签/搜索