[Vue] Использование переменных Vue-i18n и сводка карьера майнинга

JavaScript Vue.js
[Vue] Использование переменных Vue-i18n и сводка карьера майнинга

предисловие

В настоящее время автор находится вShopeeНа работе основным видом деятельности нашей компании является трансграничная электронная коммерция, и в бизнесе участвуют несколько стран, поэтому наши системы будут включать международный перевод. насVueПроект технически принятVue-i18nэта библиотека.

Сегодня поговорим о функции этой библиотеки, использующей переменные при интернационализации. Использование переменных в переводе — очень распространенный сценарий. Самый простой пример, такой как следующий текст, необходимо интернационализировать.

I am Gopal.I am from China

но среди нихGopalа такжеChinaПеременные должны быть переданы, что нам делать в это время?

простой пропуск

Сначала мы определяем символы для перевода следующим образом

"introTips": "I am {name}.I am from {region}"

затем в шаблоне используйте

$t('introTips', { name: 'Gopal一号', region: 'China' })

может сделатьЯ Гопал №1. Я из Китая

Нужно добавить цвет в переменную

Предположим, мыGopalБольше, чем просто копия, должен быть красный? что нам делать? Мы можем визуализировать html напрямую, используя v-html. В настоящее время нам нужно изменить переведенные символы следующим образом.

introTipsTwo: "I am <span class='name'>{name}</span>.I am from {region}"

Прямой рендеринг с v-html

<div
  class="text"
  v-html="$t('introTipsTwo', { name: 'Gopal一号', region: 'China' })"
></div>

Результат рендеринга следующий

<div data-v-763db97b="" class="text">
  I am <span class="name">Gopal一号</span>.I am from China
</div>

image-20210430112350433

Примечание. Этот метод может вызвать XSS-атаки, поэтому не рекомендуется использовать этот метод.

Используйте атрибут места

Первая переведенная копия заменяется на исходную версию переменной.

introTips: "I am {name}.I am from {region}"

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

<i18n path="introTips" tag="div">
  <span class="name" place="name">Gopal 二号</span>
  <span place="region">China</span>
</i18n>

Результат рендеринга следующий:

<div data-v-763db97b="">
  I am <span data-v-763db97b="" place="name" class="name">Gopal 二号</span>.I am from <span data-v-763db97b="" place="region">China</span>
</div>

image-20210430113555745

Мы реализовали нашу схему, ноЭтот метод будет устаревшим в следующей версии, посмотрите внимательно, это не слот во Vue? Да, окончательное официально рекомендуемое решение — это Slot, очень похожее на приведенное выше.

Окончательное решение — слот

Перейдите непосредственно к коду:

<i18n path="introTips" tag="div">
  <template v-slot:name>
    <span class="name">Gopal 三号</span>
  </template>
  <template v-slot:region>
    <span>China</span>
  </template>
</i18n>

Отрендеренный результат аналогичен приведенному выше

<div data-v-763db97b="">
  I am <span data-v-763db97b="" class="name">Gopal 三号</span>.I am from <span data-v-763db97b="">China</span></div>

вопрос

При использовании его в проекте он сообщил об ошибке...

Мой подход точно такой же, как и выше...

сообщить об ошибке

<i18n path="introTips" tag="div">
  <template v-slot:name>
    <span class="name">Gopal 三号</span>
  </template>
  <template v-slot:region>
    <span>China</span>
  </template>
</i18n>
vue.esm.js:628 [Vue warn]: Error in nextTick: "TypeError: Cannot create property 'isRootInsert' on string 'You submit '"

Я чувствую, что снова потеряю волосы....

Представление точки останова

GoogleПосле прочтения этой ошибки и просмотра информации об ошибке в стеке это похоже на проблему рендеринга vNode, а затем я наткнулся на точку останова, где было сообщено об ошибке.Вы можете видеть, что элементы в массиве дочерних элементов ниже не все vnode .Первым пунктом является строка, которая должна быть виновником ошибки

Читать исходный код

Я посмотрел в node_modulesvue-i18nИсходный код, обратите внимание, что версия, которую я сейчас использую,8.15.0

