OwlCoder
vue - Оборачивание компонента с помощью render функции
Это перевод статьи https://medium.com/7gravity/wrapping-vue-components-by-using-render-function-983b396a3bfa
Часто нам необходимо обернуть определённые компоненты в один общий компонент, для достижения каких бы то ни было целей. В текущем проекте, над которым я работаю, Мне нужно иметь возможность оборачивать все компоненты в компонент c-component с конкретными классами атрибутами.
<c-chart><c-chart> <c-table><c-table> <c-list><c-list>
<c-element class="c-element" data-id="1"> <c-chart><c-chart> </c-element> <c-element class="c-element" data-id="2"> <c-table><c-table> </c-element> <c-element class="c-element" data-id="3"> <c-list><c-list> </c-element>
Для того, чтобы это сделать у нас есть много возможностей, которые нам предоставляет vue фреймворк: от использования композиции компонентов до наследования от базового компонента и обработки оборачивания в темплейтах или render функции.
Так как я предпочитаю примеси (mixins) и слишком ленив, для того, чтобы менять все компоненты, я подумал - "Почему бы не использовать render функцию внутри mixin? Как оказалось, render функция ведёт себя так же как и остальные функции в примеси - сначала вызываются функции примеси, а затем функции самого компонента.
К счастью vue предлагает определённые стратегии объединения функционала (последовательность вызова функций). Стоит попробовать использовать это! Для начала необходимо использовать render функцию из компонента и затем вставлять результат как последний аргумент в render функции примеси. В этом случае примесь имела бы оборачиваемый компонент как содержимое, вставляемое внутрь себя. Собственно здесь описана эта стратегия:
Vue.config.optionMergeStrategies.render = (parentVal, childVal) => { if (parentVal) { const mergedParentVal = function render(...args) { args.push([childVal.apply(this, args)]); return parentVal.apply(this, args); }; return mergedParentVal; } return childVal; };
Если у нас есть функция render в примеси (parentVal), мы создаём новую render функцию, которая выполняет render функцию компонента(childVal), затем добавляет результат как последний аргумент render функции примеси и выполняет её. Таким образом мы просто должны создать mпримесь для нашей обёртки (автор называет её elementable).
export default { render(createElement, children) { return createElement( "div", { class: "c-element", style: { background: "red", padding: "1em", }, }, [ "This is a parent element", ...children, ], ); }, };
Далее мы просто подключаем примесь в нужном компоненте
{ mixins: [elementable], render(createElement) { return createElement( "div", { style: { background: "yellow" } }, "This is child element" ); } }
Теперь мы знакомы с таким необычным путём управления композицией объектов, но этот путь работает и достаточно прост в реализации на больших количествах компонентов. Я не проводил тестов связанных с производительностью данных методов.
Реализация на codepen: