如何通过自定义指令修改 v-model 属性 的值?
How to modify the value of v-model property via custom directive?
当我使用自定义指令更改组件的值时,没有效果:
Vue.directive('maxchars', {
bind(el, binding, vnode) {
let maxChars = binding.value;
let handler = function(e) {
if (e.target.value.length > maxChars) {
e.target.value = e.target.value.substr(0, maxChars)
}
}
el.addEventListener('input', handler);
}
});
let app = new Vue({
el: '#app',
data() {
return {
content: '',
totalCount: 140
}
}
})
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<div id='app'>
<div>
<div class='content'>
<textarea v-model='content' v-maxchars='140'>tell me something</textarea>
</div>
</div>
</div>
当我使用 v-bind:input
指令更改值时就可以了!
第一个:
- 您正在使用
v-model
,textarea
的值将是 v-model
变量中的任何值(在本例中,变量 content
) .这意味着 DOM 的 初始值被忽略 .
- 为了处理这个问题,我将字符串从 DOM 声明移动(见下文)到
data()
中的 content
。
第二个:
- Vue 不直接响应
.value
中的变化。 v-model
实际上会监视来自 DOM 元素的 input
✱ 事件。
- ✱其实根据元素的类型不同,有时是
change
事件,或者其他
- 如果你只是设置
value
,Vue 会在下次更新时简单地将它覆盖回去(到 content
中的任何内容)。
解决方案:
更改.value
后,触发input
事件。Vue会选择事件并从当前更新v-model
变量.value
在覆盖它之前。
演示:
Vue.directive('maxchars', {
bind(el, binding, vnode) {
let maxChars = binding.value;
let handler = function(e) {
if (e.target.value.length > maxChars) {
e.target.value = e.target.value.substr(0, maxChars);
vnode.elm.dispatchEvent(new CustomEvent('input')); // added this
}
}
el.addEventListener('input', handler);
}
});
let app = new Vue({
el: '#app',
data() {
return {
content: 'tell me something',
totalCount: 140
}
}
})
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<div id='app'>
<div>
<div class='content'>
<textarea v-model='content' v-maxchars='18'></textarea>
</div>
<pre>
content: {{ content }}
Max chars is 18, current is {{ content.length }}.
</pre>
</div>
</div>
只需使用 Event 函数创建一个 input 事件。
var event = new Event("input", { bubbles: true });
然后修改值然后派发事件,它会更新v-model值
el.dispatchEvent(event);
Vue.directive('maxchars', {
update(el, binding, vnode) {
var event = new Event("input", { bubbles: true });
let maxChars = binding.value;
if (el.value.length > maxChars) {
el.value = e.value.substr(0, maxChars);
el.dispatchEvent(event);
}
}
});
希望对您有所帮助。
当我使用自定义指令更改组件的值时,没有效果:
Vue.directive('maxchars', {
bind(el, binding, vnode) {
let maxChars = binding.value;
let handler = function(e) {
if (e.target.value.length > maxChars) {
e.target.value = e.target.value.substr(0, maxChars)
}
}
el.addEventListener('input', handler);
}
});
let app = new Vue({
el: '#app',
data() {
return {
content: '',
totalCount: 140
}
}
})
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<div id='app'>
<div>
<div class='content'>
<textarea v-model='content' v-maxchars='140'>tell me something</textarea>
</div>
</div>
</div>
当我使用 v-bind:input
指令更改值时就可以了!
第一个:
- 您正在使用
v-model
,textarea
的值将是v-model
变量中的任何值(在本例中,变量content
) .这意味着 DOM 的 初始值被忽略 . - 为了处理这个问题,我将字符串从 DOM 声明移动(见下文)到
data()
中的content
。
第二个:
- Vue 不直接响应
.value
中的变化。v-model
实际上会监视来自 DOM 元素的input
✱ 事件。- ✱其实根据元素的类型不同,有时是
change
事件,或者其他
- ✱其实根据元素的类型不同,有时是
- 如果你只是设置
value
,Vue 会在下次更新时简单地将它覆盖回去(到content
中的任何内容)。
解决方案:
更改.value
后,触发input
事件。Vue会选择事件并从当前更新v-model
变量.value
在覆盖它之前。
演示:
Vue.directive('maxchars', {
bind(el, binding, vnode) {
let maxChars = binding.value;
let handler = function(e) {
if (e.target.value.length > maxChars) {
e.target.value = e.target.value.substr(0, maxChars);
vnode.elm.dispatchEvent(new CustomEvent('input')); // added this
}
}
el.addEventListener('input', handler);
}
});
let app = new Vue({
el: '#app',
data() {
return {
content: 'tell me something',
totalCount: 140
}
}
})
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<div id='app'>
<div>
<div class='content'>
<textarea v-model='content' v-maxchars='18'></textarea>
</div>
<pre>
content: {{ content }}
Max chars is 18, current is {{ content.length }}.
</pre>
</div>
</div>
只需使用 Event 函数创建一个 input 事件。
var event = new Event("input", { bubbles: true });
然后修改值然后派发事件,它会更新v-model值
el.dispatchEvent(event);
Vue.directive('maxchars', {
update(el, binding, vnode) {
var event = new Event("input", { bubbles: true });
let maxChars = binding.value;
if (el.value.length > maxChars) {
el.value = e.value.substr(0, maxChars);
el.dispatchEvent(event);
}
}
});
希望对您有所帮助。