Vue组件实例间的直接访问实现代码


Posted in Javascript onAugust 20, 2017

前面的话

有时候需要父组件访问子组件,子组件访问父组件,或者是子组件访问根组件。 在组件实例中,Vue提供了相应的属性,包括$parent、$children、$refs和$root,这些属性都挂载在组件的this上。本文将详细介绍Vue组件实例间的直接访问

$parent 

$parent表示父组件的实例,该属性只读

下面是一个简易实例

<div id="example">
 <parent-component></parent-component>
</div>
<template id="parent-component">
 <div class="parent">
 <h3>我是父组件</h3>
 <input v-model="parentMsg">
 <p>{{parentMsg}}</p>
 <child-component></child-component> 
 </div>
</template>
<template id="child-component">
 <div class="child">
 <h3>我是子组件</h3>
 <p>{{msg}}</p>
 <button v-on:click="showData">显示父组件数据</button> 
 </div>
</template>
<script>
// 注册
Vue.component('parent-component', {
 template: '#parent-component',
 data(){
 return{
  parentMsg:'我是父组件的数据'
 }
 },
 components:{
 'child-component':{
  template:'#child-component',
  data(){
  return{
   msg:''
  }
  },
  methods:{
  showData(){
   this.msg = this.$parent.parentMsg;
  }
  }
 }
 }
})
// 创建根实例
new Vue({
 el: '#example'
})
</script>

$root 

$root表示当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。该属性只读

<div id="example">
 <h3>我是根组件</h3>
 <input v-model="rootMsg">
 <p>{{rootMsg}}</p> 
 <parent-component></parent-component>
</div>
<template id="parent-component">
 <div class="parent">
 <h3>我是父组件</h3>
 <input v-model="parentMsg">
 <p>{{parentMsg}}</p>
 <child-component></child-component> 
 </div>
</template>
<template id="child-component">
 <div class="child">
 <h3>我是子组件</h3>
 <p>
  <button v-on:click="showRootData">显示根组件数据</button><span>{{rootMsg}}</span>
 </p>  
 <p>
  <button v-on:click="showParentData">显示父组件数据</button><span>{{parentMsg}}</span>
 </p>
 </div>
</template>
<script>
// 注册
Vue.component('parent-component', {
 template: '#parent-component',
 data(){
 return{
  parentMsg:'我是父组件的数据'
 }
 },
 components:{
 'child-component':{
  template:'#child-component',
  data(){
  return{
   parentMsg:'',
   rootMsg:''
  }
  },
  methods:{
  showParentData(){
   this.parentMsg = this.$parent.parentMsg;
  },
  showRootData(){
   this.rootMsg = this.$root.rootMsg;
  },  
  }
 }
 }
})
// 创建根实例
new Vue({
 el: '#example',
 data:{
 rootMsg:'我是根组件数据'
 }
})
</script>

$children 

$children表示当前实例的直接子组件。需要注意$children并不保证顺序,也不是响应式的。如果正在尝试使用$children来进行数据绑定,考虑使用一个数组配合v-for来生成子组件,并且使用Array作为真正的来源

<div id="example">
 <parent-component></parent-component>
</div>
<template id="parent-component">
 <div class="parent">
 <h3>我是父组件</h3>
 <button @click="getData">获取子组件数据</button>
 <br>
 <div v-html="msg"></div>
 <child-component1></child-component1> 
 <child-component2></child-component2> 
 </div>
</template>
<template id="child-component1">
 <div class="child">
 <h3>我是子组件1</h3>
 <input v-model="msg">
 <p>{{msg}}</p>
 </div>
</template>
<template id="child-component2">
 <div class="child">
 <h3>我是子组件2</h3>
 <input v-model="msg">
 <p>{{msg}}</p>
 </div>
</template>
<script>
// 注册
Vue.component('parent-component', {
 template: '#parent-component',
 data(){
 return{
  msg:'',
 }
 },
 methods:{
 getData(){
  let html = '';
  let children = this.$children;
  for(var i = 0; i < children.length;i++){
  html+= '<div>' + children[i].msg + '</div>';
  }
  this.msg = html;
 }
 },
 components:{
 'child-component1':{
  template:'#child-component1',
  data(){
  return{
   msg:'',
  }
  },
 },
 'child-component2':{
  template:'#child-component2',
  data(){
  return{
   msg:'',
  }
  },
 }, 
 } 
})
// 创建根实例
new Vue({
 el: '#example',
})
</script>

$refs

组件个数较多时,难以记住各个组件的顺序和位置,通过序号访问子组件不是很方便

在子组件上使用ref属性,可以给子组件指定一个索引ID:

<child-component1 ref="c1"></child-component1>
<child-component2 ref="c2"></child-component2>

在父组件中,则通过$refs.索引ID访问子组件的实例

this.$refs.c1

this.$refs.c2

<div id="example">
 <parent-component></parent-component>
</div>
<template id="parent-component">
 <div class="parent">
 <h3>我是父组件</h3>
 <div>
  <button @click="getData1">获取子组件c1的数据</button>
  <p>{{msg1}}</p>
 </div>
 <div>
  <button @click="getData2">获取子组件c2的数据</button>
  <p>{{msg2}}</p>
 </div>
 <child-component1 ref="c1"></child-component1> 
 <child-component2 ref="c2"></child-component2> 
 </div>
</template>
<template id="child-component1">
 <div class="child">
 <h3>我是子组件1</h3>
 <input v-model="msg">
 <p>{{msg}}</p>
 </div>