Обнаружено, что в исходном коде функционального компонента i18n есть два очень странных кода, см. исходный код этого функционального компонента.Связь

export default {
  name: 'i18n',
  functional: true,
  props: {
    // 留意这里
    tag: {
      type: String
    },
		// ...
  },
  render (h: Function, { data, parent, props, slots }: Object) {
    const { $i18n } = parent
		// ...
    const { path, locale, places } = props
    const params = slots()
    const children = $i18n.i(
      path,
      locale,
      onlyHasDefaultPlace(params) || places
        ? useLegacyPlaces(params.default, places)
        : params
    )

    const tag = props.tag || 'span'
    return tag ? h(tag, data, children) : children
  }
}

Обратите внимание на две последние строки кода

const tag = props.tag || 'span'
return tag ? h(tag, data, children) : children

Ах, это. . .childrenНеужели нет возможности казнить?

Я пытаюсь вернуться напрямуюchildren. ну успех...

попробуй обновить версию

Я думал об этом, попробовать обновиться до более новой версии?

Конечно, этот компонент был изменен..., код упрощен, исходный код виденСвязь

export default {
  name: 'i18n',
  functional: true,
  props: {
    // 留意这里
    tag: {
      type: [String, Boolean, Object],
      default: 'span'
    }
    // ...
  },
  render (h: Function, { data, parent, props, slots }: Object) {
    // ....
		// 留意这里
    const tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span'
    return tag ? h(tag, data, children) : children
  }
}

Тег здесь может передавать String, Boolean и Object

Взгляните на официальную документацию

You can choose the root container's node type by specifying a tag prop. If omitted, it defaults to 'span'. You can also set it to the boolean value false to insert the child nodes directly without creating a root element.

Проще говоряТег может быть передан как false, поэтому нет необходимости добавлять еще один узел во внешний слой перевода.

Я снова искал, чтобы исправить этоPRи соответствующийIssue

Решать проблему

Хотя кажется, что это решает проблему отсутствия необходимости настраивать корневой узел, я чувствую, что это также может решить мою проблему.После приведенной ниже версии обновления я изменил свой код.

<div class="test-container">
  <i18n path="introTips" :tag="false">
    <template v-slot:name>
      <span class="name">Gopal 三号</span>
    </template>
    <template v-slot:region>
      <span>China</span>
    </template>
  </i18n>
</div>

На этот раз действительно успешно, очень счастлив, в конечном итоге это следует

<div data-v-0b89d11d="" class="test-container">
  <!-- 这里外层没有节点了 -->
  I am <span data-v-0b89d11d="" class="name">Gopal 三号</span>.I am from <span data-v-0b89d11d="">China</span></div>

Вы можете видеть, что при рендеринге в это время нет самого внешнего тега.

Суммировать

В этой статье рассказывается об использовании переменных vue-i18n, несколько методов относительно просты и понятны. Это в основном для записи ямы, на которую я наступил, и это можно рассматривать как приобретение некоторого опыта.

  • Когда нет идей, можно посмотреть исходный код. Вы можете просмотреть его непосредственно в node_modules или даже найти соответствующий код в файле dist, отладка точек останова
  • Отладка исходного кода не только полезна для обнаружения проблем, но и расширяет горизонты. Например, реализация упомянутого выше функционального компонента i18n. Когда я смотрел на это, если бы меня попросили написать это, смог бы я написать это?
  • Обратите внимание на официальный ISSUE, но в этот раз я посмотрел раньше, а не у меня эта ошибка...
  • Сравните все официальные документы на английском языке, китайский и английский языки совсем разные (должны переводиться лаги)

наконец

Как упоминалось ранее, автор работает в Shopee, и студенты, которым нужно сменить работу, могут попросить меня подтолкнуть его~

На специальной сессии в мае есть много возможностей, вы можете проверить деталиСвязь. Первоклассная заводская заработная плата, меньше сверхурочных (компания способствует эффективной работе), хорошая атмосфера в коллективе, больше возможностей для карьерного роста, заинтересованные студенты, пожалуйста, спешите отправить свое резюме на мой почтовый ящик15521091584@163.com