如何通过自定义指令修改v-model属性的值?

时间:2018-04-01 13:24:22

标签: events vue.js vuejs2 directive dom-events

当我使用自定义指令更改组件的值时,没有效果:



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>
&#13;
&#13;
&#13;

当我使用v-bind:input指令更改值时,确定无误!

2 个答案:

答案 0 :(得分:7)

首先:

  • 您正在使用v-modeltextarea的值将是v-model变量中的任何内容(在本例中为变量content)。这意味着忽略DOM的初始值
  • 为了解决这个问题,我将DOM声明中的字符串移动(见下文)content中的data()

第二

  • 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>

答案 1 :(得分:0)

只需使用事件功能创建一个输入事件。

  

var event = new Event(“ input”,{bubble: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);
      }
  }
});

希望这会有所帮助。