Ответы пользователя по тегу Vue.js
  • Почему внутри компонента не выводится свойство, а за пределами все норм?

    0xD34F
    @0xD34F Куратор тега Vue.js
    <script type="text/x-template" id="tree-template">
        {{ item }}
    </script>

    Что, просто текст? Нет, так не будет. Должен быть какой-то элемент. Сделайте li - вы же внутри ul пытаетесь их выводить:

    <script type="text/x-template" id="tree-template">
      <li>{{ item }}</li>
    </script>

    <ul v-for="item in items" :key="item.id">
                <tree-items
                        :item="item"
                ></tree-items>
            </ul>

    Множество списков с одним элементом? Может, должен быть один список с множеством элементов? - переносим v-for внутрь списка (кстати, а какого чёрта в имени компонента элемента списка множественное число? почему items, а не item?):

    <ul>
      <tree-items
        v-for="item in items"
        :key="item.id"
        :item="item"
      ></tree-items>
    </ul>
    Ответ написан
  • Как создать вложенный список из объекта Vue?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Нужны отдельные компоненты для страны, региона и города - компонент страны выводит список своих регионов, компонент региона список городов. Например. Или, можно делать компоненты не под отдельные элементы, а под списки - список стран, список регионов, список городов - будет примерно то же самое.
    Ответ написан
    Комментировать
  • Как добавить карту от Leaflet через Vue?

    0xD34F
    @0xD34F Куратор тега Vue.js
    <div ref="map">

    mounted() {
      this.map = L.map(this.$refs.map).setView([ 55.75222, 37.61556 ], 13);
      ...
    Ответ написан
  • Как повесить клик на строчку в таблице?

    0xD34F
    @0xD34F Куратор тега Vue.js
    <v-data-table @click:row="onClickRow">

    methods: {
      onClickRow(item) {
        console.log(item);
      },
      ...
    Ответ написан
    2 комментария
  • Как каждому из экземпляров Vue назначить отдельный Store?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Если воспользуетесь конструктором Vuex.Store более одного раза, вас за это в тюрьму не посадят. Так что вам ничего не мешает создать несколько разных сторов, свой для каждого экземпляра Vue.

    А если их структура должна быть идентична - сделайте функцию, которая будет создавать стор и вместо

    new Vue({
      store: store,
      ...

    будет

    new Vue({
      store: createStore(),
      ...

    https://jsfiddle.net/25L08xj1/
    Ответ написан
    Комментировать
  • Как управлять параметром для отдельного элемента DOM из Vue.js компонента?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Сделайте отдельный компонент для этих секций, со свойством isActive - у каждого экземпляра оно будет собственное. Или этих isActive'ов у вас должен быть массив, длина которого равна количеству секций. Или добавьте свойство isActive элементам sections - каждому.
    Ответ написан
    5 комментариев
  • Как отрефакторить computed методы во Vue?

    0xD34F
    @0xD34F Куратор тега Vue.js
    передавать параметры <...> оставив в computed

    А смысл? Будет computed свойство, значение которого является функцией. Никакого кеширования, только усложнение кода. Делайте обычный метод:

    methods: {
      filterHeroes(attr) {
        const s = this.searchHeroesString.toLowerCase();
        return this.heroes.filter(n => n.hero_attribute === attr && n.name.toLowerCase().includes(s));
      },
    Ответ написан
    Комментировать
  • Как сделать скрытие блока, при клике на любую область?

    0xD34F
    @0xD34F Куратор тега Vue.js
    data: () => ({
      active: false,
    }),
    created() {
      const onClick = e => this.active = this.$refs.block.contains(e.target) && this.active;
      document.addEventListener('click', onClick);
      this.$on('hook:beforeDestroy', () => document.removeEventListener('click', onClick));
    },

    <button @click.stop="active = !active">click me</button>
    <div :class="{ active }" ref="block">hello, world!!</div>
    Ответ написан
    1 комментарий
  • Как при клике на кнопку в блоке открывать модальное окно/выезжающий сайдбар с данными того блока, в котором находиться кнопка?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Добавляете в стейт свойство, которое будет представлять выбранный блок:

    state: {
      opened: null,
      ...

    В экземпляры компонента Trigger передавайте соответствующие им блоки:

    <Trigger :block="block">

    props: [ 'block' ],

    Также, Trigger должен знать, какой блок открыт:

    computed: mapState([ 'opened' ]),

    Чтобы можно было назначить класс кнопке:

    :class="{ 'active' : block === opened }"

    При клике на которую следует передавать блок в мутацию:

    @click="toggleNav(block)"

    Мутация же будет устанавливать значение выбранного блока:

    toggleNav(state, block) {
      state.opened = state.opened === block ? null : block;
    },

    Это если оно действительно toggle. Если просто открытие - тогда достаточно state.opened = block (название мутации в этом случае конечно следует поменять).

    Мутация, отвечающая за закрытие, будет выглядеть так:

    closeSidebarPanel(state) {
      state.opened = null;
    },

    Геттер isNavOpen тоже изменится:

    isPanelOpen(state) {
      return !!state.opened;
    },

    Ну и наконец, можно что-нибудь вывести в Sidebar, например:

    <span v-if="isPanelOpen">{{ $store.state.opened.bName }}</span>

    Но если Sidebar предназначен конкретно для этих блоков, наверное, разумнее будет, чтобы он сам знал, кто сейчас открыт. В Sidebar'е цепляете opened к слоту:

    <slot :block="$store.state.opened"></slot>

    Соответственно, в родительском компоненте:

    <template #default="{ block }">
      <div class="sidebar-panel-settings">
        <div class="setting-block">
          {{ block.bName }}
        </div>
      </div>
    </template>
    Ответ написан
    1 комментарий
  • Как вывести data-attr?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Вам это не надо, не на jquery же пишите. Пусть выбранным значением будет сам элемент массива deliveryPrice, а не какое-то из его свойств:

    <select v-model="selected">
      <option v-for="n in deliveryPrice" :value="n">{{ n.city }}</option>
    </select>

    Ну и выводите чего хотите без проблем:

    <p>{{ selected.city }}</p>
    <p>{{ selected.priceFrom }}</p>


    Если вдруг напрягает [object Object], отображаемый в качестве value в разметке, то можно сделать computed свойство, которое будет представлять выбранный элемент, оставив в v-model строковую переменную:

    <select v-model="city">
      <option v-for="n in deliveryPrice">{{ n.city }}</option>
    </select>

    computed: {
      selected() {
        return this.deliveryPrice.find(n => n.city === this.city);
      },
    },
    Ответ написан
    1 комментарий
  • Как бесконечно проходить по массиву с задержкой?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Чем setInterval не устроил?
    let index = -1;
    setInterval(() => {
      index = (index + 1) % array.length;
      console.log(array[index]);
    }, 500);

    UPD. Вынесено из комментариев:

    Показалось будет неудобно юзать в Вью компоненте. Мне надо при наведении мышки показывать по кругу картинки из массива и останавливать при убирании мышки.

    Не вижу ничего неудобного:

    <div
      @mouseenter="установитьИнтервал"
      @mouseleave="сброситьИнтервал"
    >

    methods: {
      установитьИнтервал() {
        this.interval = setInterval(() => { ... }, 666);
      },
      сброситьИнтервал() {
        clearInterval(this.interval);
      },
    },
    Ответ написан
    2 комментария
  • Как организовать опрос, как на tj?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Структура данных, содержащая вопросы.
    Массив объектов, каждый из которых представляет один вопрос. Внутри два свойства - текст вопроса, и массив с вариантами ответа:

    data: () => ({
      questions: [
        {
          text: '2 x 2?',
          answers: [ '5', '3', '69', '187' ],
        },
        {
          text: '...',
          answers: [ '...', '...', ... ],
        },
        ...
      ],
    }) ,

    Компонент вопроса.
    Принимает три параметра - текст вопроса, массив вариантов ответа, и выбранный ответ:

    props: [ 'text', 'answers', 'value' ],

    Показываем текст вопроса; на основе массива ответов создаём радиокнопки, если ответ совпадает с выбранным, соответствующая кнопка помечается как выбранная; при выборе кнопки отправляем значение родительскому компоненту:

    <div>{{ text }}</div>
    <div v-for="n in answers">
      <label>
        <input
          type="radio"
          :checked="n === value"
          @change="$emit('input', n)"
        >
        {{ n }}
      </label>
    </div>

    Компонент опроса.
    Принимает список вопросов в качестве параметра:

    props: [ 'questions' ],

    Из данных содержит в себе индекс текущего вопроса и массив выбранных ответов:

    data: () => ({
      index: 0,
      answers: [],
    }),

    Если индекс меньше количества вопросов, значит опрос ещё не окончен, показываем вопрос, в противном случае следует отобразить результаты:

    <div v-if="index < questions.length">
      вопрос
    </div>
    <div v-else>
      результаты
    </div>

    Чтобы показать вопрос, отрендерим экземпляр компонента вопроса, передав ему в качестве параметров содержимое элемента массива вопросов + привязав элемент массива ответов:

    <question
      v-bind="questions[index]"
      v-model="answers[index]"
    />

    Чтобы перейти к следующему вопросу, достаточно увеличить индекс текущего вопроса (кнопку, пока пользователь не выбрал ответ, можно: а) блокировать - :disabled="!answers[index]"; б) скрывать - v-show="answers[index]"):

    <button @click="index++">дальше</button>

    Результаты - список вопросов и соответствующих им (с тем же индексом) ответов:

    <div v-for="(n, i) in questions">
      {{ n.text }} - {{ answers[i] }}
    </div>


    https://jsfiddle.net/fdbj1w29/
    Ответ написан
    1 комментарий
  • Почему не обновляется state после успешного получения данных?

    0xD34F
    @0xD34F Куратор тега Vue.js
    return this.$store.authInfo

    А может, всё-таки this.$store.state.authInfo?
    Ответ написан
    4 комментария
  • Как не присваивать класс, если значение переменной null?

    0xD34F
    @0xD34F Куратор тега Vue.js
    :class="form.FirstName !== null ? form.FirstName ? 'input-successes' : 'input-error' : ''"

    или

    :class="{ 'input-successes': form.FirstName, 'input-error': form.FirstName === false }"

    или

    :class="form.FirstName !== null && [ 'input-error', 'input-successes' ][+form.FirstName]"

    или

    :class="({ true: 'input-successes', false: 'input-error' })[form.FirstName]"

    Лучше бы подобное конечно в computed/метод завернуть, как-то громоздко получается.
    Ответ написан
    2 комментария
  • Как вернуть копию значения с объекта в vuex store?

    0xD34F
    @0xD34F Куратор тега Vue.js
    после перезагрузки страницы получаю undefined

    Сохраняйте стейт в localStorage.

    Если лень реализовывать сохранение самостоятельно - есть готовые плагины, например.

    правильно ли я возвращаю копию значения с объекта store.singleMetricNamesMap

    Геттер в хранилище, возвращающий функцию, которая по переданному id возвращает объект... Не вижу, в чём смысл подобных сложностей.

    Просто читайте свойство объекта, типа $store.state.singleMetricNamesMap[value.metricId]. Если так по-вашему слишком длинно - сделайте в компоненте вычисляемое свойство, которое будет представлять singleMetricNamesMap.
    Ответ написан
    2 комментария
  • Как отобразить Яндекс карту в компоненте vue?

    0xD34F
    @0xD34F Куратор тега Яндекс.Карты
    Проблема из-за css. Для всех canvas'ов у вас задано правило width: 100% !important;, а родительский элемент canvas'а карты имеет нулевые размеры.

    UPD.

    new ymaps.Map("map", {

    Вот так делать не надо. Что если экземпляров компонента с картой будет больше одного? - двух, трёх и т.д. карт с одним id быть не может. Замените id на ref, и передавайте в конструктор карты вместо id сам элемент.
    Ответ написан
    3 комментария
  • Как смещать серый квадрат только после прохода курсором ячейки?

    0xD34F
    @0xD34F Куратор тега Vue.js
    data: () => ({
      size: 52,
      col: 0,
      row: 0,
    }),
    methods: {
      onMouseMove(e) {
        this.col = e.offsetX / this.size | 0;
        this.row = e.offsetY / this.size | 0;
      },
    },
    computed: {
      blockStyle() {
        return {
          backgroundSize: `${this.size}px ${this.size}px`,
        };
      },
      blockCursorStyle() {
        const { col, row, size } = this;
        return {
          transform: `translate(${col * size}px, ${row * size}px)`,
          width: `${size * 0.95}px`,
          height: `${size * 0.95}px`,
        };
      },
    },

    <div class="block" :style="blockStyle" @mousemove="onMouseMove">
      <div class="block-cursor" :style="blockCursorStyle"></div>
    </div>

    https://jsfiddle.net/La4297zd/

    Почему вместо координат курсора хранятся индексы столбца и строки - это чтобы при изменении размера не случалось переключения подсветки на другую ячейку.
    Ответ написан
    2 комментария
  • Как изменить ширину столбца?

    0xD34F
    @0xD34F Куратор тега CSS
    Свойство width у элементов headers. Число или строка. Если число - это пиксели. Если строка - доступны все единицы измерения css (значение подставляется в style соответствующего th).

    В документации не нашёл.

    Я бы скорее поверил в "не нашёл документацию". Чего там можно было не найти - без понятия, всё на поверхности лежит (в блоке API: компонент v-data-table, вкладка props - выбраны по умолчанию, достаточно просто скроллить вниз и читать, какой параметр за что отвечает - неужели это так сложно?).
    Ответ написан
    1 комментарий
  • Почему директива не работает?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Сначала определяете директиву, потом создаёте экземпляр Vue. Не наоборот.

    UPD. Первая буква в имени директивы - русская:

    Vue.directive('сarusel', {
    Ответ написан
    2 комментария
  • Как добавить имя нескольким сущностям с store?

    0xD34F
    @0xD34F Куратор тега Vue.js
    return this.singleMetricNamesMap.forEach(el => el[this.value.metricId])

    Круто.

    Откройте документацию, разберитесь, что такое forEach. И какие ещё бывают методы у массивов.

    UPD.

    metric() {
        if (this.metric) {
            this.setSingleMetricNamesMap({ [this.metric.id]: this.metric.name })
        }
    }

    Текущее значение наблюдаемого свойства передаётся в наблюдатель первым параметром, this. не нужен:

    metric(val) {
      if (val) {
        this.setSingleMetricNamesMap({ [val.id]: val.name });
      }
    },
    Ответ написан
    Комментировать