工作中發現默認vue綁定checkbox很不方便,存在下面幾個問題。
1、如果傳遞的數值不是數組,那默認綁定值就會轉為true或false但是作為后端人員,true或flase這類值一般都是用數值型字段來保存,比如1和0,我們后台傳遞出來的數據往往就直接是0或1.
2、如果有多個checkbox,那就需要傳遞的數值是數組,但是實際中往往一組checkbox提交后台后,就是保存在一個nvarchar字段中,如果需要和前台配合,在讀取的時候就需要把字符串轉為數組才能實現雙向綁定。
基於以上原因,封裝了一個checkbox組件,代碼如下,希望對大家有幫助。
//ui-checkbox組件 Vue.component("ui-checkbox", { props: { value: { default: "" }, dataSource: { default: [] } }, inheritAttrs: false, methods: { //獲取父級的v-model getModel: function () { if (Array.isArray(this.value)) { vModel = this.value; } else { vModel = this.value.toString().split(","); } return vModel }, //清除冗余數值 filterModel: function (vModel) { var dataSource = this.dataSource; var canSetValue = []; var dataSourceValue = []; for (var i = 0; i < dataSource.length; i++) { dataSourceValue.push(dataSource[i].value.toString()); //需要轉為字符串,兼容數字類型值 } vModel.forEach(function (item, index) { var index = dataSourceValue.indexOf(item); if (index > -1) { canSetValue.push(item); } }); return canSetValue; }, onChange: function (event) { var vModel = this.getModel(); //每次觸發都先獲取父級的v-model,保證多個選項的數據同步,v-model初始值中可能存在冗余數據,后面需要用filterModel過濾掉冗余數據。 if (this.dataSource.length <= 1) { vModel.splice(0, vModel.length); } var $obj = event.target; var index = vModel.indexOf($obj.value); if ($obj.checked){ if (index < 0) { vModel.push($obj.value); } } else { if (index >= 0) { vModel.splice(index, 1); //數組中移除 } } vModel = this.filterModel(vModel);//清除冗余數值 if (!Array.isArray(this.value)) { vModel = vModel.join(",");//如果v-model是字符串,同步時候也轉為字符串。 } console.log(vModel) this.$emit("change",vModel);//同步父級的v-model }, isChecked: function (val) { var vModel = this.getModel(); //務必toString()后再查找,否則會和數值型不兼容。 if (vModel.indexOf(val.toString()) > -1) { return true; } else { return false; } } }, template: `<span :data-value="value"> <label class="checkbox-inline" v-for="item in dataSource" :key=item.value> <input type="checkbox" :checked="isChecked(item.value)" v-on:change="onChange($event)" :value="item.value" v-bind="$attrs" /> {{item.label}}</label> </span>` });
上面代碼大家可以下載自己調試,重要地方都加了注釋。
父級頁面調用時候v-model直接傳遞字符串即可,如下:
var formData = {Love:"寫代碼"}; var vue = new Vue({ el: "#myForm", data: formData, });
單選的調用方法
<ui-checkbox v-model="Love" v-on:change="Love=$event" :data-source="[{value:1,label:'是否有愛好'}]"></ui-checkbox>
這樣就可以保證選種后Love的值為1,如果不選,值就為空,提交到后台很容易處理。
效果如下:

選中后v-mode的值同步改為1,不再是vue默認的true或false。
如果有多個選項,可以這樣調用:
<ui-checkbox v-model="Love" v-on:change="Love=$event" :data-source="[{value:'read',label:'讀書'},{value:'write',label:'寫字'}]"></ui-checkbox>
在父級調用的時候,v-model可以傳遞逗號隔開的字符串,也可以直接傳遞數組,更具有實用性,單選時候效果如下:

兩個都選中的時候,效果如下:

調用時候我們初始默認值為:{Love:"寫代碼"};
很明顯這是一個冗余值,組件中通過 filterModel方法過濾掉了。
如果你想按vue默認的方式來工作,那么初始默認值可以改為數組形式:
var formData = {Love:[]};
這樣點擊觸發后傳遞出來的就是數組,效果如下:

以上是本人今天工作項目中封裝的一個小組件,希望大家喜歡,歡迎轉發。