Доступ к данным компонента Vue с помощью $ref.
В этой статье предполагается, что у вас есть базовые знания о реактивной системе Vue и Vue.
Чрезвычайные ситуации — это данность, и иногда мы получаем одну из них при создании интерфейсных приложений, к счастью, большинство этих интерфейсных фреймворков предоставляют нам несколько способов справиться с чрезвычайными ситуациями. В Vue одним из многих аварийных люков является $ref
атрибут.
Как правило, атрибут ref обычно используется для чистых HTML-элементов (например, <input />
element) в Vue точно так же вы можете иметь ссылку на пользовательский компонент (<my-custom-componet />
) и иметь доступ к его вычисляемым значениям, методам, свойствам данных и т. д. Это, однако, следует использовать только в экстренных ситуациях или в крайнем случае.
Доступ к данным — общий подход
Скажем, у нас есть два дочерних компонента (компонент A и компонент B) внутри родительского компонента, и нам по какой-то причине нужно отобразить некоторые данные из компонента A в B и наоборот. видеть грубый набросок ниже:
Общим и рекомендуемым подходом будет отправка данных из A, добавление прослушивателя/обработчика в родительский компонент, а затем передача значения в компонент B через реквизиты. Это будет выглядеть примерно так:
В некоторых случаях нам может понадобиться взломать наш путь и исключить некоторые шаги из этого потока, чтобы немного сократить путь передачи данных. Сказать ComponentA
не нужно будет передавать значение данных родительскому компоненту, тогда мы можем удалить шаги отправки и прослушивания и получить прямой доступ к значениям в ComponentA
из родительского компонента.
Использование $ref
Скажем, у нас есть два одинаковых компонента — Компонент А и Компонент Б.
Компонент А имеет два метода; setThought
который устанавливает значение a thought
data на любое значение, переданное из редактируемого div, и другой метод — readMind
это пока ничего не дает.
<template>
<div>
<div contenteditable @input="setThought($event.target.innerText)">
{{ thought }}
</div>
<div>
<button @click="readMind">What is B thinking?</button> {{ otherThought }}
</div>
</div>
</template>
<script>
export default {
name: "ComponentA",
data() {
return {
thought: 'I should steal a cookie',
otherThought: '',
};
},
methods: {
setThought(value) {
this.thought = value;
},
readMind() { }
},
};
</script>
Компонент Б похожа, только с небольшой разницей в содержании:
<template>
<div>
<div contenteditable @input="setThought($event.target.innerText)">
{{ thought }}
</div>
<div class="">
<button @click="readMind">What is A thinking?</button> {{ otherThought }}
</div>
</div>
</template>
<script>
export default {
name: "ComponentB",
data() {
return {
thought: 'I like school a tiny bit',
otherThought: '',
};
},
methods: {
setThought(value) {
this.thought = value
},
readMind() { }
},
};
</script>
Возможно, вы уже поняли, что мы хотим здесь сделать, а может и нет. Нам нужно, чтобы Компонент А мог читать мысли Компонента Б, без того, чтобы Компонент Б излучал свои мысли.
Для этого у обоих компонентов должно быть что-то общее — их родитель. Чтобы разделить datjsa между двумя компонентами, используя $ref
, они должны быть дочерними элементами одного и того же родительского компонента. Таким образом, в родительском компоненте мы импортируем компоненты A и B в родительский компонент и назначаем атрибуты ref им обоим.
<template>
<div id="app">
<ComponentA ref="componentA" />
<ComponentB ref="componentB" />
</div>
</template>
<script>
import ComponentA from './components/ComponentA.vue'
import ComponentB from './components/ComponentB.vue'
export default {
name: 'App',
components: {
ComponentA,
ComponentB
},
}
</script>
С помощью этой структуры мы можем легко получить доступ к каждому компоненту по ссылке из его родителя следующим образом:
this.$parent.$refs.componentA
OR
this.$parent.$refs.componentB
Теперь мы можем обновить readMind
метод для Component A
чтобы при нажатии кнопки Component A
точно знал бы, что Component B
думает:
<script>
export default {
name: "ComponentA",
methods: {
...
readMind() {
this.otherThought = this.$parent.$refs.componentB.thought
}
...
}
}
</script>
Обратите внимание, что мы можем получить доступ к thought
data в ComponentB, установив для него атрибут ref и обратившись к нему из его родителя.
Мы можем сделать аналогичное обновление для readMind
метод в Компонент Б сделать то же самое — выяснить, что Компонент А думает.
<script>
export default {
name: "ComponentB",
methods: {
...
readMind() {
this.otherThought = this.$parent.$refs.componentA.thought
}
...
}
}
</script>
Как это выглядит?
Можем ли мы также установить значения компонентов?
Конечно, как и 2010 фильм — Начало, давайте заставим мысли Компонента B быть именно теми, о которых думает Компонент A. Мы можем установить значение свойств данных таким же образом:
<script>
export default {
name: "ComponentA",
methods: {
...
setThought(value) {
this.thought = value;
this.$parent.$refs.componentB.thought = value;
},
...
}
}
</script>
В качестве альтернативы вы можете позвонить в setThought
метод КомпонентB из сложный:
<script>
export default {
name: "ComponentA",
methods: {
...
setThought(value) {
this.thought = value;
this.$parent.$refs.componentB.setThought(value);
},
...
}
}
</script>
Как это будет выглядеть?
О, рефери реактивные?
Нет, они не. То, что вы видите, является только результатом вызова setThought
метод каждый раз, когда есть ввод в компоненте А, и, в свою очередь, установка значения this.$parent.$refs.componentB.thought
к тому же значению, что и thought
свойство данных в ComponentA
.
Ссылки — одна из необычных частей Vue, и они могут вызвать проблемы, если вы не понимаете их правильное использование. Самый безопасный способ их использования — вне хуков вашего жизненного цикла и только внутри методов. Кроме того, избегайте прямого использования в шаблонах компонентов или вычисляемых свойствах.
Если вы хотите повозиться с исходным кодом, вы найдете его здесь:
Также, Вот подробное руководство о том, как и где безопасно получить доступ к ссылкам, и, конечно же, официальная документация.
Привет ☕️