此處省略八百字的前言......
怕內容太多理解須要點時間,我一句話作總結。創做使我快樂。javascript
疫情當前愉快的心情提升了個人免疫力。html
Checkbox
和CheckboxGroup
兩個組件。參數 | 說明 | 類型 | 可選值 | 默認值 |
---|---|---|---|---|
type | 類型 | String | default errer success warning |
default |
value / v-model | 綁定值 | Boolean | 無 | 無 |
label | 選中狀態的值 | String | 無 | 無 |
icon | 自定義選中的icon |
String | 無 | iconselected |
disabled | 是否禁用Checkbox |
Boolean | 無 | 無 |
參數 | 說明 | 類型 | 可選值 | 默認值 |
---|---|---|---|---|
type | 類型 | String | default errer success warning |
default |
value / v-model | 綁定值 | Array | 無 | 無 |
inline | 是否串聯成一行 | Boolean | 無 | true |
icon | 自定義選中的icon |
String | 無 | iconselected |
disabled | 是否禁用Checkbox |
Boolean | 無 | 無 |
Checkbox
CheckboxGroup
配合使用時CheckboxGroup
設置type
icon
disabled
屬性可控制Checkbox
的type
icon
disabled
屬性。/utils/index.js
/** * 查找上級是否有存在對應組件 * @param {*} context * @param {*} componentName * @param {*} componentNames */
export const findComponentUpward = (context, componentName, componentNames) => {
if (typeof componentName === 'string') {
componentNames = [componentName];
} else {
componentNames = componentName;
}
let parent = context.$parent;
let name = parent.$options.name;
while (parent && (!name || componentNames.indexOf(name) < 0)) {
parent = parent.$parent;
if (parent) { name = parent.$options.name; }
}
return parent;
};
複製代碼
/mixins/props.js
const type = {
props: {
type: {
type: String,
default: "default",
validator: function (value) {
return ["default", "errer", "success", "warning"].includes(value);
}
}
}
}
module.exports = { type };
複製代碼
/utils/index.js
/** * 根據組件名稱查找全部下級對應的組件(特定的層級關係,無法跨級查詢) * @param {*} context * @param {*} componentName */
export const findComponentsDownward = (context, componentName) => {
const array = [];
for (let i = 0; i < context.$children.length; i += 1) {
if (context.$children[i].$options.name === componentName) {
array.push(context.$children[i]);
}
}
return array;
};
複製代碼
templatevue
<template>
<label class="g7-Checkbox">
<span :class="['g7-Checkbox-icon',`g7-text-color-${parentType}`,{['disabled']:parenDisabled}]">
<transition name="fade">
<Icon v-show="currentValue" :size="20" :icon="parentIcon" />
</transition>
</span>
<span :class="['g7-Checkbox-text',{['disabled']:parenDisabled}]">
<slot>{{label}}</slot>
</span>
<!-- 依據是否存在CheckboxGroup父組件,而使用不一樣的處理方式 -->
<input v-if="parent" type="checkbox" :value="label" class="g7-Checkbox-input" @change="change" v-model="model" :disabled="parenDisabled" />
<input v-else type="checkbox" class="g7-Checkbox-input" :checked="currentValue" @change="change" :disabled="parenDisabled" />
</label>
</template>
複製代碼
javaScriptjava
<script>
import Icon from "../Icon"; //自定義的組件
import { findComponentUpward } from "../../utils";
import { type } from "../../mixins/props";
export default {
name: "G-Checkbox",
components: { Icon },
mixins: [type],
data() {
return {
parent: "",
currentValue: this.value,
model: []
};
},
props: {
label: {
type: String
},
icon: {
type: String,
default: "iconselected"
},
value: {
type: Boolean
},
disabled: {
type: Boolean
}
},
watch: {
value(val) {
this.currentValue = val;
},
model(val) {
for (let i = 0; i < val.length; i += 1) {
if (!this.label) {
return;
}
if (val[i] === this.label) {
this.currentValue = true;
break;
}
this.currentValue = false;
}
}
},
methods: {
/** * 根據入參判斷CheckboxGroup組件是否有指定的的值 */
parentFnc(options, value) {
if (value) {
return this.parent[options] === value
? this[options]
: this.parent[options];
}
return this.parent[options] ? this.parent[options] : this[options];
},
change(e) {
if (this.parenDisabled) {
return;
}
//若是存在父組件的實例,則觸發父組件對應的方法
if (this.parent) {
this.parent.change(this.model);
return;
}
this.currentValue = e.target.checked;
this.$emit("input", this.currentValue);
this.$emit("on-change", this.currentValue);
}
},
computed: {
parentIcon() {
if (this.parent) {
const { parentFnc } = this;
return parentFnc("icon", "iconselected");
}
return this.icon;
},
parentType() {
if (this.parent) {
const { parentFnc } = this;
return parentFnc("type", "default");
}
return this.type;
},
parenDisabled() {
if (this.parent) {
const { parentFnc } = this;
return parentFnc("disabled");
}
return this.disabled;
}
},
mounted() {
const parent = findComponentUpward(this, "G-Checkbox-Group");
if (parent) {
this.parent = parent;
parent.updateModel();
}
}
};
</script>
複製代碼
/CheckboxGroup/index.vue
<template>
<div :class="['g7-CheckboxGroup',{['inline']:inline}]">
<slot></slot>
</div>
</template>
<script> import { type } from "../../mixins/props"; import { findComponentsDownward } from "../../utils/index"; export default { name: "G-Checkbox-Group", mixins: [type], data() { return { childrens: [], currentValue: this.value }; }, props: { value: { type: Array, default() { return []; } }, inline: { type: Boolean, default: true }, disabled: { type: Boolean }, icon: { type: String, default: "iconselected" } }, watch: { value(val) { this.currentValue = val; this.updateModel(); } }, methods: { updateModel() { this.childrens = findComponentsDownward(this, "G-Checkbox"); if (this.childrens) { this.childrens.forEach(element => { element.model = this.currentValue; element.currentValue = this.currentValue.indexOf(element.label) >= 0; }); } }, change(value) { this.currentValue = value; this.$emit("input", value); this.$emit("on-change", value); this.updateModel(); } }, mounted() { this.updateModel(); } }; </script>
複製代碼
<template>
<demoTop gray text="Checkbox">
<section class="demo-button-row">
<h3>基本用法</h3>
<div class="cell">
<G-Checkbox>選項</G-Checkbox>
</div>
</section>
<section class="demo-button-row">
<h3>type類型</h3>
<div class="cell">
<G-Checkbox-Group>
<G-Checkbox type="default" label="default"></G-Checkbox>
<G-Checkbox type="errer" label="errer"></G-Checkbox>
<G-Checkbox type="success" label="success"></G-Checkbox>
<G-Checkbox type="warning" label="warning"></G-Checkbox>
</G-Checkbox-Group>
</div>
</section>
<section class="demo-button-row">
<h3>搭配CheckboxGroup使用</h3>
<div class="cell">
<G-Checkbox-Group>
<G-Checkbox label="選項一" />
<G-Checkbox label="選項二" />
<G-Checkbox label="選項三" />
</G-Checkbox-Group>
</div>
</section>
<section class="demo-button-row">
<h3>v-model綁定</h3>
<div class="cell">
<G-Checkbox-Group v-model="model">
<G-Checkbox label="選項一" />
<G-Checkbox label="選項二" />
<G-Checkbox label="選項三" />
</G-Checkbox-Group>
</div>
</section>
<section class="demo-button-row">
<h3>禁用</h3>
<div class="cell">
<G-Checkbox-Group :value="['選項二']">
<G-Checkbox disabled label="選項一" />
<G-Checkbox disabled label="選項二" />
<G-Checkbox label="選項三" />
</G-Checkbox-Group>
</div>
</section>
<section v-if="false" class="demo-button-row">
<h3>禁用</h3>
<div class="cell">
<G-Checkbox-Group disabled :value="['選項二']">
<G-Checkbox label="選項一" />
<G-Checkbox label="選項二" />
<G-Checkbox label="選項三" />
</G-Checkbox-Group>
</div>
</section>
<section v-if="false" class="demo-button-row">
<h3>禁用</h3>
<div class="cell">
<G-Checkbox-Group type="success" :value="['選項二']">
<G-Checkbox label="選項一" />
<G-Checkbox label="選項二" />
<G-Checkbox label="選項三" />
</G-Checkbox-Group>
</div>
</section>
<section v-if="false" class="demo-button-row">
<h3>禁用</h3>
<div class="cell">
<G-Checkbox-Group icon="iconradioactive" :value="['選項二']">
<G-Checkbox label="選項一" />
<G-Checkbox label="選項二" />
<G-Checkbox label="選項三" />
</G-Checkbox-Group>
</div>
</section>
<section class="demo-button-row">
<h3>change事件</h3>
<div class="cell">
<G-Checkbox-Group @on-change="change">
<G-Checkbox label="選項一" />
<G-Checkbox label="選項二" />
<G-Checkbox label="選項三" />
</G-Checkbox-Group>
</div>
</section>
</demoTop>
</template>
<script> export default { data() { return { model: ["選項二"] }; }, methods: { change(val) { this.$Toast.info(`選中:${val}`); } } }; </script>
<style lang="less" scoped> .demo-button-row { padding: 0 15px; h3 { margin: 0; padding: 15px 0; color: #84849a; font-weight: normal; font-size: 14px; } } </style>
複製代碼
本人水平有限,搬磚不易,不足之處請多指教!
各類各樣的業務組件通過內部業務的打磨後,會慢慢整理共享給各位大佬......less