vue的数据是单向数据流动,在子组件中是不可以修改父组件的数据的,但是还是可以通过其他方式间接修改父组件的数据。

核心思想:数据在哪个组件,就在哪个组件修改。

1,方式一:通过向子组件传递方法

这个方式主要是在父组件内定义一个改变父组件数据的方法,然后将方法转入大子组件内。由于vue数据是单向流动的,父组件的数据只能通过父组件直接修改,而子组件只能间接修改,子组件间接修改的方式就是获取到父组件传递过来的方法,向该方法传入一个值以修改父组件的数据。

代码流程如下:

父组件:

<template>
<div id="app">
<div>{{ numbers }}</div>
<boy :changNumber="changNumber"></boy>
</div>
</template>
<script>
import boy from './components/boy.vue';
export default {
components: {
boy
},
data() {
return {
numbers: 0
};
},
methods: {
changNumber(value) {
this.numbers = value;
}
}
};
</script> <style>
</style>

这里我们需要修改的数据是numbers,在父组件定义一个修改该组件的方法changNumber(参数就需要在子组件内传入),将这个方法传入子组件。

<boy :changNumber="changNumber"></boy>

子组件:

<template>
<div class="checked-box">
<input v-model="num" />
<button @click="change">改变</button>
</div>
</template>
<script>
export default {
props: ['changNumber'],
data() {
return {
num: 1
};
},
methods: {
change() {
this.changNumber(this.num);
}
}
};
</script>
<style scoped></style>

子组件首先使用props接收父组件转过来的方法:

 props: ['changNumber'],

什么了这个方式之后,相对于在该组件的数据中以及存在changNumber方法的索引,此时相当于在子组件的data中存在changNumber这个方法变量(引用),所以取值得时候需要使用this来取。

随后在子组件内定义一个方法来实现间接改变父组件内的数据。

2,方式二,使用$emit来触发绑定在子组件的方法。

该方式主要是在父组件引入组件时,在引入的组件标签上绑定一个方法,这时子组件的$emit实例上就会有该方法,可用在子组件中使用$emit触发绑定在它的方法上,来实现修改父组件的数据。值得注意的是,在子组件标签上需要绑定被修改的变量,将这个变量传入子组件内并接收。

代码:父组件

<template>
<div id="app">
<div>{{ numbers }}</div>
<boy :nums="numbers" @changNumber="changNumber"></boy>
</div>
</template>
<script>
import boy from './components/boy.vue';
export default {
components: {
boy
},
data() {
return {
numbers: 0
};
},
methods: {
changNumber(value) {
this.numbers = value;
}
}
};
</script>
<style></style>

子组件:

<template>
<div class="checked-box">
<input v-model="num" />
<button @click="change">改变</button>
</div>
</template>
<script>
export default {
props: ['nums'],
data() {
return {
num: 1
};
},
methods: {
change() {
this.$emit('changNumber', this.num);
}
}
};
</script>
<style scoped></style>

运行结果:

这里可能会有人不了解,为什么子组件还需要接收父组件的数据而不是接收绑定的方法。

这里要注意的是,子组件标签已经绑定了方法,在它的实例上已经存在了,只需要通过$emit来触发该方法执行就可以了,但是需要传入父组件中需要修改的数据,这是需要通知子组件的的方法,要修改的是哪个数据。

this.$emit('changNumber', this.num);

相当于:


this.$emit(
changNumber(value) {
this.numbers = value;
},
this.num
);

如果不传入父组件的数据numbers ,子组件将会报undefined的错。

以上代码中。父组件可以简写为:

<template>
<div id="app">
<div>{{ numbers }}</div>
<boy :nums="numbers" @changNumber="changNumber=>thischangNumber=changNumber"></boy>
</div>
</template>
<script>
import boy from './components/boy.vue';
export default {
components: {
boy
},
data() {
return {
numbers: 0
};
},
methods: {
}
};
</script>
<style></style>

3,方式三,使用v-model实现父子组件双向数据绑定。

还记得方式而中的这段吗?

 <boy :nums="numbers" @changNumber="changNumber=>thischangNumber=changNumber">

我们给标签绑定一个方法和传入一个参数,就可以实现父子组件双向数据绑定了,如果这个标签是一个html标签呢?

啊!

这个是不是和v-model实现的功能类似?

其实,这个就是v-model的实现原理,我们在一个标签使用v-model的时候,渲染过程中会把v-model渲染成名为:value和@input。

<boy :value="numbers" @input="changNumber=>thischangNumber=changNumber"></boy>

等价于

<boy v-model="numbers"></boy>

所以就清晰了。

父组件:

<template>
<div id="app">
<div>{{ numbers }}</div>
<boy v-model="numbers"></boy>
</div>
</template>
<script>
import boy from './components/boy.vue';
export default {
components: {
boy
},
data() {
return {
numbers: 0
};
}
};
</script>
<style></style>

子组件:

<template>
<div class="checked-box">
<input v-model="num" />
<button @click="change">改变</button>
</div>
</template> <script>
export default {
props: ['value'],
data() {
return {
num: 1
};
},
methods: {
change() {
this.$emit('input', this.num);
}
}
};
</script>
<style scoped></style>

效果图:

需要注意的是,子组件中的props接收的名称不一定是叫value,$emit触发的方法必须是input(不会报错,但是数据不会改变)

如下:

子组件:

<template>
<div class="checked-box">
<input v-model="num" />
<button @click="change">改变</button>
</div>
</template> <script>
export default {
props: ['shdfnf'],
data() {
return {
num: 1
};
},
methods: {
change() {
this.$emit('input', this.num);
}
}
};
</script>
<style scoped></style>

效果为:

