【问题标题】:Vuetify v-select component width changingVuetify v-select 组件宽度变化
【发布时间】:2021-09-05 12:21:00
【问题描述】:

我的v-select 组件应该有一个固定的宽度(60px),它们适合一个表格单元格,我想防止它们在选择值后改变宽度。

他们改变宽度,下拉箭头在选择后向右移动,所以如果有办法减小图标的大小或其填充/边距,它可能会有所帮助。

不知道如何获取这个箭头的 props 以及它是如何调用的。

这是可重现的

https://codesandbox.io/s/competent-dew-eixq2?file=/src/components/Playground.vue

编辑:添加 sn-p

<!DOCTYPE html>
<html>

<head>
  <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/vuetify@2.0.1/dist/vuetify.min.css" rel="stylesheet">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
  <style>
    .select {
      max-width: 60px;
      max-height: 60px;
      font-size: 11px;
    }
    
    .col {
      max-width: 60px;
      max-height: 60px;
    }
  </style>
</head>

<body>
  <div id="app">
    <v-app>
      <v-row>
        <div class="col" v-for="col in cols" :key="col">
          <v-select class="select" :items="variants" item-value="name" item-text="name" label="" dense outlined hide-details single-line v-model="selected">
          </v-select>
        </div>
      </v-row>
    </v-app>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vuetify@2.0.1/dist/vuetify.js"></script>
  <script>
    new Vue({
      el: '#app',
      vuetify: new Vuetify(),
      data: {
        selected: "",
        cols: [1, 2, 3, 4, 5],
        variants: [{
            id: 0,
            name: ""
          },
          {
            id: 1,
            name: "1:0"
          },
          {
            id: 2,
            name: "0:1"
          },
          {
            id: 3,
            name: "1:0 B"
          },
          {
            id: 4,
            name: "0:1 B"
          },
          {
            id: 6,
            name: "1:0 R"
          },
          {
            id: 7,
            name: "0:1 R"
          },
          {
            id: 8,
            name: "1:0 F"
          },
          {
            id: 9,
            name: "0:1 F"
          },
        ],
      },
    })
  </script>
</body>

</html>

