說明
【Vue 開發實戰】學習筆記。
ref 引用資訊
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiQDOxEzX3xCZlhXam9VbsUmepNXZy9CXwJWZ3xCdh1mcvZ2Lc1zaHRGcWdUYuVzVa9GczoVdG1mWfVGc5RHLwIzX39GZhh2csATMflHLwEzX4xSZz91ZsAzMfRHLGZkRGZkRfJ3bs92YskmNhVTYykVNQJVMRhXVEF1X0hXZ0xiNx8VZ6l2cssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4YTMzkjY3gjM1EWNjRjMzYzX3ETM1IDM3EzLclDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
遞歸查找
- 代碼繁瑣.
- 性能低效
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,) => {
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,) {
binding.value(vnode.componentInstance || el, vnode.key);
},
update: function update(el, binding, vnode,) {
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,) {
binding.value(null, vnode.key);
}
});
}
};