Vue进阶(幺捌贰):父子组件元素获取、方法互相调用

举报
SHQ5785 发表于 2021/04/14 00:45:44 2021/04/14
【摘要】 前言 Vue项目开发过程中,有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件。梳理出如下请求方法: 父组件访问子组件:$children 或者 $refs子组件访问父组件:$parent子组件访问根组件(通过 new Vue 创建的根 Vue 实例):$root 父组件访问子组件 使用 $children 在父组件中使用 thi...

前言

Vue项目开发过程中,有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件。梳理出如下请求方法:

  • 父组件访问子组件:$children 或者 $refs
  • 子组件访问父组件:$parent
  • 子组件访问根组件(通过 new Vue 创建的根 Vue 实例):$root

父组件访问子组件

使用 $children

在父组件中使用 this.$children 拿到的是一个数组类型,它包含所有子组件实例。

<div id="app">
  <cpn></cpn>
  <cpn></cpn>
  <button @click="btnClick">按钮</button>
</div>

<template id="cpn">
  <div> <h1>我是子组件</h1>
  </div>
</template>

<script>
  let vm = new Vue({ el: "#app", data: {}, methods: { btnClick() { //1.拿到所有子组件,是一个数组 console.log(this.$children); //2.拿到一个组件实例,可以直接访问子组件中的方法和 data 中的数据 this.$children[0].showMessage(); console.log(this.$children[0].name); } }, components: { cpn: { template: '#cpn', data() { return { name: 'webchang' } }, methods: { showMessage() { console.log('我是子组件'); } } } }
  });
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

使用 $refs

使用$children 的缺陷如下:

通过 $children 访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。

但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。

有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用 $refs

$refs 的使用

通过设置子组件的ref,父组件通过this.$refs.xxx.method_name(data)调用子组件方法,data参数可选。

$refsref 指令通常是一起使用的。

首先,我们在子组件上添加一个 ref 属性,相当于给某一个子组件绑定一个特定的ID

其次,this.$refs 拿到的是所有标有 ref 属性的子组件(如果一个子组件实例没有 ref 属性,通过这种方式是拿不到的),最后拿到的是一个对象,属性名是子组件实例的 ref 属性,属性值是该组件实例。

通过 this.$refs.ID 就可以访问到该组件。

示例代码如下:

<div id="app">
  <cpn ref="child1"></cpn>
  <cpn ref="child2"></cpn> <!-- 这个子组件实例没有 ref 属性,通过 this.$refs 方式拿不到这个组件实例 -->
  <cpn></cpn>
  <button @click="btnClick">按钮</button>
</div>

<template id="cpn">
  <div> <h1>我是子组件</h1>
  </div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  let vm = new Vue({ el: "#app", data: { message: "hello" }, methods: { btnClick() { console.log(this.$refs) console.log(this.$refs.child1) console.log(this.$refs.child1.name) this.$refs.child1.showMessage('父组件') } }, components: { cpn: { template: '#cpn', data() { return { name: 'webchang' } }, methods: { showMessage(value) { console.log("子组件方法被调用,调用者:" + value) } } } }
  });
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

子组件调用父组件方法

方法一:this.$parent.event

直接在子组件中通过this.$parent.event来调用父组件的方法。示例代码如下:

父组件

<template>
  <div> <child></child>
  </div>
</template>
<script>
  import child from './components/dam/child';
  export default { components: { child }, methods: { fatherMethod(value) { console.log("父组件方法被调用,调用者:" + value) } }
  };
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

子组件

<template>
  <div> <button @click="childMethod()">点击</button>
  </div>
</template>
<script>
  export default { methods: { childMethod() { this.$parent.fatherMethod('子组件'); } }
  };
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

注意事项

  • 尽管在Vue开发中,我们允许通过 $parent 来访问父组件,但是在真实开发中尽量不要这样做。
  • 子组件应该尽量避免直接访问父组件的数据,因为这样代码耦合度太高了。
  • 如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题。
  • 另外,通过 $parent 直接修改父组件的状态,那么父组件中的状态将变得飘忽不定,很不利于调试和维护。

方法二: $emit

在子组件里用$emit向父组件触发一个事件,父组件监听这个事件。

父组件

<template>
  <div> <child @fatherMethod="fatherMethod"></child>
  </div>
</template>
<script>
  import child from '~/components/dam/child';
  export default { components: { child }, methods: { fatherMethod() { console.log('测试'); } }
  };
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

子组件

<template>
  <div> <button @click="childMethod()">点击</button>
  </div>
</template>
<script>
  export default { methods: { childMethod() { this.$emit('fatherMethod'); } }
  };
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

方法三:方法传参

父组件把方法传入子组件中,在子组件里直接调用这个方法。

父组件

<template>
  <div> <child :fatherMethod="fatherMethod"></child>
  </div>
</template>
<script>
  import child from '~/components/dam/child';
  export default { components: { child }, methods: { fatherMethod() { console.log('测试'); } }
  };
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

子组件

<template>
  <div> <button @click="childMethod()">点击</button>
  </div>
</template>
<script>
  export default { props: { fatherMethod: { type: Function, default: null } }, methods: { childMethod() { if (this.fatherMethod) { this.fatherMethod(); } } }
  };
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

子组件 更简便的写法

<template>
  <div> <button @click="fatherMethod()">点击</button>
  </div>
</template>
<script>
  export default { props: { fatherMethod: { type: Function, default: null } }, methods: { }
  };
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

其他调用方法

由于最终所有组件都会渲染成真实的Dom元素,所以可以通过jsjquery,获取Dom元素对象,通过模拟点击的方式触发元素绑定的方法,通过本地CookielocalStoragesessionStorage做参数缓存,实现值传递。此方法不限于子父组件,只要组件位于同一页面都可使用,但因为不符合vue规范,并非特殊情况不建议使用。

组件A:

<template>
  <div> <h1>我是组件A</h1> <button id='btn' @click='methodA()'>点我</button>
  </div>
</template>
<script>
  export default { methods: { methodA() { var parameter= localStorage.getItem('parameter'); console.log('我是组件A方法'); } }
  };
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

组件B:

<template>
  <div> <h1>我是组件B</h1> <button @click='methodB(data)'>点我</button>
  </div>
</template>
<script>
  export default { methods: { methodB(data) { localStorage.setItem('parameter',data); $('#btn').click();//模拟按钮点击 console.log('模拟点击按钮,触发A组件方法'); } }
  };
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

文章来源: shq5785.blog.csdn.net,作者:No Silver Bullet,版权归原作者所有,如需转载,请联系作者。

原文链接:shq5785.blog.csdn.net/article/details/108573581

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。