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 相关文章推荐
jquery时间下拉框小例子
Apr 15 Javascript
禁止iframe页面的所有js脚本如alert及弹出窗口等
Sep 03 Javascript
JavaScript中的对象序列化介绍
Dec 30 Javascript
jquery事件preventDefault()方法用法实例
Jan 16 Javascript
Bootstrap每天必学之导航组件
Apr 25 Javascript
Javascript在IE和Firefox浏览器常见兼容性问题总结
Aug 03 Javascript
在Vue.js中使用Mixins的方法
Sep 12 Javascript
JS 中使用Promise 实现红绿灯实例代码(demo)
Oct 20 Javascript
Vue2.0 实现单选互斥的方法
Apr 13 Javascript
适合前端Vue开发童鞋的跨平台Weex的使用详解
Oct 16 Javascript
javascript实现倒计时效果
Feb 17 Javascript
js删除对象中的某一个字段的方法实现
Jan 11 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计划任务、定时执行任务的实现代码
2011/04/23 PHP
深入PHP5中的魔术方法详解
2013/06/17 PHP
PHP中调用SVN命令更新网站方法
2015/01/07 PHP
php+ajax实现异步上传文件或图片功能
2017/07/18 PHP
PHP实现腾讯与百度坐标转换
2017/08/05 PHP
PHP类的自动加载与命名空间用法实例分析
2020/06/05 PHP
jquery.validate使用时遇到的问题
2015/05/25 Javascript
js实现浮动在网页右侧的简洁QQ在线客服代码
2015/09/04 Javascript
JQUERY表单暂存功能插件分享
2016/02/23 Javascript
jQuery EasyUI 右键菜单--关闭标签/选项卡的简单实例
2016/10/10 Javascript
jQuery弹出层插件popShow用法示例
2017/01/23 Javascript
bootstrap中添加额外的图标实例代码
2017/02/15 Javascript
ES6正则表达式扩展笔记
2017/07/25 Javascript
JavaScript函数中的this四种绑定形式
2017/08/15 Javascript
基于jQuery实现定位导航位置效果
2017/11/15 jQuery
vue移动UI框架滑动加载数据的方法
2018/03/12 Javascript
实用Javascript调试技巧分享(小结)
2019/06/18 Javascript
Python递归遍历列表及输出的实现方法
2015/05/19 Python
Python实现string字符串连接的方法总结【8种方式】
2018/07/06 Python
Django实战之用户认证(初始配置)
2018/07/16 Python
Python图像处理之图像的读取、显示与保存操作【测试可用】
2019/01/04 Python
Python3.5 Pandas模块之DataFrame用法实例分析
2019/04/23 Python
Django 博客实现简单的全文搜索的示例代码
2020/02/17 Python
Django websocket原理及功能实现代码
2020/11/14 Python
html5的画布canvas——画出弧线、旋转的图形实例代码+效果图
2013/06/09 HTML / CSS
Top Villas美国:豪华别墅出租和度假屋
2018/07/10 全球购物
Ted Baker美国官网:英国时尚品牌
2018/10/29 全球购物
护士毕业生自荐信
2014/02/07 职场文书
党员自我批评与反省材料
2014/02/10 职场文书
一份恶作剧的检讨书
2014/09/13 职场文书
国家税务局领导班子对照检查材料思想汇报
2014/10/04 职场文书
2014年便民服务中心工作总结
2014/12/20 职场文书
先进典型事迹材料
2014/12/29 职场文书
2015年大学组织委员个人工作总结
2015/10/23 职场文书
党风廉政建设心得体会
2019/05/21 职场文书
党员学习型组织心得体会
2019/06/21 职场文书