解锁Vue魔法门:父子组件双向绑定的神秘密码!

郝思文
• 阅读 163

引言

在前端开发中,组件通信是不可避免的一部分。Vue中的数据流是单向的,这有助于使应用更容易维护和调试,但也带来了一些挑战。在讨论数据双向绑定之前,让我们先了解一下Vue中的单向数据流。

单向数据流

在Vue中,数据的流动被设计成单向的,所有父子组件之间形成了一种自上而下的单向绑定。即父级组件的prop更新会向下传递到子组件中,但反过来却不成立。这种设计有助于提高应用的可维护性和调试性,避免了子组件意外修改父级组件状态的风险。每次父级组件发生变更时,子组件中所有的prop都会刷新为最新的值。然而,在子组件内部直接修改prop将触发Vue在浏览器控制台中发出警告。

示例警告代码可能类似于:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value.

由于Vue是单向数据流,为了解决从子组件向父组件传递变更的需求,我们需要实现父子组件中的数据双向绑定。

.sync修饰符

.sync修饰符是Vue提供的一种方式,通过在父组件中使用:visible.sync="showDialog",在子组件中使用computed计算visible的值,并在变化时通过this.$emit('update:visible', false)广播给父组件,实现双向绑定。

使用 .sync 修饰符,是双向绑定的一种语法糖

<ChildComponent :visible.sync="show" />

等价于

<ChildComponent :visible="showDialog" @update:visible="val => showDialog = val" />

实际场景 - 模态框: 以一个模态框为例,展示如何使用.sync修饰符实现模态框的显示和隐藏,以及在子组件内部如何通过按钮切换模态框的状态。

父组件代码示例:

<!-- 在父组件中 -->
<template>
  <ChildComponent :visible.sync="showDialog" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  data() {
    return {
      showDialog: false
    };
  },
  components: {
    ChildComponent
  }
};
</script>

子组件代码示例:

<!-- 在子组件中 -->
<template>
  <div>
    <!-- 使用计算属性 -->
    <div v-if="visibleComputed">Dialog is visible!</div>
    <button @click="toggleVisibility">Toggle Visibility</button>
  </div>
</template>

<script>
export default {
  props: {
    visible: Boolean
  },
  computed: {
    visibleComputed: {
      get() {
        return this.visible;
      },
      set(value) {
        this.$emit('update:visible', value);
      }
    }
  },
  methods: {
    toggleVisibility() {
      this.visibleComputed = !this.visibleComputed;
    }
  }
};
</script>

v-model关键字

v-model关键字是Vue提供的另一种语法糖,通过在父组件中使用v-model="msg"向子组件传递值,子组件内部通过props接受value,并使用watch观察者模式监听value的变化,使用this.$emit('input', this.message)广播子组件的值到父组件,实现双向数据绑定。

使用 v-model 关键字,也是一种语法糖

<ChildComponent v-model="msg" />

等价于

<ChildComponent :value="msg" @input="val => msg = val" />

实际场景 - 实时搜索: 展示一个实时搜索的例子,父组件传递搜索关键字,子组件实时更新搜索结果。

父组件代码示例:

<!-- 在父组件中 -->
<template>
  <ChildComponent v-model="msg" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  data() {
    return {
      msg: 'Hello from parent!'
    };
  },
  components: {
    ChildComponent
  }
};
</script>

子组件代码示例:

<!-- 在子组件中 -->
<template>
  <div>
    <input v-model="message" />
  </div>
</template>

<script>
export default {
  props: {
    value: String
  },
  data() {
    return {
      message: this.value
    };
  },
  watch: {
    value(newVal) {
      this.message = newVal;
    },
    message(newVal) {
      this.$emit('input', newVal);
    }
  }
};
</script>

普通数据双向绑定

在某些情况下,我们需要在父子组件之间进行更复杂的数据交互,不仅仅是简单的值传递。这时,我们可以使用事件的方式实现这种双向通信。父组件修改prop的数据状态,子组件 this.$emit发送事件广播,通知父组件修改父组件内的数据状态,同时父组件需要监听相关的event来修改同步修改prop的值。

父组件代码示例:

<!-- 在父组件中 -->
<template>
  <Child :message="message" @updateMessage="updateMessage" />
</template>

<script>
import Child from './Child.vue';

export default {
  data() {
    return {
      message: 'Hello from parent!'
    };
  },
  components: {
    Child
  },
  methods: {
    updateMessage(newMessage) {
      this.message = newMessage;
    }
  }
};
</script>

子组件代码示例:

<!-- 在子组件中 -->
<template>
  <div>
    <input v-model="localMessage" />
    <button @click="sendMessage">Send Message</button>
  </div>
</template>

<script>
export default {
  props: {
    message: String
  },
  data() {
    return {
      localMessage: this.message
    };
  },
  methods: {
    sendMessage() {
      this.$emit('updateMessage', this.localMessage);
    }
  }
};
</script>

骚操作:传入引用数据类型

在Vue中,通过传递引用数据类型,我们可以在子组件中修改属性时,父组件同时更新,实现双向绑定。

实际场景 - 购物车: 假设我们正在构建一个购物车组件。父组件传递购物车商品列表给子组件,而子组件可以通过事件向父组件发出添加或删除商品的请求,保持购物车数据的同步。

父组件代码示例:

<!-- 在父组件中 -->
<template>
  <Child :cart="cart" />
</template>

