本文主要说两件事

1. 如何实现父子组件之间的双向绑定

2. 父组件如何访问子组件的data,method, 子组件如何访问父组件的data,method等


一. 如何实现父子组件之间的双向绑定

案例描述:

  1. 父子组件双向绑定
  2. 父组件有一个message,
  3. 子组件有一个文本框
  4. 让他们两个同步变化

实现思路:

  1. 1. 子组件接收父组件传递过来的参数
  2. 2. 先实现子组件的双向绑定
  3. 3. 子组件将数据传给父组件

实现步骤:

第一步: 子组件接收父组件的data

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="../../js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. 父组件的值: {{message}}
  11. <br>
  12. <input type="text" v-model="message"></input>
  13. <comp1 :cmessage="message" ></comp1>
  14. </div>
  15.  
  16. <template id="comp1">
  17. <div style=" width: 600px; background-color: #085e7d; color: antiquewhite">
  18. <h2>子组件cmessage的值:{{cmessage}}</h2>
  19. <br>
  20. </div>
  21. </template>
  22. <script>
  23. Vue.component("comp1", {
  24. template: "#comp1",
  25. props: ["cmessage"],
  26.  
  27. })
  28. const app = new Vue({
  29. el: "#app",
  30. data: {
  31. message: "hello"
  32. }
  33. });
  34. </script>
  35. </body>
  36. </html>

子组件通过属性props: ["cmessage"], 来接收父组件的message属性. 并且父组件修改message的值, 子组件跟随改变

效果如下:

第二步: 实现子组件属性的双向绑定

组件的数据绑定, 使用的也是data属性.但在组件中, data定义为一个方法

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="../../js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. 父组件的值: {{message}}
  11. <br>
  12. <input type="text" v-model="message"></input>
  13. <comp1 :cmessage="message" ></comp1>
  14. </div>
  15.  
  16. <template id="comp1">
  17. <div style=" width: 600px; background-color: #085e7d; color: antiquewhite">
  18. <h2>子组件cmessage的值:{{cmessage}}</h2>
  19. <h2>子组件cmess的值: {{cmess}}</h2>
  20. <br>
  21. cmess:<input type="text" v-model="cmess" ></input>
  22. <br>
  23. </div>
  24. </template>
  25. <script>
  26. Vue.component("comp1", {
  27. template: "#comp1",
  28. props: ["cmessage"],
  29. data() {
  30. return {
  31. "cmess": this.cmessage
  32. }
  33. }
  34.  
  35. })
  36. const app = new Vue({
  37. el: "#app",
  38. data: {
  39. message: "hello"
  40. }
  41. });
  42. </script>
  43. </body>
  44. </html>

data中定义了属性cmess, 其值是属性cmessage的值. 我们实现cmess属性的双向绑定.cmess:<input type="text" v-model="cmess" ></input>

效果如下:

这样子组件cmess的双向绑定实现了, 但是我们发现修改父组件的时候,子组件没有变化. 修改子组件的时候, 父组件也没有变化

第三步: 子组件属性变化同步给父组件

子组件属性的改变同步给父组件, 使用的是自定义事件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="../../js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. 父组件的值: {{message}}
  11. <br>
  12. <input type="text" v-model="message"></input>
  13. <comp1 :cmessage="message" @csyncchange="syncchange"></comp1>
  14. </div>
  15.  
  16. <template id="comp1">
  17. <div style=" width: 600px; background-color: #085e7d; color: antiquewhite">
  18. <h2>子组件cmessage的值:{{cmessage}}</h2>
  19. <h2>子组件cmess的值: {{cmess}}</h2>
  20. <br>
  21. cmess:<input type="text" v-model="cmess" @input="changeMessage"></input>
  22. <br>
  23. </div>
  24. </template>
  25. <script>
  26. Vue.component("comp1", {
  27. template: "#comp1",
  28. props: ["cmessage"],
  29. data() {
  30. return {
  31. "cmess": this.cmessage
  32. }
  33. },
  34. methods: {
  35. changeMessage(event) {
  36. console.log(event.target.value)
  37. this.$emit("csyncchange", event.target.value)
  38. }
  39. },
  40. watch: {
  41. cmessage(val, oldval) {
  42. console.log(val, oldval)
  43. console.log()
  44. this.cmess = val
  45. }
  46. }
  47.  
  48. })
  49. const app = new Vue({
  50. el: "#app",
  51. data: {
  52. message: "hello"
  53. },
  54. methods: {
  55. syncchange(value) {
  56. this.message = value
  57. }
  58. }
  59. });
  60. </script>
  61. </body>
  62. </html>

