Vuejs将值从prop或计算值绑定到v模型

时间:2018-11-30 10:11:08

标签: vue.js binding vuejs2 components

我需要一个星期的时间来解决问题,这通常是一件很容易的事,但我只是在挣扎。

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

<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模型。

这是我的整个代码块。

    

<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中,但我只是无法让它作为值呈现在输入中,请问,我在做什么错了。

致谢

保罗

2 个答案:

答案 0 :(得分:0)

我不太确定我是否了解您要达到的目标,但是这里有一些解决问题的方法。

我想您希望您的父组件对子组件属性具有反应性,并且希望子属性由父组件更新。告诉我我是否错了。

此问题可能是由于您在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>

答案 1 :(得分:0)

您的计算属性具有无限循环,因为其设置器再次设置了自身:

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

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

但是,看起来您实际上实际上是想预先用sanitizeSlug()来净化所发出的值。当前,它在每个输入(例如,每个按键)上发出原始输入值,然后通过change-事件发出经过净化的值,该事件在<v-text-field>失去焦点之后发生。假设您已经拥有change,则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-事件处理程序绑定:

    <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