<script>
import Child from './Child.vue';

export default {
  data() {
    return {
      cart: {
        items: [],
        total: 0
      }
    };
  },
  components: {
    Child
  }
};
</script>

子组件代码示例:

<!-- 在子组件中 -->
<template>
  <div>
    <button @click="addToCart">Add to Cart</button>
  </div>
</template>

<script>
export default {
  props: {
    cart: Object
  },
  methods: {
    addToCart() {
      // 在子组件中修改cart对象的属性
      this.cart.items.push({ name: 'Product', price: 20 });
      this.cart.total += 20;
    }
  }
};
</script>

结语

Vue提供了多种方式来实现父子组件之间的数据双向绑定,每种方式都有其适用的场景。通过灵活运用这些技巧,我们能够更高效地进行组件通信,提高代码的可维护性和可读性。希望本文能够帮助你更好地理解Vue中的数据双向绑定,并在实际开发中得心应手。

才疏学浅,如有讲述不清之处,还请指正,共同进步。

本文由mdnice多平台发布

点赞
收藏
评论区
推荐文章
02-Vue入门之数据绑定
02Vue入门之数据绑定02Vue入门之数据绑定2.1.什么是双向绑定?Vue框架很核心的功能就是双向的数据绑定。双向是指:HTML标签数据绑定到Vue对象,另外反方向数
九旬 九旬
4年前
前端培训-Vue专题之Vue基础
简介特点:MVVM框架,双向绑定,数据驱动,单页面,组件化。区别Vue和jQuery的区别:不直接操作DOM,而是操作数据。案例:HelloWorld你好,世界HTML代码:xml<h1msg</h1jQuery实现javascript$("h1").text("你好,世界");Vue实现javascriptthis.msg'你好,世界'
明月 明月
4年前
vue常见面试题
1.有使用过vue吗?说说你对vue的理解?2.说说你对SPA单页面的理解,它的优缺点分别是什么?如何实现SPA应用呢?3.什么是双向绑定?原理是什么?4.请描述下你对vue生命周期的理解?在created和mounted这两个生命周期中请求数据有什么区别呢?5.Vue组件之间的通信方式都有哪些?6.vshow和vif有什么区别?使用场景分别是什
Alex799 Alex799
4年前
vue最新面试题
最近在面试,总结几个重点的面试题:一、vue父子组件之间的传值:简单来说,子组件通过props方法接受父组件传来的值,子组件通过$emit方法来向父组件发送数据。(具体案例可以看我之前写的博客)。二、vue生命周期函数:beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeDestr
Easter79 Easter79
4年前
Vue 组件实现数据双向绑定(el
一、组件vmodel值通过props传入,必须定义为value!(https://oscimg.oschina.net/oscnet/66e6fa03cb5d23a24fd7d45e5e782b125ec.png)二、将传入的value在data中重新定义赋值,以便子组件改变值(子组件中不能直接修改props
可莉 可莉
5年前
了解Vuex状态管理模式
1Vuex是什么呢?它是Vue的状态管理模式,在使用vue的时候,需要在vue中各个组件之间传递值是很痛苦的,在vue中我们可以使用vuex来保存我们需要管理的状态值,值一旦被改变,所有引用该值的地方就会自动更新。是不是很方便,很好用呢?vuex是专门为vue.js设计的状态管理模式,集中式存储和管理应用程序中所有组件的状态,vuex也集成了vue的
科林-Colin 科林-Colin
5年前
Vue 组件通信方式及其应用场景总结
前言相信实际项目中用过vue的同学,一定对vue中父子组件之间的通信并不陌生,vue中采用良好的数据通讯方式,避免组件通信带来的困扰。今天笔者和大家一起分享vue父子组件之间的通信方式,优缺点,及其实际工作中的应用场景首先我们带着这些问题去思考1vue中到底有多少种父子组件通信方式?2vue中那种父子组件最佳通信方式是什么?3
Stella981 Stella981
4年前
Hyperledger Fabric如何启用双向TLS安全通信?
HyperlederFabric区块链支持在通信节点之间启用TLS传输层安全通信,TLS支持单向验证仅验证服务节点身份,或双向验证同时验证服务节点和客户端节点的身份。本文将介绍如何在HyperledgerFabric网络中启用双向TLS安全通信。HyperledgerFabric链码与应用开发相关教程:Hype
Stella981 Stella981
4年前
React的单向数据流与组件间的沟通
今天来给大家总结下React的单向数据流与组件间的沟通。首先,我认为使用React的最大好处在于:功能组件化,遵守前端可维护的原则。先介绍单向数据流吧。React单向数据流:React是单向数据流,数据主要从父节点传递到子节点(通过props)。如果顶层(父级)的某个props改变了,React会重渲染所有的子节点。刚才我们提到了
手牵手带你实现mini-vue | 京东云技术团队
Vue的双向数据绑定实现原理是什么样的,如果让我们自己去实现一个这样的双向数据绑定要怎么做呢,本文就与大家分享一下Vue的绑定原理及其简单实现
京东云开发者 京东云开发者
4个月前
常用Web 实时通信技术:原理+选型,一篇通关
在Web开发中,实时通信技术的核心目标是实现客户端(Browser)与服务器之间低延迟、双向/单向的动态数据交互,而非传统HTTP的“请求响应”模式。以下是Web端最常用的实时通信技术,从概念、原理特点、适用场景、对比选型进行详细解析。一、WebSocke