添加子组件的input事件: @input="changeMessage".

  1. changeMessage(event) {
  2. console.log(event.target.value)
  3. this.$emit("csyncchange", event.target.value)
  4. }

然后自定义一个csyncchange事件, 父组件监听这个事件的变化

  1. <comp1 :cmessage="message" @csyncchange="syncchange"></comp1>

父组件自定义一个method方法, 接收事件传递的数据

  1. methods: {
  2. syncchange(value) {
  3. this.message = value
  4. }
  5. }

这样就实现了子组件修改cmess的值, 同步给父组件. 效果如下:

但是, 我们发现,在组建同步给父组件没问题, 组件只同步数据给了props属性, 而没有同步给cmess

第四步: 使用watch方法监听props属性的变化

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="../../js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. 父组件的值: {{message}}
  11. <br>
  12. <input type="text" v-model="message"></input>
  13. <comp1 :cmessage="message" @csyncchange="syncchange"></comp1>
  14. </div>
  15.  
  16. <template id="comp1">
  17. <div style=" width: 600px; background-color: #085e7d; color: antiquewhite">
  18. <h2>子组件cmessage的值:{{cmessage}}</h2>
  19. <h2>子组件cmess的值: {{cmess}}</h2>
  20. <br>
  21. cmess:<input type="text" v-model="cmess" @input="changeMessage"></input>
  22. <br>
  23. </div>
  24. </template>
  25. <script>
  26. Vue.component("comp1", {
  27. template: "#comp1",
  28. props: ["cmessage"],
  29. data() {
  30. return {
  31. "cmess": this.cmessage
  32. }
  33. },
  34. methods: {
  35. changeMessage(event) {
  36. console.log(event.target.value)
  37. this.$emit("csyncchange", event.target.value)
  38. }
  39. },
  40. watch: {
  41. cmessage(val, oldval) {
  42. console.log(val, oldval)
  43. console.log()
  44. this.cmess = val
  45. }
  46. }
  47.  
  48. })
  49. const app = new Vue({
  50. el: "#app",
  51. data: {
  52. message: "hello"
  53. },
  54. methods: {
  55. syncchange(value) {
  56. this.message = value
  57. }
  58. }
  59. });
  60. </script>
  61. </body>
  62. </html>

这一步的重点是watch方法. 同步cmessage的值给cmess. 看看效果

以上,完美实现了,父子组件的双向数据绑定.

二. 父子组件的相互访问

如果父组件想要访问子组件的属性和方法, 或者子组件想要访问父组件的属性和方法怎么办呢? 下面来看看:

1. 父组件访问子组件

父组件访问子组件有两种方式

  • 1. 使用$children
  • 2. 使用@refs

案例: 现在有一个父组件, 想要拿到子组件的方法或者变量.

  • 使用$children获取

  1. 获取所有的子组件: this.$children
  2. 获取某个子组件的属性: this.$children.属性名
  3. 获取某个子组件的方法: this.$children.方法名()
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9. <h1>第一种方法: 使用children访问子组件</h1>
  10. <app1-comp></app1-comp>
  11. <app1-comp></app1-comp>
  12. <app1-comp></app1-comp>
  13. <button @click="btnclick">按钮</button>
  14.  
  15. </div>
  16.  
  17. <template id="comp1">
  18. <div>
  19. <p>只有app1才能使用的组件</p>
  20. <h2>{{name}}</h2>
  21. </div>
  22. </template>
  23. <script src="../../js/vue.js"></script>
  24. <script>
  25. const app1Comp = Vue.extend({
  26. template: comp1,
  27. data() {
  28. return {
  29. name : "name名称"
  30. }
  31. },
  32. methods: {
  33. getchange() {
  34. console.log("getchange方法")
  35. }
  36. }
  37.  
  38. })
  39.  
  40. let app = new Vue({
  41. el: "#app",
  42. data: {
  43. message: "hello"
  44. },
  45. components:{
  46. app1Comp: app1Comp
  47. },
  48. methods: {
  49. btnclick() {
  50. console.log("点击事件", this.$children)
  51. console.log("父组件访问子组件的data数据: ",this.$children[1].name)
  52. console.log("父组件访问子组件的方法: ",this.$children[1].getchange())
  53. }
  54. }
  55. });
  56.  
  57. </script>
  58. </body>
  59. </html>

在dom中使用了三个comp1组件. 我们可以使用this.$children来获取所有的组件

这里获取到了3个组件, 并打印了第二个组件的名称和方法

  • 使用@refs获取属性

