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 相关文章推荐
LBS blog sql注射漏洞[All version]-官方已有补丁
Aug 26 Javascript
javascript 定义新对象方法
Feb 20 Javascript
js字符串转成JSON
Nov 07 Javascript
javascript数据结构与算法之检索算法
Apr 04 Javascript
Vue.js教程之计算属性
Nov 11 Javascript
bootstrap table操作技巧分享
Feb 15 Javascript
JS判断两个对象内容是否相等的方法示例
Apr 10 Javascript
详解angular部署到iis出现404解决方案
Aug 14 Javascript
koa2使用ejs和nunjucks作为模板引擎的使用
Nov 27 Javascript
微信小程序如何利用getCurrentPages进行页面传值
Jul 01 Javascript
JavaScript布尔运算符原理使用解析
May 06 Javascript
vue 公共列表选择组件,引用Vant-UI的样式方式
Nov 02 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程序员工具
2008/05/26 PHP
解析用PHP读写音频文件信息的详解(支持WMA和MP3)
2013/05/10 PHP
免费的ip数据库淘宝IP地址库简介和PHP调用实例
2014/04/08 PHP
php mysql PDO 查询操作的实例详解
2017/09/23 PHP
php探针使用原理和技巧讲解
2019/09/17 PHP
json 入门基础教程 推荐
2009/10/31 Javascript
判断目标是否是window,document,和拥有tagName的Element的代码
2010/05/31 Javascript
用js一次改变多个input的readonly属性值的方法
2014/06/11 Javascript
jQuery实现伸展与合拢panel的方法
2015/04/30 Javascript
js命名空间写法示例
2015/12/18 Javascript
AnjularJS中$scope和$rootScope的区别小结
2016/09/18 Javascript
bootstrap日历插件datetimepicker使用方法
2016/12/14 Javascript
JS Select下拉框(支持输入模糊查询)
2017/02/04 Javascript
nodeJS模块简单用法示例
2018/04/21 NodeJs
vue--vuex详解
2019/04/15 Javascript
Python+matplotlib+numpy实现在不同平面的二维条形图
2018/01/02 Python
对python中的xlsxwriter库简单分析
2018/05/04 Python
python计算列表内各元素的个数实例
2018/06/29 Python
对python读取CT医学图像的实例详解
2019/01/24 Python
python3通过selenium爬虫获取到dj商品的实例代码
2019/04/25 Python
Django {{ MEDIA_URL }}无法显示图片的解决方式
2020/04/07 Python
Python日志打印里logging.getLogger源码分析详解
2021/01/17 Python
俄罗斯卫浴采暖及维修用品超级市场:Dkrussia
2020/05/12 全球购物
Nike瑞士官网:Nike CH
2021/01/18 全球购物
期末自我鉴定
2014/01/23 职场文书
一年级语文教学反思
2014/02/13 职场文书
互联网电子商务专业毕业生求职信
2014/03/18 职场文书
百货商场楼层班组长竞聘书
2014/03/31 职场文书
小学数学课后反思
2014/04/23 职场文书
竞选文艺委员演讲稿
2014/04/28 职场文书
英语专业毕业生求职信
2014/05/24 职场文书
保护水资源的标语
2014/06/17 职场文书
2014法院四风问题对照检查材料思想汇报
2014/10/04 职场文书
2015年幼儿园教育教学工作总结
2015/05/25 职场文书
读《瓦尔登湖》有感:每个人都需要一个瓦尔登湖
2019/10/17 职场文书
用Python写一个简易版弹球游戏
2021/04/13 Python