说明

 props: ['shdfnf'],

可以接收任意变量名。而改变input名呢?

子组件:

<template>
<div class="checked-box">
<input v-model="num" />
<button @click="change">改变</button>
</div>
</template> <script>
export default {
props: ['value'],
data() {
return {
num: 1
};
},
methods: {
change() {
this.$emit('input1234', this.num);
}
}
};
</script>
<style scoped></style>

效果图:

它既不报错,怎么点击按钮,值也无法跟着变化。

写了这么多,讲的这么细,难道不知道您点个赞吗?

vue小知识~实现父子组件双向数据绑定的更多相关文章

  1. Vue父子组件双向数据绑定

    [本文出自天外归云的博客园] 简介 Vue版本:2.9.6 Element版本:2.4.8 问题描述:子组件对Element中el-select进行封装,父组件中把选中的值selected和所有选项o ...

  2. vue小故事之父子(上下级)通信之父传子props

    vue小故事之父子(上下级)通信之父传子props vue 父子(上下级)通信 props  或许你对父子通信有点迷糊,为什么这样那样父子之间就可以通信了,以下通过一个小故事来进行解说,故事模型或许有 ...

  3. Angular中父子组件双向绑定传值

    下面为大家展示一个较为简单的ng父子组件双向绑定传值,下面是父组件页面 这个页面的大概功能就是父组件(红色)通过输入框输入内容反映到子组件上进行展示,并且进行了投影, 子组件(橙黄色)通过Input输 ...

  4. vue 父子组件双向绑定

    vue组件有2大特性: 1.全局组件和局部组件 2.父子组件的数据传递 接下来直接用demo直接看如何传值(静态传值) father.vue <template> <div> ...

  5. vue v-io 父子组件双向绑定多个数据

    vue-io-directive 可以减少使用emit,组件自带的v-model好像也只能设置一个 安装 npm i vue-io-directive 使用 import Vue from 'vue' ...

  6. 三大前端框架(react、vue、angular2+)父子组件通信总结

    公司业务需要,react.vue.angular都有接触[\无奈脸].虽然说可以拓展知识广度,但是在深度上很让人头疼.最近没事的时候回忆各框架父子组件通信,发现很模糊,于是乎稍微做了一下功课,记录于此 ...

  7. 详细讲解vue.js里的父子组件通信(props和$emit)

    在进入这个话题之前,首先我们先来想一下在vue里,如何写一个父子组件.为了简单起见,下面的代码我都没用脚手架来构建项目,直接在html文件里引入vue.js来作为例子.父子组件的写法如下: <d ...

  8. vue3.x自定义组件双向数据绑定v-model

    vue2.x 语法 在 2.x 中,在组件上使用 v-model 相当于绑定 value prop 并触发 input 事件: <ChildComponent v-model="pag ...

  9. Vue基础-渲染函数-父子组件-传递数据

    Vue 测试版本:Vue.js v2.5.13 做了个 demo,把父子组件的数据都绑定到 Vue 实例 app 上,注释中的 template 相对好理解些 <div id="app ...

  10. 2-4 Vue中的属性绑定和双向数据绑定

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. synchronized锁升级过程

    更过博文请关注:https://blog.bigcoder.cn JDK 1.6后锁的状态总共有四种,级别由低到高依次为:无锁.偏向锁.轻量级锁.重量级锁,这四种锁状态分别代表什么,为什么会有锁升级? ...

  2. 一篇文章让你读懂Java异常栈信息

    一. 基本的异常打印 public class Test { public static void main(String[] args) { fun1();//第4行 } public static ...

  3. 阿里面试:NIO为什么会导致CPU100%?

    在 Java 中总共有三种 IO 类型:BIO(Blocking I/O,阻塞I/O).NIO(Non-blocking I/O,非阻塞I/O)和 AIO(Asynchronous I/O,异步I/O ...

  4. Vue 组件生命周期:探索钩子

    title: Vue 组件生命周期:探索钩子 date: 2024/5/27 18:42:38 updated: 2024/5/27 18:42:38 categories: 前端开发 tags: 生 ...

  5. [C#] 禁用控制台关闭按钮

    禁用控制台关闭按钮 internal class Program { [DllImport("user32.dll", EntryPoint = "FindWindow& ...

  6. 算法金 | 突破最强算法模型!!学会随机森林,你也能发表高水平SCI

    大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 就在去年下半年,如果你在 Google Scholar 上以 "Random ...

  7. Python爬虫 | 批量爬取今日头条街拍美图

    01 前言 上篇文章我们爬取了今日头条街拍美图,心情相当愉悦,今天这篇文章我们使用Selenium来爬取当当网的畅销图书排行.正所谓书中自有黄金屋,书中自有颜如玉,我们通过读书学习来提高自身的才华,自 ...

  8. 强!推荐一款开源接口自动化测试平台:AutoMeter-API !

    在当今软件开发的快速迭代中,接口自动化测试已成为确保代码质量和服务稳定性的关键步骤. 随着微服务架构和分布式系统的广泛应用,对接口自动化测试平台的需求也日益增长. 今天,我将为大家推荐一款强大的开源接 ...

  9. 关于正在开发中的DjangoStarter v3版本

    前言 最近做的这个项目大量使用了 python 及其相关的生态,因此自然而然选择了我的 DjangoStarter 作为后端框架 之前 v2 版本是用 RestFramework 做接口的,后面我试用 ...

  10. C# .NET HttpWebRequest 显示指定SSL TLS 版本

    C# .NET HttpWebRequest 显示指定SSL TLS 版本 (TLS1.0,TLS1.1,TLS1.2) 在程序启动时加入这段代码: ServicePointManager.Secur ...