使用refs的好处是可以根据组件名称获取. 而不是遍历, 因为遍历的下标时可能修改的.

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <!--
  9. 父组件访问子组件有两种方式
  10. 1. 使用$children
  11. 2. 使用@refs
  12.  
  13. 需求: 现在有一个父组件, 想要拿到子组件的方法或者变量.
  14. 所以, 我们先定义一个组件.
  15.  
  16. -->
  17. <div id="app">
  18. <h1>第二种方法: 使用refs访问子组件</h1>
  19. <app2-comp ref="app21"></app2-comp>
  20. <app2-comp ref="app22"></app2-comp>
  21. <app2-comp ref="app23"></app2-comp>
  22. <button @click="btnclick">按钮</button>
  23.  
  24. </div>
  25.  
  26. <template id="comp1">
  27. <div>
  28. <p>只有app1才能使用的组件</p>
  29. <h2>{{name}}</h2>
  30. </div>
  31. </template>
  32. <script src="../../js/vue.js"></script>
  33. <script>
  34. const app1Comp = Vue.extend({
  35. template: comp1,
  36. data() {
  37. return {
  38. name : "name名称"
  39. }
  40. },
  41. methods: {
  42. getchange() {
  43. console.log("getchange方法")
  44. }
  45. }
  46.  
  47. })
  48.  
  49. let app = new Vue({
  50. el: "#app",
  51. data: {
  52. message: "hello"
  53. },
  54. components:{
  55. app1Comp: app1Comp,
  56. app2Comp: app1Comp
  57. },
  58. methods: {
  59. btnclick() {
  60.  
  61. console.log(this.$refs.app21.name)
  62. console.log(this.$refs.app21.getchange())
  63. }
  64. }
  65. });
  66.  
  67. </script>
  68. </body>
  69. </html>

这一次我们给组件起了名字, 通过$refs可以指定组件名,获取属性和方法

2. 子组件访问父组件

  • 子组件访问父组件使用的是$parent
  • 子组件访问根组件使用$root

通常new Vue()也是一个组件, 他是根组件. 如果子组件想要获取根组件的属性和方法,使用@root

下面这个例子, 是子组件comp1里面引用了另一个组件comp2. 在comp2中获取comp1的属性和方法, 使用@parent, 这就是子组件获取父组件的属性和方法

comp2要想获取new Vue()对象的属性和方法, 使用的是$root.

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <!--
  9. 父组件访问子组件有两种方式
  10. 1. 使用$children
  11. 2. 使用@refs
  12.  
  13. 需求: 现在有一个父组件, 想要拿到子组件的方法或者变量.
  14. 所以, 我们先定义一个组件.
  15.  
  16. -->
  17. <div id="app">
  18. <h1>子组件访问父组件</h1>
  19. <comp1></comp1>
  20.  
  21. </div>
  22. <template id="comp1">
  23. <div>
  24. <comp2></comp2>
  25. </div>
  26.  
  27. </template>
  28. <template id="comp2">
  29. <div>
  30. <p>组件comp2</p>
  31. <button type="text" @click="btnClick">按钮</button>
  32. </div>
  33. </template>
  34. <script src="../../js/vue.js"></script>
  35. <script>
  36. const app1Comp = Vue.extend({
  37. template: comp1,
  38. data() {
  39. return {
  40. name: "name名称"
  41. }
  42. },
  43. components: {
  44. comp2: {
  45. template: comp2,
  46.  
  47. methods: {
  48. btnClick() {
  49. console.log(this.$parent)
  50. console.log(this.$parent.name)
  51.  
  52. // 获取root元素, 也就是vue元素
  53. console.log(this.$root)
  54. console.log(this.$root.message)
  55. }
  56. }
  57. }
  58. }
  59. })
  60.  
  61. let app = new Vue({
  62. el: "#app",
  63. data: {
  64. message: "hello"
  65. },
  66. components:{
  67. comp1: app1Comp
  68. },
  69. methods: {
  70. btnclick() {
  71.  
  72. }
  73. }
  74. });
  75.  
  76. </script>
  77. </body>
  78. </html>

以上就是父子组件之间相互访问的情况