【问题讨论】:

    标签: css vue.js vuetify.js v-select


    【解决方案1】:

    1.如果你不关心附加的图标,你可以使用append-icon prop将其移除(传递空值):

    <v-select
        class="select"
        ...
        append-icon=""
    ></v-select>
    

    2.您可以使用自己的内容覆盖图标的插槽:

    <v-select
        class="select"
        ...
    >
       <template #append>
          <div class="my-custom-icon">...</div>
       </template>
    </v-select>
    

    然后将样式添加到您的 my-custom-icon 类中,使其出现在一个位置:

    .my-custom-icon {
        position: absolute;
        left: ...;
        right: ...;
    }
    

    3.利用overflow: hidden属性:

    <style> // don't add "scoped" attribute, otherwise the style won't be applied
    .select .v-input__control {
      overflow: hidden;
    }
    </style>
    

    【讨论】:

      【解决方案2】:

      基本问题是 v-select 的某些样式(特别是填充和边距)在小宽度下效果不佳。

      这是渲染后的v-select的innerHTML,需要减少的样式

      <div class="select...">                                      
        <div class="v-input__control">
          <div role="button" class="v-input__slot">                <!-- padding-right: 12px; -->
            <div class="v-select__slot">
              <div class="v-select__selections">                               
                <div class="v-select__selection--comma">           <!-- margin-right: 4px; -->
                  1:0 B
                </div>
              </div>
              <div class="v-input__append-inner">                  <!-- padding-left: 4px; -->
                <div class="v-input__icon v-input__icon--append">  <!-- width: 24px; min-width: 24px;-->
                  <i aria-hidden="true" class="v-icon..."></i>                 
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      

      除了那些 innerHTML 更改之外,您还需要每列 60 像素的固定宽度,因此请更改

      <style>
        .select {
          max-width: 60px;
          ...
        }
      

      <style>
        .select {
          width: 60px;
          ...
        }
      

      调整 Vuetify 内部样式

      查看围绕样式的 Vuetify 问题,有人建议使用无范围的样式块或深度范围的样式块,但对我来说都没有用。 Vuetify 表示他们正在努力改进样式的应用方式以克服这些问题。

      幸运的是 Vue 本身有工具可以在 javascript 中执行此操作。

      这些是关键步骤

      • 添加对 v-select 的引用,以便在 javascript 中访问它
      • 向 v-select 添加更改处理程序,以便在用户选择某些内容时重新设置元素的样式
      • 在对象中定义样式调整,以便您轻松调整它们
      • 添加应用样式的方法
      • 调用mounted() 中的方法和v-select @change 处理程序
      • 使用 Vue.nextTick() 允许 Vuetify 先设置样式,然后应用我们的自定义样式

      这是调整后的代码 sn-p。我放入了一些非常小的填充和边距,并最大化了所选值的空间(以避免文本换行)。您可能想使用这些样式,因为我不确定我是否理解所有要求。

      <!DOCTYPE html>
      <html>
      
      <head>
        <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
        <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
        <link href="https://cdn.jsdelivr.net/npm/vuetify@2.0.1/dist/vuetify.min.css" rel="stylesheet">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
        <style>
          .select {
            width: 60px;
            max-height: 60px;
            font-size: 11px;
          }
          
          .col {
            max-width: 60px;
            max-height: 60px;
          }
        </style>
      </head>
      
      <body>
        <div id="app">
          <v-app>
            <v-row>
              <div class="col" v-for="col in cols" :key="col">
                <v-select ref="select" @change="applyCustomStyles"
       class="select" :items="variants" item-value="name" item-text="name" label="" dense outlined hide-details single-line v-model="selected">
                </v-select>
              </div>
            </v-row>
          </v-app>
        </div>
      
        <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/vuetify@2.0.1/dist/vuetify.js"></script>
        <script>
          const customStyles = {
            ".v-input__slot": {
              padding: "0 0 0 4px",
            },
            ".v-select__selections": {
              width: "27px",
            },
            ".v-select__selection--comma": {
              margin: "7px 0 7px 0",
            },
            ".v-input__append-inner": {
              "padding-left": "0",
            },
            ".v-input__icon": {
              width: "14px",
              "min-width": "14px",
            },
          };
      
          new Vue({
            el: '#app',
            vuetify: new Vuetify(),
            mounted() {
              this.applyCustomStyles();
            },
            methods: {
              applyCustomStyles() {
                Vue.nextTick(() => {
                  this.$refs.select.forEach((vSelect) => {
                    Object.entries(customStyles).forEach(([selector, styles]) => {
                      Object.entries(styles).forEach(([style, value]) => {
                        vSelect.$el.querySelector(selector).style[style] = value;
                      });
                    });
                  });
                });
              },
            },
            data: {
              selected: "",
              cols: [1, 2, 3, 4, 5],
              variants: [{
                  id: 0,
                  name: ""
                },
                {
                  id: 1,
                  name: "1:0"
                },
                {
                  id: 2,
                  name: "0:1"
                },
                {
                  id: 3,
                  name: "1:0 B"
                },
                {
                  id: 4,
                  name: "0:1 B"
                },
                {
                  id: 6,
                  name: "1:0 R"
                },
                {
                  id: 7,
                  name: "0:1 R"
                },
                {
                  id: 8,
                  name: "1:0 F"
                },
                {
                  id: 9,
                  name: "0:1 F"
                },
              ],
            },
          })
        </script>
      </body>
      
      </html>

      为什么不用&lt;style&gt; 块?

      建议使用无范围的样式块来覆盖 Vuetify 样式。

      例如,

      <style>
        .select .v-input__slot {
         padding-right: 4px
        }
        ...
      </style>
      

      问题是 Vuetify 样式是在组件上声明的样式之后应用的。

      您可以通过应用比 Vuetify 使用的更高的特异性来做到这一点,例如

      <style>
        .select.v-text-field.v-text-field--enclosed:not(.v-text-field--rounded)>.v-input__control>.v-input__slot {
        padding-right: 4px
      }
      </style>
      

      给你这个

      这样您就可以找出所有需要更改的现有位置并复制 Vuetify 选择器。

      使用新版本的 Vuetify 或更改组件的形状时可能会出现问题。对我来说,javascript 解决方案看起来更易于管理。

      【讨论】:

      • 这里应该不需要以编程方式应用 CSS。 stylesheet/&lt;style&gt; 块会更好地工作(即,如果组件需要重新渲染,避免被覆盖)并且更简单。
      • 内联样式具有最高优先级,因此方法非常好。是否可以从样式块中读取覆盖样式?
      猜你喜欢
      • 2021-06-12
      • 2019-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-24
      • 2020-02-10
      • 2021-12-27
      • 2018-11-25
      相关资源
      最近更新 更多