Vue 开发实战基础篇 # 13:如何优雅地获取跨层级组件实例(拒绝递归)
Posted 凯小默
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 开发实战基础篇 # 13:如何优雅地获取跨层级组件实例(拒绝递归)相关的知识,希望对你有一定的参考价值。
说明
【Vue 开发实战】学习笔记。
ref 引用信息
递归查找
- 代码繁琐.
- 性能低效
callback ref
- 主动通知(setXxxRef)
- 主动获取(getXxxRef)
比如E节点更新就通知A组件,A组件进行ref的缓存即可
组件A
<template>
<div class="border">
<h1>A 结点</h1>
<button @click="getHRef">获取子孙节点 E Ref</button>
<ChildrenB />
<ChildrenC />
<ChildrenD />
</div>
</template>
<script>
import ChildrenB from "./ChildrenB";
import ChildrenC from "./ChildrenC";
import ChildrenD from "./ChildrenD";
export default
components:
ChildrenB,
ChildrenC,
ChildrenD
,
provide()
return
setChildrenRef: (name, ref) =>
console.log("A 组件 setChildrenRef", name);
this[name] = ref;
,
getChildrenRef: name =>
console.log("A 组件 getChildrenRef", name);
return this[name];
,
getRef: () =>
console.log("A 组件 getRef");
return this;
;
,
data()
return
color: "blue"
;
,
methods:
getHRef()
console.log(this.childrenE);
;
</script>
组件D
<template>
<div class="border1">
<h2>D 结点</h2>
<ChildrenG />
<ChildrenH v-ant-ref="c => setChildrenRef('childrenH', c)" />
<ChildrenI />
</div>
</template>
<script>
import ChildrenG from "./ChildrenG";
import ChildrenH from "./ChildrenH";
import ChildrenI from "./ChildrenI";
export default
components:
ChildrenG,
ChildrenH,
ChildrenI
,
inject:
setChildrenRef:
default: () =>
;
</script>
组件E
<template>
<div class="border2">
<h3 v-ant-ref="c => setChildrenRef('childrenE', c)">
E 结点
</h3>
</div>
</template>
<script>
export default
components: ,
inject:
setChildrenRef:
default: () =>
;
</script>
组件F
<template>
<div class="border2">
<h3>F 结点</h3>
<button @click="getARef">获取祖先节点 A Ref</button>
<button @click="getHRef">获取同级节点 H Ref</button>
</div>
</template>
<script>
export default
components: ,
inject:
getParentRef:
from: "getRef",
default: () =>
,
getParentChildrenRef:
from: "getChildrenRef",
default: () =>
,
methods:
getARef()
console.log(this.getParentRef());
,
getHRef()
console.log(this.getParentChildrenRef("childrenH"));
;
</script>
然后点击三个按钮
这里面使用了 v-ant-ref
这个指令,用于通知上层节点更新。我们可以找一下依赖 vue-ref 这个包,看一下指令源码
"use strict";
Object.defineProperty(exports, "__esModule",
value: true
);
exports.default =
install: function install(Vue)
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ;
var directiveName = options.name || 'ref';
Vue.directive(directiveName,
bind: function bind(el, binding, vnode)
binding.value(vnode.componentInstance || el, vnode.key);
,
update: function update(el, binding, vnode, oldVnode)
if (oldVnode.data && oldVnode.data.directives)
var oldBinding = oldVnode.data.directives.find(function (directive)
var name = directive.name;
return name === directiveName;
);
if (oldBinding && oldBinding.value !== binding.value)
oldBinding && oldBinding.value(null, oldVnode.key);
binding.value(vnode.componentInstance || el, vnode.key);
return;
// Should not have this situation
if (vnode.componentInstance !== oldVnode.componentInstance || vnode.elm !== oldVnode.elm)
binding.value(vnode.componentInstance || el, vnode.key);
,
unbind: function unbind(el, binding, vnode)
binding.value(null, vnode.key);
);
;
完整demo源码可以参考这个https://github.com/kaimo313/vue-development-practice/tree/master/vue-demo/src/views/demo13
以上是关于Vue 开发实战基础篇 # 13:如何优雅地获取跨层级组件实例(拒绝递归)的主要内容,如果未能解决你的问题,请参考以下文章