7.vue组件(二)--双向绑定,父子组件访问的更多相关文章

  1. 组件的通信 :provide / inject 对象进入后,就等于不用props,然后内部对象,直接复制可以接受数组,属性不能直接复制,可以用Object.assgin覆盖对象,或者Vue的set 双向绑定数据

    组件的通信 :provide / inject 对象进入后,就等于不用props,然后内部对象,直接复制可以接受数组,属性不能直接复制,可以用Object.assgin覆盖对象,或者Vue的set 双 ...

  2. sync 简单实现 父子组件的双向绑定

    这里主要是对vue文档中的sync进行一个再解释: 如果自己尝试的话,最好在已经使用emit 和prop实现了双向绑定的组件中尝试,以免出现不必要的错误: <!DOCTYPE html> ...

  3. 使用 v-model 实现 双向绑定.(子组件和父组件.)

    vue 自定义组件 v-model双向绑定. 父子组件同步通信   父子组件通信,都是单项的,很多时候需要双向通信.方法如下: 1.父组件使用:msg.sync="aa"  子组件 ...

  4. 如何在Vue2中实现组件props双向绑定

    Vue学习笔记-3 前言 Vue 2.x相比较Vue 1.x而言,升级变化除了实现了Virtual-Dom以外,给使用者最大不适就是移除的组件的props的双向绑定功能. 以往在Vue1.x中利用pr ...

  5. ionic3.x angular4.x ng4.x 自定义组件component双向绑定之自定义计数器

    本文主要示例在ionic3.x环境下实现一个自定义计数器,实现后最终效果如图: 1.使用命令创建一个component ionic g component CounterInput 类似的命令还有: ...

  6. 自定义组件实现双向绑定v-model

    自定义组件实现 v-model 双向绑定,首先要先明白 v-model,这个指令到底实现了什么? v-model实际做的事情就是:传入一个value属性值,然后监听input事件返回一个值,用该返回值 ...

  7. Vue的数据双向绑定和Object.defineProperty()

    Vue是前端三大框架之一,也被很多人指责抄袭,说他的两个核心功能,一个数据双向绑定,一个组件化分别抄袭angular的数据双向绑定和react的组件化思想,咱们今天就不谈这种大是大非,当然我也没到达那 ...

  8. Vue框架之双向绑定事件

    Vue框架之双向绑定事件 首先介绍下Vue框架的语法 vue通过 {{temp}} 来渲染变量 {{count+100}} # 求和 v-text # 为标签插入text文本 v-html # 为标签 ...

  9. 用ES6的class模仿Vue写一个双向绑定

    原文地址:用ES6的class模仿Vue写一个双向绑定 点击在线尝试一下 最终效果如下: 构造器(constructor) 构造一个TinyVue对象,包含基本的el,data,methods cla ...

随机推荐

  1. Codeforces Round #625 Div. 2 D E

    D题:https://codeforces.com/contest/1321/problem/D 题意:题目给个有向图,然后给一段序列,我们要沿着这个序列走,问走的过程中当前点到t的最短路会重构多少次 ...

  2. HDU 6900 Residual Polynomial【分治 NTT】

    HDU 6900 Residual Polynomial  题意: 给出一个多项式\(f_1(x) = \sum_{i=0}^na_ix^i\) 对于任意\(i>=2\),满足\(f_i(x) ...

  3. Codeforces Round #655 (Div. 2) C. Omkar and Baseball

    题目链接:https://codeforces.com/contest/1372/problem/C 题意 给出一个大小为 $n$ 的排列,每次操作可以选取一个连续子数组任意排列其中的元素,要求每个元 ...

  4. Codeforces Round #533 (Div. 2) B. Zuhair and Strings(字符串)

    #include <bits/stdc++.h> using namespace std; int main() { int n,k;cin>>n>>k; stri ...

  5. 牛客编程巅峰赛S1第5场 - 黄金&钻石&王者 B.牛牛的字符串 (DP)

    题意:有一个字符串\(s\),我们可以选择\(s_{i}\),如果\(s_{i+k}>s_{i}\),那么就可以交换\(s_{i}\)和\(s_{i+k}\),问最多能够交换多少次. 题解:因为 ...

  6. Git 初始化及仓库创建及操作

    一.基本信息设置 1.初始化设置用户名 2.初始化设置用户名邮箱 备注:该设置在Github仓库主页显示谁提交了该文件. 二.初始化一个新的Git仓库 1.创建文件夹 mkdir test 2.在文件 ...

  7. docker 支持systemctl start|stop|status等操作

    用docker运行centos7容器时候,无法使用systemctl,官方解释是centos7的一个bug,可以有修复的办法: 在docker run的时候,加上--privileged 并且cmd使 ...

  8. spring再学习之注解

    1.使用注解配置spring <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi= ...

  9. spring再学习之配置详解

    applicationContext.xml文件配置: bean元素: <?xml version="1.0" encoding="UTF-8"?> ...

  10. 数理统计10(习题篇):寻找UMVUE

    利用L-S定理,充分完备统计量法是寻找UMVUE的最方便方法,不过实际运用时还需要一些小技巧,比如如何写出充分完备统计量.如何找到无偏估计.如何求条件期望,等等.课本上的例题几乎涵盖了所有这些技巧,我 ...