</template>
<template id="child-component2">
 <div class="child">
 <h3>我是子组件2</h3>
 <input v-model="msg">
 <p>{{msg}}</p>
 </div>
</template>
<script>
// 注册
Vue.component('parent-component', {
 template: '#parent-component',
 data(){
 return{
  msg1:'',
  msg2:'',
 }
 },
 methods:{
 getData1(){
  this.msg1 = this.$refs.c1.msg;
 },
 getData2(){
  this.msg2 = this.$refs.c2.msg;
 }, 
 },
 components:{
 'child-component1':{
  template:'#child-component1',
  data(){
  return{
   msg:'',
  }
  },
 },
 'child-component2':{
  template:'#child-component2',
  data(){
  return{
   msg:'',
  }
  },
 }, 
 } 
})
// 创建根实例
new Vue({
 el: '#example',
})
</script>

总结 

虽然vue提供了以上方式对组件实例进行直接访问,但并不推荐这么做。这会导致组件间紧密耦合,且自身状态难以理解,所以尽量使用props、自定义事件以及内容分发slot来传递数据。

Javascript 相关文章推荐
javascript面向对象之二 命名空间
Feb 08 Javascript
javascript loadScript异步加载脚本示例讲解
Nov 14 Javascript
用循环或if语句从json中取数据示例
Aug 18 Javascript
Bootstrap每天必学之级联下拉菜单
Mar 27 Javascript
angular+bootstrap的双向数据绑定实例
Mar 03 Javascript
利用jQuery解析获取JSON数据
Apr 08 jQuery
bootstrap suggest下拉框使用详解
Apr 10 Javascript
Angular中sweetalert弹框的基本使用教程
Jul 22 Javascript
在axios中使用params传参的时候传入数组的方法
Sep 25 Javascript
JS获取月的第几周和年的第几周实例代码
Dec 05 Javascript
说说如何在Vue.js中实现数字输入组件的方法
Jan 08 Javascript
js实现简单的轮播图效果
Dec 13 Javascript
JavaScript贪吃蛇小组件实例代码
Aug 20 #Javascript
React Native 环境搭建的教程
Aug 19 #Javascript
ionic App问题总结系列之ionic点击系统返回键退出App
Aug 19 #Javascript
浅谈关于.vue文件中style的scoped属性
Aug 19 #Javascript
如何理解Vue的作用域插槽的实现原理
Aug 19 #Javascript
Vue Transition实现类原生组件跳转过渡动画的示例
Aug 19 #Javascript
JavaScript文件的同步和异步加载的实现代码
Aug 19 #Javascript
You might like
php中ob(Output Buffer 输出缓冲)函数使用方法
2007/07/21 PHP
php生成复杂验证码(倾斜,正弦干扰线,黏贴,旋转)
2018/03/12 PHP
jquery 中的each()跳出循环的语句
2014/05/23 Javascript
基于编写jQuery的无缝滚动插件
2014/08/02 Javascript
轻松创建nodejs服务器(4):路由
2014/12/18 NodeJs
js+css实现tab菜单切换效果的方法
2015/01/20 Javascript
NodeJS使用jQuery选择器操作DOM
2015/02/13 NodeJs
JavaScript和JQuery的鼠标mouse事件冒泡处理
2015/06/19 Javascript
基于JavaScript实现图片点击弹出窗口而不是保存
2016/02/06 Javascript
扩展Bootstrap Tooltip插件使其可交互的方法
2016/11/07 Javascript
jQuery 获取select选中值及清除选中状态
2016/12/13 Javascript
JS实现图片高斯模糊切换效果的焦点图实例
2017/01/21 Javascript
Javascript ES6中数据类型Symbol的使用详解
2017/05/02 Javascript
nuxt+axios解决前后端分离SSR的示例代码
2017/10/24 Javascript
基于Vue+element-ui 的Table二次封装的实现
2018/07/20 Javascript
微信小程序实现分享朋友圈的图片功能示例
2019/01/18 Javascript
Angular Excel 导入与导出的实现代码
2019/04/17 Javascript
layui添加动态菜单与选项卡
2019/07/26 Javascript
JavaScript复制变量三种方法实例详解
2020/01/09 Javascript
Python中的sort()方法使用基础教程
2017/01/08 Python
Python 比较两个数组的元素的异同方法
2017/08/17 Python
全面分析Python的优点和缺点
2018/02/07 Python
Python实现的读取电脑硬件信息功能示例
2018/05/30 Python
pyinstaller打包opencv和numpy程序运行错误解决
2019/08/16 Python
Spring实战之使用util:命名空间简化配置操作示例
2019/12/09 Python
Python class的继承方法代码实例
2020/02/14 Python
使用python操作lmdb对数据读取的实例
2020/12/11 Python
HTML5 本地存储之如果没有数据库究竟会怎样
2013/04/25 HTML / CSS
英国汽车座椅和婴儿车购物网站:Uber Kids
2017/04/19 全球购物
Java里面Pass by value和Pass by Reference是什么意思
2016/05/02 面试题
大学毕业生通用自荐信范文
2013/10/31 职场文书
中学生获奖感言
2014/02/04 职场文书
广告学专业求职信
2014/06/19 职场文书
庆祝新中国成立65周年“向国旗敬礼”网上签名寄语
2014/09/27 职场文书
企业法人代表证明书
2015/06/18 职场文书
插件导致ECharts被全量引入的坑示例解析
2022/09/23 Javascript