Заставьте два элемента иметь одинаковую ширину

Я пытаюсь заставить два b-buttons (компонент кнопки из Buefy) оставаться такими же большими, как и более широкий из них.

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

Как я могу это сделать?

Моим первым шагом было установить привязку к стилю 'min-width' для каждой кнопки, например так:

<b-button ref="firstButton" type="is-primary" size="is-large"
      :style="{ 'min-width': $refs.secondButton !== undefined ? $refs.secondButton.$el.clientWidth + 'px' : 0 }">
    First Button
</b-button> 

<b-button ref="secondButton" type="is-primary" size="is-large"
      :style="{ 'min-width': $refs.firstButton !== undefined ? $refs.firstButton.$el.clientWidth + 'px' : 0 }">
    Second Button
</b-button> 

Но это почти не работает, похоже, что это работает один раз при рендеринге страницы, и любое изменение размера (например, из-за локализации) игнорируется. Похоже, в этом $ref нет реактивности.

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

Но на этот раз элементы $ref не определены, похоже, что вычисление происходит до их установки.

Как я могу сделать две кнопки одинаковой ширины, не устанавливая фиксированное значение и имея возможность изменять размер по мере увеличения/уменьшения размера кнопок?

Вот весь код:

(это просто две кнопки, окруженные разделом героя)

<template>
    <div>
        <section class="hero is-primary is-bold is-relative">
            <div class="hero-body">
                <div class="section">
                    <div class="container">
                        <!-- $refs.secondButton !== undefined ? $refs.secondButton.$el.clientWidth + 'px' : 0 -->
                        <!-- $refs.firstButton !== undefined ? $refs.firstButton.$el.clientWidth + 'px' : 0 -->

                        <div class="columns is-centered is-multiline is-mobile">
                            <div class="column is-narrow has-text-centered">
                                <b-button ref="firstButton" type="is-primary" size="is-large"
                                    :style="{ 'min-width': $refs.secondButton !== undefined ? $refs.secondButton.$el.clientWidth + 'px' : 0 }">
                                    First Button
                                </b-button>
                            </div>

                            <div class="column is-narrow has-text-centered">
                                <b-button ref="secondButton" type="is-primary" size="is-large"
                                    :style="{ 'min-width': $refs.firstButton !== undefined ? $refs.firstButton.$el.clientWidth + 'px' : 0 }">
                                    Second Button
                                </b-button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </div>
</template>

<script>
    export default {

    }
</script>

<style lang="scss" scoped>
    //All from Buefy and Bulma.
</style>

person Nicke Manarin    schedule 25.05.2020    source источник
comment
где твой css?   -  person Dejan.S    schedule 25.05.2020
comment
Я думаю, вы можете создать свойство и контролировать его ширину. Поэтому они всегда будут одинаковой ширины   -  person Asimple    schedule 25.05.2020
comment
@Dejan.S Это все от Buefy/Bulma. Я не использую пользовательский CSS. В любом случае, это не так важно, так как все, что он делает, это централизует две кнопки и добавляет немного поля.   -  person Nicke Manarin    schedule 25.05.2020
comment
@AsiPle Не уверен. Моя проблема заключается в том, чтобы получить ширину кнопок, поскольку они меняются в размере из-за локализации.   -  person Nicke Manarin    schedule 25.05.2020
comment
Вы можете изменить свойство из-за локализации, и кнопки будут изменены на. Может быть, вы пытаетесь сказать, что у них есть ширина из-за содержимого внутри, и вам нужно установить ширину самой длинной кнопки на другую?   -  person Asimple    schedule 25.05.2020
comment
@AsiPle Да, если содержимое кнопки изменится, ширина кнопки тоже изменится. Мне нужно синхронизировать ширину обеих кнопок. Установка наибольшей ширины на ширину наименьшей, делая оба одинаковых размера.   -  person Nicke Manarin    schedule 25.05.2020
comment
@NickeManarin Как насчет пересчета ширины по мере срабатывания изменения локализации?   -  person Yom T.    schedule 25.05.2020
comment
@ЙомС. Я использую vue-i18n. Я собираюсь проверить, есть ли какой-нибудь триггер, который я могу использовать. Но было бы проще, если бы я мог напрямую смотреть ширину кнопки.   -  person Nicke Manarin    schedule 25.05.2020
comment
@NickeManarin Когда вы сказали синхронизировать их, вы имеете в виду, что эти две кнопки будут иметь одинаковое содержимое?   -  person Yom T.    schedule 25.05.2020
comment
@ЙомС. Нет, только ширина.   -  person Nicke Manarin    schedule 26.05.2020
comment
На самом деле не имеет значения, используете ли вы вставку css framework. Я могу дать вам собственный CSS, но я не собираюсь тратить время на то, чтобы дать вам решение с нуля, если вы не можете приложить усилия, чтобы создать для нас рабочее решение. Если я также дам вам решение, я не знаю, стало ли оно мешать другим CSS, которые у вас есть. Итак, опять же, вам лучше сделать рабочий пример.   -  person Dejan.S    schedule 26.05.2020
comment
@Dejan.S Не нужно. Я уже понял это. Я включил рабочий пример в свой ответ, включая CSS (но это был CSS, который уже был в песочнице).   -  person Nicke Manarin    schedule 26.05.2020


