【问题标题】:How to apply Vue directives to Vuetify custom components如何将 Vue 指令应用于 Vuetify 自定义组件
【发布时间】:2021-12-23 19:36:07
【问题描述】:

我有一些像这样的 vuetify 自定义组件(输入组件):

// Component 
<v-text-field 
  background-color="#ffffff"
  outlined 
  dense
  hide-details
  class="text-field"
  :class="textFieldClass"
  v-model="content"
  :disabled="disabled"
  :rules="textFieldRules"
  @keydown="handleKeydown"
  :maxlength="maxLength"
  :error="textFieldError"
></v-text-field>


//Parent
<v-container>
  <v-row class="d-flex justify-center">
    <v-col cols="4">
      <div class="d-flex justify-center">
        <label class="input-label"> Insert data </label>
      </div>
      <InputTextField v-uppercase :textFieldRules="[rules.inputDataFormat]" :textFieldContent.sync="inputData"></InputTextField>
    </v-col>
  </v-row>
</v-container>

我正在尝试在我的组件上使用名为“大写”的 Vue 自定义指令:

import Vue from "vue";

export const InputCase = {
  update: function (el) {
    el.value = el.value.toUpperCase();
  }
};

Vue.directive("uppercase", InputCase);

但是我发现vuetify组件没有value属性,所以不起作用。我该如何解决这个问题?

【问题讨论】:

    标签: javascript vue.js vue-component vuetify.js


    【解决方案1】:

    您将指令应用于自定义组件 InputTextField,而不是直接应用于 Vuetify 的 v-text-field,因此声明 我发现 vuetify 组件没有 value 属性不正确. Yours 组件没有value 属性。 v-text-field does 因为它支持v-model

    但是这里没关系。问题是 Vue 指令的级别非常低。来自文档:

    请注意,在 Vue 2.0 中,代码重用和抽象的主要形式是组件——但是在某些情况下,您可能需要对普通元素进行一些低级 DOM 访问,而这仍然是自定义指令有用的地方。

    所以指令直接在 DOM 级别上操作,而不是在组件级别上。传递给指令钩子的el 不是组件实例,它始终是渲染组件时生成的 DOM 元素。现在是 documented in Vue 3 docs

    所以你的指令(可能来自this SO answer)将不起作用。一个解决方案可以基于另一个答案 - Custom directive v-focus is not working on vuetify component - 但它对 Vuetify 组件的呈现方式做了一些假设。另请查看this forum thread 了解并发症和其他解决方案...

    我个人不会走指令路线并坚持 Vue 作者给出的建议 - 代码重用和抽象的主要形式是组件

    注意:我真的不喜欢你InputTextField自定义输入的界面。 Vue 中的输入处理基于v-model,其他开发人员(在您的团队中)已经习惯了它。为什么要让您的自定义输入(本质上是一个包装器)与众不同?

    您已经有一个自定义组件InputTextField,因此应该很容易添加简单的布尔属性,例如uppercase,并将它与基于计算的v-model 实现一起使用,如下所示:

    Vue.component('custom-input', {
      props: {
        value: {
          type: String,
          required: true
        }, 
        uppercase: {
          type: Boolean,
          default: false
        }
      },
      template: `<input type="text" v-model="model">`,
      computed: {
        model: {
          get() { return this.value },
          set(newVal) {
            this.$emit('input', this.uppercase ? newVal.toUpperCase() : newVal)
          }
        }
      },
      watch: {
        value: {
          // to handle the situation when model value set by parent is not uppercase
          handler: function(newValue) {
            if(this.uppercase && newValue !== newValue.toUpperCase())
              this.model = newValue
          },
          immediate: true
        }
      }
    })
    
    new Vue({
      el: "#app",
      data() {
        return {
          text: "Hello"
        }
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
    <div id="app">
      <custom-input v-model="text" :uppercase="true"></custom-input>
      <pre>{{ text }}</pre>
    </div>

    升级到 Vue 3 时,您可以摆脱 uppercase 的独立 props 并轻松重写组件以使用 custom v-model modifiers

    【讨论】:

      猜你喜欢
      • 2020-01-27
      • 1970-01-01
      • 2018-10-20
      • 2019-12-04
      • 2021-09-08
      • 2019-11-06
      • 2020-05-25
      • 2020-03-21
      • 1970-01-01
      相关资源
      最近更新 更多