Я знаю, что я хочу напрямую изменить dom (нет, нет в vue.js), однако единственные альтернативы, которые я могу придумать, будут создавать гораздо более неряшливый и сложный для поддержки код.

Проблема

Я использую vue-i18n, и в зависимости от того, какой язык выбрал пользователь в данный момент, я хочу переместить символ валюты либо впереди, либо за элементом цены (у меня есть много элементов, отображающих цену на многих страницах, фактически более 150 .)

Альтернативы

Лучшая альтернатива, которую я могу придумать, - это добавить привязку :class к каждому элементу, который нужно поменять местами, но для этого мне пришлось бы добавить тонну v-ifs + {{X2} } + дополнительная разметка на каждой из 15 отдельных страниц сайта (+ логика vuex). Мне также, вероятно, пришлось бы использовать ::before и ::after в css, создать класс для каждого языка и добавить символ в content: '' каждого из них.

Недавно рассмотренное решение

Я подумал, что было бы проще просто использовать хук mounted внутри app.vue, который будет запускаться в nextTick() (чтобы дочернее представление было полностью отрисовано), а затем вызвать функцию для добавления символа валюты либо до, либо после всех элементов, которые включают класс priceItem.

Таким образом, у меня не было бы всей дополнительной разметки и v-if, загрязняющих мой шаблон, хотя я бы изменил dom напрямую, хотя и только после того, как все будет отрисовано.

Есть ли какие-либо альтернативы вышеизложенному, которые позволят мне добиться желаемой простоты, но при этом добиться этого с помощью шаблона типа Vue?

Пример кода (app.vue)

    this.$nextTick(function () {
  // Get currently selected lang from i18n
  let lang = this.$i18n.locale

  // get correct currency symbol for selected language
  let symbol = ''

  switch (lang) {
    case 'ko':
      symbol = '₩'
      break
    case 'en':
      symbol = '$'
      break
    case 'ja':
      symbol = '¥'
      break
    case 'zh':
      symbol = '¥'
      break
    case 'es':
      symbol = '€'
      break
    case 'ru':
      symbol = '₽'
      break
  }

  // if lang is Korean append symbol after, else append before
  if (lang !== 'ko') {
    document
      .querySelector('priceItem')
      .insertAdjacentText('beforeBegin', symbol)
  } else {
    document
      .querySelector('priceItem')
      .insertAdjacentText('afterBegin', symbol)
  }
})

РЕДАКТИРОВАТЬ:

Если подумать, это, вероятно, было бы лучше в опоре computed, чтобы я мог переназначать символ всякий раз, когда пользователь меняет язык.

1
Tim Titus 7 Дек 2020 в 12:02

1 ответ

Лучший ответ

Для тех, кто ищет быстрое решение для Vue, я использовал этот пакет для решения своей проблемы:

https://github.com/vinayakkulkarni/vue-intl-numberformat

В своем шаблоне я использовал следующий формат:

<vue-intl-numberformat
   locale="en-IN"
   format-style="currency"
   :currency="getCurrency"
   :number="item.price"
 />

...

computed: {
   ...mapGetters(['getCurrency'])
}

Затем я передаю ему правильную валюту на основе активно выбранного языка в i18n через геттер.

(В моем магазине vuex)

  getCurrency: (state) => {
    let activeLang = i18n.locale
    let currency = ''

    switch (activeLang) {
      case 'en':
        currency = 'USD'
        break
      case 'ko':
        currency = 'KRW'
        break
      case 'ja':
        currency = 'JPY'
        break
      case 'es' || 'fr' || 'it':
        currency = 'EUR'
        break
      case 'zh':
        currency = 'CNY'
        break
      case 'ru':
        currency = 'RUR'
        break
    }
    state.currency = currency
    return state.currency
  }

На данный момент это кажется самым чистым решением.

0
Tim Titus 9 Дек 2020 в 11:14