Ответы (2)


Вы не можете установить стиль ref таким образом, потому что в жизненном цикле Vue ссылка доступна только после монтирования.

Вы можете добавить код JS, чтобы изменить ширину кнопки в установленном хуке.

                    <div class="columns is-centered is-multiline is-mobile">
                        <div class="column is-narrow has-text-centered">
                            <b-button ref="firstButton" type="is-primary" size="is-large">
                                First Button
                            </b-button>
                        </div>

                        <div class="column is-narrow has-text-centered">
                            <b-button ref="secondButton" type="is-primary" size="is-large">
                                Second Button
                            </b-button>
                        </div>
                    </div>


  mounted() {
    let firstWidth = this.$refs.firstButton.clientWidth;
    let secondWidth = this.$refs.secondButton.clientWidth;
    if (firstWidth > secondWidth) {
      this.$refs.secondButton.style.width = firstWidth + "px";
    } else {
      this.$refs.firstButton.style.width = secondWidth + "px";
    }
  }

Кроме того, я не уверен в этом, но вам может потребоваться добавить display: inline-block к кнопке b, если текущий тип отображения css кнопки b игнорирует настройку размера

b-button {
  display: inline-block;
}
person Jake Lam    schedule 26.05.2020
comment
Вам нужно установить стиль, обратившись к свойству $el внутри button следующим образом: this.$refs.secondButton.$el.style. Также этот код не обновляет размер при изменении текста внутри кнопок. Тоже х2, Для работы нужно вместо этого поставить значение minWidth. - person Nicke Manarin; 26.05.2020

Мне удалось решить проблему, создав два метода с двумя вложенными вызовами $nextTick() внутри. После этого вы просто устанавливаете методы для стиля каждой кнопки.

 <div class="column is-narrow has-text-centered">
     <b-button ref="firstButton" type="is-light" size="is-large"
              :style="{ 'min-width':  getMinWidthFirst() }">
         {{ firstText }}
     </b-button>
 </div>

<div class="column is-narrow has-text-centered">
    <b-button ref="secondButton" type="is-light" size="is-large"
              :style="{ 'min-width': getMinWidthSecond() }">
        {{ secondText }}
    </b-button>
</div>

Вот методы, они вызываются автоматически при изменении текста:

getMinWidthFirst() {
  var size = this.$refs.secondButton !== undefined
      ? this.$refs.secondButton.$el.clientWidth + 2 + "px"
      : 0;

  this.$nextTick().then(() => {
    this.$refs.firstButton.$el.style.minWidth = 0 + "px";

    this.$nextTick().then(() => {
      this.$refs.firstButton.$el.style.minWidth =
        this.$refs.secondButton.$el.clientWidth + 2 + "px";
    });
  });

  return size;
},
getMinWidthSecond() {
  var size = this.$refs.firstButton !== undefined
      ? this.$refs.firstButton.$el.clientWidth + 2 + "px"
      : 0;

  this.$nextTick().then(() => {
    this.$refs.secondButton.$el.style.minWidth = 0 + "px";

    this.$nextTick().then(() => {
      this.$refs.secondButton.$el.style.minWidth =
        this.$refs.firstButton.$el.clientWidth + 2 + "px";
      });
  });

  return size;
}

Идея использования двух вложенных вызовов $nextTick заключается в том, что при одном вызове кнопка не уменьшалась бы по ширине, текст был маленьким.

Рабочее решение:

https://codesandbox.io/s/vue-template-r4fp1?file=/src/components/HelloWorld.vue:1679-2622

Gif размером 97,1 КБ, демонстрирующий решение (Gif размером 97 КБ, демонстрирующий решение)

person Nicke Manarin    schedule 26.05.2020