Vuejs中的Select2 onchange事件无法工作

13

我在使用vuejs中的select2时发现,vuejs不能与jquery select2一起使用,因为vuejs只能与原生HTML一起使用。

我正在使用以下代码:

Vue.directive('select', {
        twoWay: true,
        bind: function () {
            $(this.el).select2()
            .on("select2:select", function(e) {
                this.set($(this.el).val());
            }.bind(this));
            },
        update: function(nv, ov) {
            $(this.el).trigger("change");
        }
    });
    var app = new Vue({
      el: '#app',
      data: {
        supplier_id: "niklesh"
      }
    })
    $('#supplier_id').select2({});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.css">
<div id="app">
  {{ supplier_id }}

<select id="supplier_id" class='form-control' v-model='supplier_id' v-select='supplier_id'>
    <option value="atul">Atul</option>
    <option value="niklesh">Niklesh</option>
    <option value="sachin">Sachin</option>
</select>

</div>

请分享您的回复以处理此问题。
4个回答

20

要将其与指令一起使用,我们需要了解 v-model 的工作原理。参考文档

<input v-model="something">

is just syntactic sugar for:

<input v-bind:value="something" v-on:input="something = $event.target.value">

在选择元素的情况下,v-model 将监听 change 事件(而不是 input 事件)。所以,如果指令在元素变化时派发了一个 change 事件,那么 v-model 就会按照预期工作。

这是您代码的更新版本(适用于 Vue 2):

Vue.directive('select', {
  twoWay: true,
  bind: function (el, binding, vnode) {
    $(el).select2().on("select2:select", (e) => {
      // v-model looks for
      //  - an event named "change"
      //  - a value with property path "$event.target.value"
      el.dispatchEvent(new Event('change', { target: e.target }));
    });
  },
  componentUpdated: function(el, me) {
    // update the selection if the value is changed externally
    $(el).trigger("change");
  }
});
var app = new Vue({
  el: '#app',
  data: {
    supplier_id: "niklesh"
  },
})
$('#supplier_id').select2({});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.css">
<div id="app">
  {{ supplier_id }}

  <select id="supplier_id" class='form-control' v-model='supplier_id' v-select='supplier_id'>
    <option value="atul">Atul</option>
    <option value="niklesh">Niklesh</option>
    <option value="sachin">Sachin</option>
  </select>

</div>

这里有一个适用于 Vue 3 的版本(自定义指令具有不同的语法,在此链接中提供):

var app = Vue.createApp({
  data: function() { 
    return {
      supplier_id: "niklesh"
    }
  }
})

app.directive('select', {
  beforeMount: function (el, binding, vnode) {
    $(el).select2().on("select2:select", (e) => {
      // v-model looks for
      //  - an event named "change"
      //  - a value with property path "$event.target.value"
      el.dispatchEvent(new Event('change', { target: e.target }));
    });
  },
    updated: function(el) {
    // update the selection if the value is changed externally
    $(el).trigger("change");
  }
});

app.mount('#app');

$('#supplier_id').select2({});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://unpkg.com/vue@3.0.11"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.css">
<div id="app">
  {{ supplier_id }}

  <select id="supplier_id" class='form-control' v-model='supplier_id' v-select='supplier_id'>
    <option value="atul">Atul</option>
    <option value="niklesh">Niklesh</option>
    <option value="sachin">Sachin</option>
  </select>

</div>


感谢您的解决方案!我正在使用多选功能,因此还必须在 select2:unselect 上触发更改事件,就像这样:$(el).select2().on("select2:select select2:unselect", (e) => { - Patrizio Bekerle
这似乎不适用于Vue3。有什么想法为什么? - e4rthdog
1
@e4rthdog 指令在Vue 3中的工作方式有所不同。我添加了一个Vue 3的代码片段。 - asemahle

10

将select2的值分配给VueJS数据,我能够解决这个问题。这里我没有使用自定义指令。

var app = new Vue({
  el: '#app',
  data: {
    supplier_id: "niklesh"
  },
  filters: {
    capitalize: function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
  }
});

$('#supplier_id').on("change",function(){
    app.supplier_id = $(this).val();
    console.log('Name : '+$(this).val());
});

$('#supplier_id').select2({});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.css">
<div id="app">
  Name : {{ supplier_id | capitalize }}
<select id="supplier_id" class='form-control' v-model='supplier_id'>
    <option value="atul">Atul</option>
    <option value="niklesh">Niklesh</option>
    <option value="sachin">Sachin</option>
</select>

</div>

如果这不是好方法,或者您有更好的解决方案,请评论。


1分钟前提问并得到回答? - darryn.ten
@darryn.ten:这是我的答案,虽然它可以通过jQuery工作,但如果我能通过Vue.js解决这个问题就更好了。 - Niklesh Raut
@Rishi:我不认为这是一个糟糕的解决方案,但你最初使用指令的想法似乎更具可重用性。我添加了一个解决方案,展示了如何改用指令。 - asemahle

2
<select v-model="selected">
       <option value="1">1</option>
       <option value="2">2</option>
       <option value="3">3</option>
</select>


const self = this;
$("select").change(function () {
        const val = $(this).find("option:selected").val();
        self.selected = val;
 });

7
这个答案可以通过提供解释来改善,解释为什么它有效,并且为什么它比被接受的答案更好。 - KevinO
最简单和最简单的解决方案。 - Moauya Meghari

0
尝试在您的选择控件中添加v-on:change="onChange"HTML模板
<select id="supplier_id" class='form-control' 
v-model='supplier_id' v-select='supplier_id' v-on:change="onChange">
    <option value="atul">Atul</option>
    <option value="niklesh">Niklesh</option>
    <option value="sachin">Sachin</option>
</select>

"

\"onChange\"是你的方法名称

JavaScript

"
methods: {
  onChange(e) {        
      alert("Change");   
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接