vue-learning:30 - component - 组件实例的引用方式
组件实例的引用方式
ref / $refs$root$parent$children- 扩展查找任意组件实例的方法
在vue开发的项目中,通常会以一棵嵌套的组件树的形式来组织项目。
- 都存在着一个根组件
- 组件同时也都是 Vue 实例,组件间可以嵌套使用,形成了树状的级联形式,也就形成了父子组件、兄弟组件、祖先或后代组件这些关系。

在实际开发中,有时需要获取某个组件实例来引用其数据或方法。在前面讲解组件API的event时,通过ref / $refs调用组件实例来进行事件监听和触发。但$refs只能引用该组件下的子组件。
但实际上vue还提供其它几个API来获取组件实例$root / $parent / $children,我们也可以基于这些来扩展查找组件实例的便捷方法。

<div id="app">
<child1></child1>
</div>
const child1 = Vue.extend({template: `<div>子组件1<child1_1></child1_1></div>`})
const child1_1 = Vue.extend({
template: `<div>
<button @click="handleClick">子组件1_1,点击打印</button>
<child1_1_1></child1_1_1>
<child1_1_2 ref="child1_1_2"></child1_1_2/>
</div>`,
methods: {
handleClick() {
console.log('this:',this.$vnode.tag)
console.log('this.$root:',this.$root)
console.log('this.$parent:',this.$parent.$vnode.tag)
console.log('this.$children:',this.$children)
console.log('this.$children[0]:',this.$children[0].$vnode.tag)
console.log('this.$children[1]:',this.$children[1].$vnode.tag)
console.log('this.$refs.child1_1_2:',this.$refs.child1_1_2.$vnode.tag)
}
}
})
const child1_1_1 = Vue.extend({template: `<div>子组件1_1_1</div>`})
const child1_1_2 = Vue.extend({template: `<div>子组件1_1_2</div>`})
Vue.component('child1',child1)
Vue.component('child1_1',child1_1)
Vue.component('child1_1_1',child1_1_1)
Vue.component('child1_1_2',child1_1_2)
const vm = new Vue({
el: "#app",
})
this: vue-component-2-child1_1
this.$root: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
this.$parent: vue-component-1-child1
this.$children: [VueComponent, VueComponent]
this.$children[0]: vue-component-3-child1_1_1
this.$children[1]: vue-component-4-child1_1_2
this.$refs.child1_1_2: vue-component-4-child1_1_2
根据组件名称查找任意组件实例
点击查看参考链接:https://github.com/icarusion/vue-component-book
场景:
- 由一个组件,向上找到最近的指定组件
- 由一个组件,向上找到所有的指定组件
- 由一个组件,向下找到最近的指定组件
- 由一个组件,向下找到所有指定的组件
- 由一个组件,找到指定组件的兄弟组件
实现:
结合$parent / $children,通过递归、遍历查找与指定组件的name选项匹配的组件实例。
// 由一个组件,向上找到最近的指定组件
function findComponentUpward (context, componentName) {
let parent = context.$parent;
let name = parent.$options.name;
while (parent && (!name || [componentName].indexOf(name) < 0)) {
parent = parent.$parent;
if (parent) name = parent.$options.name;
}
return parent;
}
// 由一个组件,向上找到所有的指定组件
function findComponentsUpward (context, componentName) {
let parents = [];
const parent = context.$parent;
if (parent) {
if (parent.$options.name === componentName) parents.push(parent);
return parents.concat(findComponentsUpward(parent, componentName));
} else {
return [];
}
}
// 由一个组件,向下找到最近的指定组件
function findComponentDownward (context, componentName) {
const childrens = context.$children;
let children = null;
if (childrens.length) {
for (const child of childrens) {
const name = child.$options.name;
if (name === componentName) {
children = child;
break;
} else {
children = findComponentDownward(child, componentName);
if (children) break;
}
}
}
return children;
}
// 由一个组件,向下找到所有指定的组件
function findComponentsDownward (context, componentName) {
return context.$children.reduce((components, child) => {
if (child.$options.name === componentName) components.push(child);
const foundChilds = findComponentsDownward(child, componentName);
return components.concat(foundChilds);
}, []);
}
// 由一个组件,找到指定组件的兄弟组件
// 每个vue组件实例都有一个唯一的_uid
function findBrothersComponents (context, componentName, exceptMe = true) {
let res = context.$parent.$children.filter(item => {
return item.$options.name === componentName;
});
let index = res.findIndex(item => item._uid === context._uid);
if (exceptMe) res.splice(index, 1);
return res;
}
vue-learning:30 - component - 组件实例的引用方式的更多相关文章
- VUE 动态加载组件的四种方式
动态加载组件的四种方式: 1.使用import导入组件,可以获取到组件 var name = 'system'; var myComponent =() => import('../compon ...
- vue中js获取组件实例
获取到的VM实例,外部js仍然能自由调用VM的一切属性和方法. <template> </template> <script> // 声明变量currVM let ...
- Vue中封装axios组件实例
首先要创建一个网络模块network文件夹 里面要写封装好的几个组件 在config.js里面这样写 在index.js要这样写 core.js文件里面内容如下 然后要在main.js文件里面要设置 ...
- Vue加载组件、动态加载组件的几种方式
https://cn.vuejs.org/v2/guide/components.html https://cn.vuejs.org/v2/guide/components-dynamic-async ...
- vue动态加载组件
vue动态加载组件,可以使用以下方式 <component :is="propertyname" v-for="tab in tabs"></ ...
- 在被vue组件引用的 js 文件里获取组件实例this
思路: 通过调用函数 把 组件实例this 传递 到 被应用的 js文件里 实例: 文件结构 在SendThis.vue 文件中引用 了modalConfig.js import modalConf ...
- 二、Vue组件(component):组件的相互引用、通过props实现父子组件互传值
一.组件各部分说明及互相引用 1.一个vue组件由三个部分组成 Template 只能存在一个根元素 2.Script 3.Style scoped:样式只在当前组件内生效 1.1 组件的基本引用代码 ...
- 第七十七篇:ref引用(在vue中引用组件实例)
好家伙, 为方便理解, 我们先来写一个经典自增一按钮, 再加上一个count清零按钮, Left.vue组件中: <template> <div > <h1>我是L ...
- vue构造函数(根实例化时和组件实例对象选项)参数:选项详解
实例选项(即传给构造函数的options):数据,DOM,生命周期钩子函数,资源,组合,其他 数据 data 属性能够响应数据变化,当这些数据改变时,视图会进行重渲染. 访问方式: 1.通过 vm.$ ...
随机推荐
- Leetcode830.Positions of Large Groups较大分组的位置
在一个由小写字母构成的字符串 S 中,包含由一些连续的相同字符所构成的分组. 例如,在字符串 S = "abbxxxxzyy" 中,就含有 "a", " ...
- python开发资源链接
1.docker docker Windows版下载:https://oomake.com/download/docker-windows docker 英文官网:https://www.docker ...
- CSS3摆动动画效果
效果图:红包在左右摇晃 代码如下: @keyframes upAnimation { 0 % { transform: rotate(0 deg);transition - timing - func ...
- 【C++】为什么构造函数没有返回值?(转载)
为什么构造函数没有返回值? 意见(1) 我认为构造函数隐含的返回值就是this,因为构造函数是在类的对象产生时自动调用.构造函数被调用也就意味着产生了一个对象,而this指针是与对象实体相关联的, ...
- SDUT-3342_数据结构实验之二叉树三:统计叶子数
数据结构实验之二叉树三:统计叶子数 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 已知二叉树的一个按先序遍历输入的字符 ...
- SDUT-3340_数据结构实验之二叉树一:树的同构
数据结构实验之二叉树一:树的同构 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定两棵树T1和T2.如果T1可以通过 ...
- QT 获取系统时间
1.导入QTime #include <QTime> 2.定义QTime 对象接受当前时间 QTime t=QTime::currentTime(); t就是系统时间. 3.将t转化为st ...
- Python中多线程与多进程的恩恩怨怨
概念: 并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运 ...
- 解决ArcMap绘图错误
这几天在用ArcMap对shapefile做矢量化的过程中,遇到一件特别蛋疼的事,ArcMap竟然会出现绘图错误.如下所示: 纠结了许久之后,终于在Esri社区找到了解决办法:帮助文档中说 “检查属性 ...
- 12-2 js基础
一 数据类型 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...