核心
可以查阅这篇文章,看一些v-model的具体实现;
简介来讲,就是自定义属性和自定义方法的结合使用。
Vue2.0、Vue3.0分别使用v-model封装组件
首先新建脚手架引入element-ui组件和样式;
新建vCheckBox.vue组件:
<template >
<div>
<div class="inputBox" v-if="title">
<p class="inputBoxP">{
{
title}}:</p>
<el-checkbox-group class="radiogroup" v-model="checkList" @change="inputFun">
<el-checkbox v-for="item in options" :key="item.key" :label="item.key">{
{
item.value}}</el-checkbox>
</el-checkbox-group>
</div>
<el-checkbox-group v-else class="radiogroup" v-model="checkList" @change="inputFun">
<el-checkbox v-for="item in options" :key="item.key" :label="item.key">{
{
item.value}}</el-checkbox>
</el-checkbox-group>
</div>
</template>
<script>
export default {
model: {
prop: "value",
event: "inputFun"
},
data() {
return {
checkList: []
};
},
props: {
value: {
type: Array,
require: false,
default: () => []
},
title: {
type: String,
require: false
// default: "请传入Titlt"
},
placeholder: {
type: String,
require: false,
default: "请选择"
},
options: {
type: Array,
require: true,
default: []
}
},
watch: {
value: {
handler(newVal, oldVal) {
if (newVal) {
this.checkList = newVal;
}
},
immediate: true
}
},
methods: {
inputFun(e) {
//不改变地址 可能导致form校验的时候拿不到最新的值
this.$emit("inputFun", [...this.checkList]);
}
}
};
</script>
<style lang="less" scoped>
.inputBox {
margin-bottom: 10px;
display: flex;
justify-content: flex-start;
align-items: center;
width: var(--boxWidth);
.inputBoxP {
text-align: right;
white-space: nowrap;
width: 150px;
}
.inputBoxIpt {
width: 200px;
}
.radiogroup {
width: 200px;
height: 32px;
line-height: 32px;
display: flex;
align-items: center;
}
}
</style>
</script>
<style lang="less" scoped>
.inputBox {
margin-bottom: 10px;
display: flex;
justify-content: flex-start;
align-items: center;
width: var(--boxWidth);
.inputBoxP {
text-align: right;
white-space: nowrap;
width: 150px;
}
.inputBoxIpt {
width: 200px;
}
}
</style>
我这里根据有没有传递title属性,做了渲染判断。原因在于这个组件要分别使用在form表单中和单独使用。
单个使用
针对有title的情况
使用肯定需要按部就班:引入_注册_页面使用。
import vCheckBox from "@/components/elementCom/CheckBox";
components: {
vCheckBox,
}
页面使用:
<v-check-box
v-model="msg8"
title="msg8"
:options="[ {
key: '3',
value: '蚵仔煎'
}, {
key: '4',
value: '龙须面'
}, {
key: '5',
value: '北京烤鸭'
}]"
/>
data:
data() {
return {
msg: "1",
msg2: "2",
msg3: "3",
msg4: "4",
msg5: "",
msg6: "1",
msg7: "2",
msg8: ["3", "5"],
startDate: new Date()
};
},
结果:
收集输入的值:
<el-button type="primary" @click="getAllInputFun">主要按钮</el-button>
methods: {
getAllInputFun() {
console.log(this.$data,"data");
},
}
表单使用
针对没有title的情况
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="250px"
class="demo-ruleForm"
>
<el-form-item label="活动性质" prop="type">
<vCheckBox
v-model="ruleForm.type"
:options="[ {
key: '3',
value: '蚵仔煎'
}, {
key: '4',
value: '龙须面'
}, {
key: '5',
value: '北京烤鸭'
}]"
></vCheckBox>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
data:
data() {
let validatePass2 = (rule, value, callback) => {
console.log(rule, "rule, value,");
console.log(!value);
console.log(value.length === 0);
this.$nextTick(() => {
if (!value || value.length === 0) {
callback(new Error("请选择活动性质"));
} else {
callback();
}
});
};
return {
ruleForm: {
type: [],
},
rules: {
type: [
{
type: "array",
required: true,
validator: validatePass2,
// message: "请至少选择一个活动性质",
trigger: "change"
}
],
}
};
},
methods:
methods: {
submitForm(formName) {
this.$refs[formName].validate(valid => {
if (valid) {
alert("submit!");
console.log(this.ruleForm, "ruleForm");
} else {
console.log("error submit!!");
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}