Я хотел бы передать некоторые свойства родительского элемента всем своим дочерним элементам, когда они передаются (синтаксис распространения контента). В этом случае родитель не знает (насколько я знаю) своих детей, поэтому я не знаю, как действовать.
В частности, мне нужен способ написать это:
<my-parent prop1="foo" prop2="bar">
<my-children></my-children> <!-- Must know content of prop1 and prop2 -->
<my-children></my-children> <!-- Must know content of prop1 and prop2 -->
</my-parent>
Вместо того, чтобы писать это:
<my-parent prop1="foo" prop2="bar">
<my-children prop1="foo" prop2="bar"></my-children>
<my-children prop1="foo" prop2="bar"></my-children>
</my-parent>
Возможно ли это? Спасибо.
Вот мое решение, возможно, не так много, но это самое чистое решение для того, что я хочу сделать прямо сейчас. Принцип заключается в создании вычисленных свойств, которые будут использовать собственный компонент, если они существуют, или получить $parent значения в противном случае. Тогда реальная опора будет доступна в этом.
Vue.component('my-children', {
props: ["prop1", "prop2"],
template: "<div>{{_prop1}} - {{_prop2}}</div>",
computed: {
_prop1: function() {
return this.prop1 || this.$parent.prop1;
},
_prop2: function() {
return this.prop2 || this.$parent.prop2;
}
}
});
Вот генератор mixin, который делает это более элегантным способом и, возможно, с несколькими уровнями:
function passDown(...passDownProperties) {
const computed = {};
passDownProperties.forEach((prop) => {
computed["_" + prop] = function() {
return this[prop] || this.$parent[prop] || this.$parent["_" + prop];
};
});
return { computed };
}
Vue.component('my-children', {
props: ["prop1", "prop2"],
template: "<div>{{_prop1}} - {{_prop2}}</div>",
mixins: [passDown("prop1", "prop2")]
});
В этот момент (я не эксперт vue) я просто мог бы подумать в этом решении.
Назначить каждый компонент реквизита скучно, я согласен, так почему бы не сделать это программно?
// Create a global mixin
Vue.mixin({
mounted() { // each component will execute this function after mounted
if (!this.$children) {
return;
}
for (const child of this.$children) { // iterate each child component
if (child.$options._propKeys) {
for (const propKey of child.$options._propKeys) { // iterate each child props
// if current component has a property named equal to child prop key
if (Object.prototype.hasOwnProperty.call(this, propKey)) {
// update child prop value
this.$set(child, propKey, this[propKey]);
// create a watch to update value again every time that parent property changes
this.$watch(propKey, (newValue) => {
this.$set(child, propKey, newValue);
});
}
}
}
}
},
});
Это работает, но вы получите сообщение об уродливом предупреждении vue:
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop value.
Я не уверен, что это хорошее решение, но оно работает, поэтому, если вы решите использовать, просто имейте в виду Global-Mixin рекомендации:
Используйте глобальные миксины редко и тщательно, потому что это влияет на каждый один экземпляр Vue, включая сторонние компоненты.
Пожалуйста, смотрите полный пример в https://github.com/aldoromo88/PropsConvention
Надеюсь, что это поможет
Реквизиты позволяют передавать данные только на один уровень. Если вы хотите увековечить данные, вы можете использовать шину событий.
Проинсталлировать шину событий с пустым экземпляром Vue в основном файле.
var bus = new Vue();
Затем в своем родителе испускаем событие с передаваемыми данными
bus.$emit('myEvent', dataToBePassed);
Слушайте myEvent
в любом месте, где хотите получить данные. В вашем случае это делается в ваших дочерних компонентах
bus.$on('myEvent', function(data) {
.....
});