背景:因为使用LayUI,select,radio,checkbox 都会被托管,无法双向绑定,所以把这三个 利用layui的样式,用vue重写一遍。
-
Component 知识 https://cn.vuejs.org/v2/guide/components.html 必须看完才能往下走
-
要观察layui托管组件后,生成的Html代码,把对应的html代码拷贝下来。
-
html代码
<div class="layui-form-item"> <label class="layui-form-label" style="text-align:left;"> select: </label> <div class="layui-input-inline"> <tl-select :list="list3" v-model="targetValue" ></tl-select> </div> 显示的值:{{targetValue}} </div>
-
js代码
Vue.component("tl-select", { /* !此处数据类型必须是一个函数形式,不能直接写对象。 每个组件都是相互独立的,如果它们共用一个对象,在更改一个组件数据的时候,会影响到其它 组件,如果是函数的话,每个组件就都有自己的独立数据,相互之间不会影响。 */ props: ["list","value","title","width"], data: function() { return { selectShow: false, val: 0, showTitle: this.title || '', showValue: '' }; }, template:`<div :class="[selectShow ? 'layui-unselect layui-form-select layui-form-selected' : 'layui-unselect layui-form-select'] " v-clickOut="outsideDirec" :style="{'width':width ? width:''}"> <div class="layui-select-title" @click="selectShow = !selectShow"> <input type="text" placeholder="" :value="showValue" readonly="" class="layui-input layui-unselect"> <i class="layui-edge"></i> </div> <dl class="layui-anim layui-anim-upbit" style="" v-show="selectShow"> <dd :class="item.value == value ? 'layui-this':''" v-for="item in list" @click.stop="choose(item)">{{item.key}}</dd> </dl> </div>`, methods: { choose(value) { this.val = value; //将选中的值赋给指定的input this.selectShow = false; //隐藏下拉框 this.$emit("input", this.val.value); this.showValue = this.val.key; this.$emit("change"); }, outsideDirec() { this.selectShow = false }, test() { this.selectShow = false }, }, mounted() { let that = this; if(that.value){ this.list.forEach(item=>{ if(item.value == that.value){ that.showValue = item.key; } }) }else{ let tryNum = 0; while(tryNum < 3 && !that.value){ setTimeout(()=>{ this.list.forEach(item=>{ if(item.value == that.value){ that.showValue = item.key; } }) },150); tryNum++; } } }, directives: { clickOut: { bind: function(el, binding) { function handler(e) { if (el.contains(e.target)) return false if (binding.expression) { binding.value() } } el.handler = handler document.addEventListener('click', el.handler) }, unbind: function(el) { document.removeEventListener('click', el.handler) } } } });
-
实现完难的select,我们就参考上面 制作checkBox和radio组件吧
checkBox
Vue.component("tl-checkbox", { props: { label:[String,Number,Boolean], title:[String], value:[Number,String,Array,Boolean], disable:[Boolean] }, data: function() { return { originValue : this.value, disabled:this.disable || false }; }, template:`<div :class="[value.indexOf(label) == -1 ? 'layui-unselect layui-form-checkbox':'layui-unselect layui-form-checkbox layui-form-checked',disabled?'layui-checkbox-disbaled layui-disabled':'']" lay-skin="primary" v-if="value instanceof Array"> <span>{{ title }}</span> <i class="layui-icon layui-icon-ok" @click.stop="changeValueHandle(label)"></i> </div> <div :class="value ? 'layui-unselect layui-form-checkbox layui-form-checked':'layui-unselect layui-form-checkbox'" lay-skin="primary" v-else> <span>{{ title }}</span> <i class="layui-icon layui-icon-ok" @click.stop="changeValueHandle()"></i> </div>`, methods: { changeValueHandle(value) { if(!this.disabled){ if(this.value instanceof Array){ let index = this.value.indexOf(value); let originValue = this.value; if(index == -1){ originValue.push(value); }else{ originValue.splice(index,1); } this.$emit("input", originValue); }else{ console.log(this.value); this.$emit("input", !this.value); } this.$emit("click"); } }, changeDisable(bool){ this.disabled = bool; }, reSetValue(value){ this.originValue = value; }, } });
radio
Vue.component("tl-radio", { props: { label: [String,Number], title: [String,Number], value: [String,Number] }, data: function() { return { originValue : this.value }; }, template:`<div :class="value == label ? 'layui-unselect layui-form-radio layui-form-radioed':'layui-unselect layui-form-radio'"> <i :class="value == label ? 'layui-anim layui-icon layui-anim-scaleSpring':'layui-anim layui-icon'" @click="changeValueHandle(label)">{{value == label ? '':''}}</i> <div>{{title}}</div> </div>`, methods: { changeValueHandle(value) { this.$emit("input", value); } } });
-
对应以上的html代码
radio
<tl-radio label="1" title="小红书1" v-model="targetValue" ></tl-radio> <tl-radio label="2" title="小红书2" v-model="targetValue" ></tl-radio>
checkbox
<tl-checkbox :label="1" title="小红书1" v-model="targetValue" ></tl-checkbox> <tl-checkbox :label="2" title="小红书2" v-model="targetValue" ></tl-checkbox>
-
基本用的都是这三个组件,若有不完善,请指出,共同进步。
-
最后:其他还有不少没实现,比如日期组件
参考文献
https://www.jianshu.com/p/e805baa1574e 主要参考这个
https://www.jb51.net/article/140765.htm
https://www.jianshu.com/p/973cae0263ef 知识补充
https://www.cnblogs.com/024-faith/p/select.html 解决多个select 前一个不关闭问题