How to modify the value of v-model property via custom directive?

前端 未结 2 1037
我寻月下人不归
我寻月下人不归 2021-01-01 02:22

When I use custom directive to change component\'s value, there is not effect:

相关标签:
2条回答
  • 2021-01-01 03:06

    Just create a input event using Event function.

    var event = new Event("input", { bubbles: true });

    then modify the value and then dispatch the event, it will update the v-model value

    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);
          }
      }
    });
    

    hope it will helpful.

    0 讨论(0)
  • 2021-01-01 03:10

    First:

    • You are using v-model, the value of the textarea will be whatever is in the v-model's variable (in this case, the variable content). This means that the initial value of the DOM is ignored.
    • To handle this, I moved (see below) the string from the DOM declaration to the content in data().

    Second:

    • Vue does not respond to changes in .value directly. v-model actually watches for input✱ events from the DOM element.
      • ✱ it actually varies depending on the type of element, sometimes it is the change event, or other
    • If you just set the value, Vue will simple override it back (to whatever is in content) next time an update happens.

    Solution:

    After changing the .value, trigger input event. Vue will pick the event up and update the v-model variable from the current .value before it overrides it.

    Demo:

    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>

    0 讨论(0)
提交回复
热议问题