Как передать переменные экземпляра Rails в компоненты Vue

1656659529 kak peredat peremennye ekzemplyara rails v komponenty vue

Гарет Фуллер

O8jLrVZ6GSHmqVATENFr3aMLxOaQdr8qfGs-

Сейчас я работаю с устаревшей программой Rails. Мы медленно переходим интерфейс от представлений Rails к программе Vue.

В рамках этого перехода, у нас есть некоторые элементы, которые мы хотим превратить в глобальные компоненты Vue. Мы хотим иметь возможность использовать эти компоненты в существующих представлениях Rails и в программе Vue без необходимости настраивать каждый компонент для обработки обеих ситуаций.

Прежде чем поделиться своим решением этой проблемы, вот пример однофайлового компонента Vue, который мы хотим использовать в обоих сценариях (просмотр Rails и программа Vue):

// Payments.vue
<template lang="html">  <div id="payments>    <div class="payment" v-for="payment in payments>      {{ payment.amount }}    </div>  </div></template>
<script>export default {  name: 'payments'
  props: {    payments: { type: Array }  }}</script>
<style lang="scss" scoped></style>

В программе Vue это простой компонент для использования, не правда ли? Например:

// app/javascript/App.vue
<template lang="html">  <div id="app>    <payments :payments="payments" />  </div></template>
<script>import Payments from './Payments.vue'
export default {  name: 'app',
  components: { Payments },
  data () {    return {      payments: [        { amount: 123.00 },        { amount: 124.00 }      ]    }  }</script>
<style lang="scss" scoped></style>

Но как насчет использования его в представлении Rails?

Решение

Итак, решения для использования Payments.vue компонент в Rails выглядит так:

// app/views/payments/index.haml
.global-comp  = content_tag 'comp-wrapper', nil, data: { component: 'payments', props: { payments: @payments } }.to_json

Давайте разберем этот элемент.

.global-comp есть div (с классом “global-comp”) для монтирования сверхпростого экземпляра Vue. Этот экземпляр Vue дает нам компонент-калитку для использования. CompWrapper.vue (в минуту мы разберемся, для чего предназначен CompWrapper).

Вот экземпляр Vue, к которому установлен .global-comp:

// app/javascript/packs/global_comp.js
import Vue from 'vue/dist/vue.esm'import CompWrapper from './CompWrapper'
document.addEventListener('DOMContentLoaded', () => {  const app = new Vue({    components: { CompWrapper }  }).$mount('.global-comp')})

Все это делает компонент (CompWrapper.vue), доступный нам в div с классом global-comp.

Если вы используете Webpacker из Rails, вам нужно будет включить этот пакет в ваш макет где-нибудь перед закрывающим тегом body. Например:

// app/views/layouts/application.haml
...
= javascript_pack_tag "global_comp"

CompWrapper.vue

Это самое интересное. CompWrapper.vue позволяет нам передать:

  1. Название компонента, который мы хотим использовать, например, «платежи»
  2. Реквизит, который мы хотим передать ему

Общая цель этого компонента-оболочки состоит в том, чтобы позволить нам передавать переменные экземпляра Rails, например @payments в наши компоненты как реквизиты без необходимости обрабатывать это изнутри каждого компонента Payments.vue.

Так вот CompWrapper.vue:

// app/javascript/CompWrapper.vue
<template lang="html">  <component :is="data.component" v-bind="data.props"></component></template>
<script>import * as components from './components'
export default {  name: 'comp-wrapper',
  components,
  data () {    return {      data: {}    }  },
  created() {    this.data = JSON.parse(this.$attrs.data)  }}</script>
<style lang="scss" scoped></style>

Первое, что делает компонент CompWrapper, берет атрибуты данных, которые вы устанавливаете для элемента в представлении Rails, анализирует JSON и устанавливает внутренний атрибут данных Vue с анализируемыми данными:

created() {  this.data = JSON.parse(this.$attrs.data)}

с this.data set мы можем использовать его для выбора компонента, который мы хотим использовать, и передать ему свойства, которые мы предоставили в нашем представлении Rails с помощью динамического компонента Vue:

<component :is="data.component" v-bind="data.props"></component>

И все это!

Теперь мы можем использовать компоненты Vue, как они предназначены для использования, но в наших представлениях rails. ?

Добавить комментарий

Ваш адрес email не будет опубликован.