我需要一个星期的时间来解决问题,这通常是一件很容易的事,但我只是在挣扎。
我有一个输入,它是一个组件,并在主视图中呈现为:
<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中,但我只是无法让它作为值呈现在输入中,请问,我在做什么错了。
致谢
保罗
答案 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"
事件处理程序是多余的,因此可以将其删除。另外,最好在发出所有输入值之前先对其进行消毒。
要解决此问题:
在slug
的设置器中,删除this.slug = val
并清理input
值,然后发出:
computed: {
slug: {
set(val) {
// this.slug = val; // <-- delete this
this.$emit('input', this.sanitizeSlug(val)); // <-- sanitized input value
}
}
},
删除change
-事件处理程序绑定:
<v-text-field box label="Slug*" v-model="slug"
<!-- @change="strtoslug" DELETE THIS BINDING -->
:rules="requiredRule"></v-text-field>
还删除事件处理程序的关联方法:
methods: {
/* strtoslug: function(value){
this.slug = this.sanitizeSlug(value);
},*/ // DELETE THIS METHOD
}