【问题标题】:Vuejs Bind value to v-model from prop or computed valueVuejs 将值从 prop 或计算值绑定到 v-model
【发布时间】:2019-05-02 11:33:05
【问题描述】:

我有一个输入,它是一个组件,并在主视图中呈现如下:

<slug v-model="slug"></slug>

然后我有一个组件视图,如下所示:

<template>
  <v-text-field box label="Slug*" v-model="slug" @change="strtoslug"  :rules="requiredRule"></v-text-field>
</template>

我正在运行一个计算方法来获取和设置数据,并且可以console.log 没有问题。在编辑状态下,我无法使用更新的计算状态填充 v-model,因为我无法在渲染时声明为数据源。

这是我的整个代码块:

<template>
  <v-text-field box label="Slug*" v-model="slug" @change="strtoslug"  :rules="requiredRule"></v-text-field>
</template>

<script>
//Set the params
export default {
  name:'slug',
  props: ['value'],
  //Set the data
  data() {
      const self = this;
      return {
          slugstr: '',
          requiredRule: [
              (v) => !!v || 'Field is required',
          ],
        }
    },
    watch: {
    },
    //Get the value onchange computer to return from component
    computed: {
        slug: {
          get() {
              return this.value;
          },
          set(val) {
            //set the slug
            this.slugstr = val;
            this.slug    = val;
            //send data back to parent
            this.$emit('input',val)
             return this.value;
          }
        }
    },
    mounted() {
      const self = this;
      //Set the templates get request
     },
      methods: {
        strtoslug: function(value){
            this.slug = this.sanitizeSlug(value);
        },

        sanitizeSlug: function(title) {
         var slug = "";
         // Change to lower case
         var titleLower = title.toLowerCase();
         // Letter "e"
         slug = titleLower.replace(/e|é|è|ẽ|ẻ|ẹ|ê|ế|ề|ễ|ể|ệ/gi, 'e');
         // Letter "a"
         slug = slug.replace(/a|á|à|ã|ả|ạ|ă|ắ|ằ|ẵ|ẳ|ặ|â|ấ|ầ|ẫ|ẩ|ậ/gi, 'a');
         // Letter "o"
         slug = slug.replace(/o|ó|ò|õ|ỏ|ọ|ô|ố|ồ|ỗ|ổ|ộ|ơ|ớ|ờ|ỡ|ở|ợ/gi, 'o');
         // Letter "u"
         slug = slug.replace(/u|ú|ù|ũ|ủ|ụ|ư|ứ|ừ|ữ|ử|ự/gi, 'u');
         // Letter "d"
         slug = slug.replace(/đ/gi, 'd');
         // Trim the last whitespace
         slug = slug.replace(/\s*$/g, '');
         // Remove Punctuation
         slug = slug.replace(/[.,\/#!$%\^&\*;:{}=\`~()]/g,"");
         // Change whitespace to "-"
         slug = slug.replace(/\s+/g, '-');
     //Return the formatted str
     return slug;
   }
 }

}
</script>

onchange 发生在 console.log 中,但我无法将它作为值呈现在 input 中。我做错了什么?

【问题讨论】:

    标签: vue.js binding vuejs2 components


    【解决方案1】:

    我不太确定我是否完全理解您想要实现的目标,但这里有一些元素可以解决您的问题。

    我猜您希望您的父组件对子组件属性具有反应性,并且子属性由父组件更新。如果我错了,请告诉我。

    此问题可能是由于您在 setter 函数中的 return 值。 下面是一些带有v-model 的代码,用于自定义组件。

    App.vue

    <template>
      <slug v-model="input_data"></slug>
    </template>
    <script>
    import slug from "./components/slug";
    
    export default {
      name: "App",
      data() {
        return {
          input_data: "hello"
        };
      },
      components: {
        slug
      },
      watch: {
        input_data() {
          console.log("Parent: " + this.input_data);
        }
      }
    };
    </script>
    

    slug.vue

    <template>
      <div>
        <input v-model="msg" />
        <p>{{ value }}</p>
      </div>
    </template>
    
    <script>
    export default {
      name: "slug",
      props: ["value"],
      computed: {
        msg: {
          get: function() {
            return this.value;
          },
          set: function(val) {
            this.$emit("input", val);
          }
        }
      }
    };
    </script>
    

    【讨论】:

      【解决方案2】:

      你的计算属性有一个无限循环,因为它的 setter 再次设置自己:

      computed: {
        slug: {
          set(val) {
            this.slug = val; // <-- sets itself again -- infinite loop
            this.$emit('input', val);
          }
        }
      },
      

      该无限循环阻止您的组件将值发送给父级,您应该会看到类似于以下内容的控制台错误:Maximum call stack size exceeded

      但看起来您实际上希望事先使用sanitizeSlug() 对发出的值进行清理。目前,它在每个输入(例如,每个按键)上发出原始输入值,然后发出带有change-事件的净化值,这发生在&lt;v-text-field&gt; 失去焦点之后。 change-event 处理程序是多余的,因为您已经拥有v-model="slug",因此可以将其删除。此外,最好在发出所有输入值之前对其进行清理。

      解决问题:

      1. slug 的设置器中,删除this.slug = val,并在发出input 值之前对其进行清理:

        computed: {
          slug: {
            set(val) {
              // this.slug = val; // <-- delete this
              this.$emit('input', this.sanitizeSlug(val)); // <-- sanitized input value
            }
          }
        },
        
      2. 删除change-event 处理程序绑定:

        <v-text-field box label="Slug*" v-model="slug"
                      <!-- @change="strtoslug" DELETE THIS BINDING -->
                      :rules="requiredRule"></v-text-field>
        
      3. 同时删除事件处理程序的关联方法:

        methods: {
          /* strtoslug: function(value){
              this.slug = this.sanitizeSlug(value);
          },*/ // DELETE THIS METHOD
        }
        

      demo

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-04
        • 2020-07-15
        • 2018-06-13
        • 2018-07-29
        • 2017-10-23
        • 2021-04-25
        相关资源
        最近更新 更多