Skip to content

Commit 99e8400

Browse files
author
kaiming.xu
committedAug 21, 2018
event bus全局污染问题
1 parent d54f9ea commit 99e8400

16 files changed

+332
-42
lines changed
 

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,6 @@ handleReset() {
117117

118118
the following demo contains all the functions of the component and the supported form items.
119119

120-
demo: <https://jsrun.net/bKgKp/embedded/all/light/>
120+
demo: <http://jsrun.net/bKgKp/embedded/all/light/>
121121

122122
This [article](https://juejin.im/post/5b1cdd29e51d4506bb3a771d) introduces the detailed implementation of this component.

‎example/App.vue

+298
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
:schema="formData.schema"
77
:value="formData.value"
88
></schema-form>
9+
<schema-form
10+
ref="schemaForm2"
11+
:schema="formData.schema"
12+
:value="formData2.value"
13+
></schema-form>
914
<div style="text-align: center; margin-top: 10px;">
1015
<button @click="handleReset" type="button" class="jf-btn jf-btn-warning">
1116
<span>重置</span>
@@ -332,6 +337,299 @@ export default {
332337
"passward": ""
333338
}
334339
}
340+
},
341+
"formData2": {
342+
"schema": {
343+
"register": {
344+
"type": "TheTree",
345+
"title": "注册",
346+
"properties": {
347+
"name": {
348+
"type": "TheInput",
349+
"title": "姓名",
350+
"rules": {
351+
"required": true,
352+
"message": "The name cannot be empty"
353+
}
354+
},
355+
"age": {
356+
"type": "TheNumberInput",
357+
"title": "年龄",
358+
"rules": [
359+
{
360+
"type": "number",
361+
"required": true,
362+
"message": "The age cannot be empty"
363+
}
364+
]
365+
},
366+
"gender": {
367+
"type": "TheRadio",
368+
"title": "性别",
369+
"propertyOrder": 10,
370+
"options": [
371+
{
372+
"value": 1,
373+
"label": ""
374+
},
375+
{
376+
"value": 2,
377+
"label": ""
378+
}
379+
],
380+
"rules": {
381+
"type": "number",
382+
"required": true,
383+
"message": "The 性别 cannot be empty"
384+
}
385+
},
386+
"interests": {
387+
"type": "TheCheckbox",
388+
"title": "兴趣爱好",
389+
"propertyOrder": 1,
390+
"options": [
391+
{
392+
"value": 1,
393+
"label": "吃饭"
394+
},
395+
{
396+
"value": 2,
397+
"label": "睡觉"
398+
},
399+
{
400+
"value": 3,
401+
"label": "打豆豆"
402+
}
403+
],
404+
"rules": {
405+
"type": "array",
406+
"required": true,
407+
"message": "The 兴趣爱好 cannot be empty"
408+
}
409+
},
410+
"location": {
411+
"type": "TheTree",
412+
"title": "地址信息",
413+
"propertyOrder": 3,
414+
"properties": {
415+
"province": {
416+
"type": "TheInput",
417+
"title": "省份",
418+
"rules": {
419+
"required": true,
420+
"message": "The 省份 cannot be empty"
421+
}
422+
},
423+
"city": {
424+
"type": "TheInput",
425+
"title": "",
426+
"rules": {
427+
"required": true,
428+
"message": "The 市 cannot be empty"
429+
}
430+
}
431+
}
432+
},
433+
"job": {
434+
"type": "TheSelect",
435+
"title": "工作",
436+
"propertyOrder": 10,
437+
"options": [
438+
{
439+
"value": "internet",
440+
"label": "互联网"
441+
},
442+
{
443+
"value": "medicine",
444+
"label": "医学"
445+
},
446+
{
447+
"value": "estate",
448+
"label": "房地产"
449+
},
450+
{
451+
"value": "other",
452+
"label": "其他"
453+
}
454+
],
455+
"rules": {
456+
"required": true,
457+
"message": "工作不能为空"
458+
}
459+
},
460+
"education": {
461+
"type": "TheAddInput",
462+
"title": "教育信息",
463+
"addText": "添加教育信息",
464+
"addDefault": "哈哈哈",
465+
"rules": {
466+
"myRule": {
467+
"type": "array",
468+
"required": true,
469+
"message": "The 教育信息 cannot be empty"
470+
},
471+
"childRule": {
472+
"required": true,
473+
"message": "这一项不能为空"
474+
}
475+
}
476+
},
477+
"introduce": {
478+
"type": "TheTextArea",
479+
"title": "个人介绍",
480+
"rules": {
481+
"required": true,
482+
"message": "The 个人介绍 cannot be empty"
483+
}
484+
},
485+
"pets": {
486+
"type": "TheTable",
487+
"title": "宠物信息",
488+
"columns": {
489+
"name": {
490+
"type": "TheInput",
491+
"title": "名字",
492+
"rules": {
493+
"required": true,
494+
"message": "名字不能为空"
495+
}
496+
},
497+
"type": {
498+
"type": "TheSelect",
499+
"title": "类型",
500+
"propertyOrder": 1,
501+
"options": [
502+
{
503+
"value": 1,
504+
"label": ""
505+
},
506+
{
507+
"value": 2,
508+
"label": ""
509+
},
510+
{
511+
"value": 3,
512+
"label": ""
513+
},
514+
{
515+
"value": 4,
516+
"label": "其他"
517+
}
518+
],
519+
"rules": {
520+
"type": "number",
521+
"required": true,
522+
"message": "类型不能为空"
523+
}
524+
},
525+
"gender": {
526+
"type": "TheRadio",
527+
"title": "性别",
528+
"propertyOrder": 3,
529+
"options": [
530+
{
531+
"value": 1,
532+
"label": ""
533+
},
534+
{
535+
"value": 2,
536+
"label": ""
537+
}
538+
],
539+
"rules": {
540+
"type": "number",
541+
"required": true,
542+
"message": "The 性别 cannot be empty"
543+
}
544+
},
545+
"interests": {
546+
"type": "TheCheckbox",
547+
"title": "兴趣爱好",
548+
"propertyOrder": 2,
549+
"options": [
550+
{
551+
"value": 1,
552+
"label": "吃饭"
553+
},
554+
{
555+
"value": 2,
556+
"label": "睡觉"
557+
},
558+
{
559+
"value": 3,
560+
"label": "打豆豆"
561+
}
562+
],
563+
"rules": {
564+
"type": "array",
565+
"required": true,
566+
"message": "The 兴趣爱好 cannot be empty"
567+
}
568+
}
569+
},
570+
"addDefault": {
571+
"type": "",
572+
"name": "",
573+
"gender": "",
574+
"interests": []
575+
},
576+
"addText": "添加表格行",
577+
"rules": {
578+
"type": "array",
579+
"required": true,
580+
"message": "The 宠物信息 cannot be empty"
581+
}
582+
}
583+
}
584+
},
585+
"login": {
586+
"type": "TheTree",
587+
"title": "登录信息",
588+
"properties": {
589+
"name": {
590+
"type": "TheInput",
591+
"title": "姓名",
592+
"rules": {
593+
"required": true,
594+
"message": "The name cannot be empty"
595+
}
596+
},
597+
"passward": {
598+
"type": "ThePassInput",
599+
"title": "密码",
600+
"rules": {
601+
"required": true,
602+
"message": "The 密码 cannot be empty"
603+
}
604+
}
605+
}
606+
}
607+
},
608+
"value": {
609+
"register": {
610+
"name": "wqe",
611+
"age": 25,
612+
"gender": 1,
613+
"interests": [1],
614+
"location": {
615+
"province": "北京省",
616+
"city": "北京市"
617+
},
618+
"introduce": '',
619+
"education": ['11'],
620+
"job": "internet",
621+
"pets": [{
622+
"type": "21",
623+
"name": "Walter",
624+
"gender": 1,
625+
"interests": [1, 2]
626+
}]
627+
},
628+
"login": {
629+
"name": "",
630+
"passward": ""
631+
}
632+
}
335633
}
336634
}
337635
}

‎src/components/SchemaForm.vue

+7-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
:key="item.key"
66
:objKey="[item.key]"
77
:objVal="formValue[item.key]"
8+
:EVENT_BUS="EVENT_BUS"
89
v-bind="item.val"></the-tree>
910
<!-- <div style="text-align: center; margin-top: 10px;">
1011
<Button @click="handleReset" type="warning">重置</Button>
@@ -17,7 +18,7 @@
1718
import TheTree from './TheTree'
1819
import Button from './button'
1920
// utils
20-
import { orderProperty, EventBus, cloneDeep } from '../utils'
21+
import { orderProperty, createEventBus, cloneDeep } from '../utils'
2122
2223
// 表单验证这里参考iview的做法,通过mixin的方式将事件emitter注入到每个组件
2324
// 通过事件的广播与派发,input组件blur之后向上dispatch事件,
@@ -31,15 +32,15 @@ export default {
3132
props: ['schema', 'value'],
3233
created() {
3334
this.initFormData(this.value);
34-
EventBus.$on('on-form-item-add', field => {
35+
this.EVENT_BUS.$on('on-form-item-add', field => {
3536
if(field) this.fields.push(field);
3637
return false;
3738
});
38-
EventBus.$on('on-form-item-remove', (field) => {
39+
this.EVENT_BUS.$on('on-form-item-remove', (field) => {
3940
if (field) this.fields.splice(this.fields.indexOf(field), 1);
4041
return false;
4142
});
42-
EventBus.$on('on-set-form-data', payload => {
43+
this.EVENT_BUS.$on('on-set-form-data', payload => {
4344
this.setFormData(payload);
4445
});
4546
},
@@ -101,7 +102,8 @@ export default {
101102
return {
102103
"initFormValue": {},
103104
"formValue": {},
104-
"fields": []
105+
"fields": [],
106+
"EVENT_BUS": createEventBus()
105107
}
106108
}
107109
}

‎src/components/TheAddInput.vue

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
:keyArr="[index]"
1313
parentName="TheAddInput"
1414
:rules="rules.childRule"
15-
:noLabel="true">
15+
:noLabel="true"
16+
:EVENT_BUS="EVENT_BUS">
1617
<div style="margin-left: 8px">
1718
<Button @click="del(index)" type="warning">删除</Button>
1819
</div>
@@ -47,8 +48,7 @@
4748
import TheInput from './TheInput';
4849
import Button from './button';
4950
import schema from 'async-validator';
50-
// utils
51-
import { EventBus } from '../utils'
51+
5252
//mixin
5353
import Base from '../mixins/base';
5454
import Validate from '../mixins/validate';
@@ -60,9 +60,9 @@ export default {
6060
TheInput,
6161
Button
6262
},
63-
props: ['title', 'objKey', 'objVal', 'noLabel', 'rules', 'addDefault', 'addText'],
63+
props: ['title', 'objKey', 'objVal', 'noLabel', 'rules', 'addDefault', 'addText', 'EVENT_BUS'],
6464
created() {
65-
EventBus.$on('on-input-validate', obj => {
65+
this.$props.EVENT_BUS.$on('on-input-validate', obj => {
6666
if(obj.parentName !== 'TheAddInput') return;
6767
this.validateArray.splice(obj.keyArr[0], 1, obj.validateObj);
6868
return false;

‎src/components/TheCheckbox.vue

+1-4
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,14 @@
2222

2323
<script>
2424
25-
// utils
26-
import { EventBus } from '../utils'
27-
2825
//mixin
2926
import Base from '../mixins/base';
3027
import Validate from '../mixins/validate';
3128
3229
export default {
3330
name: 'TheCheckbox',
3431
mixins: [ Validate, Base ],
35-
props: ["options", 'title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName'],
32+
props: ["options", 'title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName', 'EVENT_BUS'],
3633
methods: {
3734
handleChange() {
3835
// this.validate();

‎src/components/TheInput.vue

+1-4
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,14 @@
1414

1515
<script>
1616
17-
// utils
18-
import { EventBus } from '../utils'
19-
2017
//mixin
2118
import Base from '../mixins/base';
2219
import Validate from '../mixins/validate';
2320
2421
export default {
2522
name: 'TheInput',
2623
mixins: [ Validate, Base ],
27-
props: ['title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName', 'theFormat'],
24+
props: ['title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName', 'theFormat', 'EVENT_BUS'],
2825
methods: {
2926
handleBlur() {
3027
this.validate();

‎src/components/TheNumberInput.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default {
1010
components: {
1111
TheInput
1212
},
13-
props: ['title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName'],
13+
props: ['title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName', 'EVENT_BUS'],
1414
}
1515
</script>
1616

‎src/components/ThePassInput.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default {
1010
components: {
1111
TheInput
1212
},
13-
props: ['title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName'],
13+
props: ['title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName', 'EVENT_BUS'],
1414
}
1515
</script>
1616

‎src/components/TheRadio.vue

+1-4
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,14 @@
2222

2323
<script>
2424
25-
// utils
26-
import { EventBus } from '../utils'
27-
2825
//mixin
2926
import Base from '../mixins/base';
3027
import Validate from '../mixins/validate';
3128
3229
export default {
3330
name: 'TheRadio',
3431
mixins: [ Validate, Base ],
35-
props: ["options", 'title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName'],
32+
props: ["options", 'title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName', 'EVENT_BUS'],
3633
methods: {
3734
handleChange() {
3835
// this.validate()

‎src/components/TheSelect.vue

+1-3
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,14 @@
4040

4141
<script>
4242
43-
// utils
44-
import { EventBus } from '../utils'
4543
//mixin
4644
import Base from '../mixins/base';
4745
import Validate from '../mixins/validate';
4846
4947
export default {
5048
name: 'TheSelect',
5149
mixins: [ Validate, Base ],
52-
props: ["options", 'title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName'],
50+
props: ["options", 'title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName', 'EVENT_BUS'],
5351
computed: {
5452
selectVal () {
5553
return this.options.filter(item => {

‎src/components/TheTable.vue

+4-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
:keyArr="[index, col.key]"
2828
parentName="TheTable"
2929
:noLabel="true"
30+
:EVENT_BUS="EVENT_BUS"
3031
v-bind="col.val"></component>
3132
</div>
3233
</td>
@@ -57,7 +58,7 @@ import Button from './button';
5758
import schema from 'async-validator';
5859
5960
// utils
60-
import { orderProperty, EventBus } from '../utils'
61+
import { orderProperty } from '../utils'
6162
6263
//mixin
6364
import Base from '../mixins/base';
@@ -76,14 +77,14 @@ export default {
7677
TheCheckbox,
7778
Button
7879
},
79-
props: ['title', 'objKey', 'objVal', "addDefault", "addText", "columns", "noLabel", "rules"],
80+
props: ['title', 'objKey', 'objVal', "addDefault", "addText", "columns", "noLabel", "rules", "EVENT_BUS"],
8081
computed: {
8182
orderColumns() {
8283
return orderProperty(this.columns);
8384
}
8485
},
8586
created() {
86-
EventBus.$on('on-input-validate', obj => {
87+
this.$props.EVENT_BUS.$on('on-input-validate', obj => {
8788
if(obj.parentName !== 'TheTable') return;
8889
obj.keyArr.reduce((pre, cur, curIndex, arr) => {
8990
if(curIndex === arr.length - 1) {

‎src/components/TheTextArea.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default {
1111
components: {
1212
TheInput
1313
},
14-
props: ['title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName']
14+
props: ['title', 'objKey', 'objVal', 'noLabel', 'rules', 'validateObj', 'keyArr', 'parentName', 'EVENT_BUS']
1515
}
1616
</script>
1717

‎src/components/TheTree.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
:is="item.val.type"
99
:objKey="getObjKeys(objKey, item.key)"
1010
:objVal="getObjVal(item.key)"
11+
:EVENT_BUS="EVENT_BUS"
1112
v-bind="item.val">
1213
</component>
1314
</div>
@@ -41,7 +42,7 @@ export default {
4142
TheAddInput,
4243
TheTable
4344
},
44-
props: ['title', 'properties', 'objKey', 'objVal'],
45+
props: ['title', 'properties', 'objKey', 'objVal', 'EVENT_BUS'],
4546
methods: {
4647
getObjVal(key) {
4748
return this.objVal[key];

‎src/mixins/base.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11

2-
import { EventBus } from '../utils';
3-
42
export default {
53
computed: {
64
msg: {
@@ -11,17 +9,17 @@ export default {
119
// if(this.theFormat && this.theFormat === 'number') {
1210
// value = Number(value);
1311
// }
14-
EventBus.$emit('on-set-form-data', {
12+
this.$props.EVENT_BUS.$emit('on-set-form-data', {
1513
key: this.keyName,
1614
value
1715
});
1816
}
1917
}
2018
},
2119
mounted() {
22-
EventBus.$emit('on-form-item-add', this);
20+
this.$props.EVENT_BUS.$emit('on-form-item-add', this);
2321
},
2422
beforeDestroy () {
25-
EventBus.$emit('on-form-item-remove', this);
23+
this.$props.EVENT_BUS.$emit('on-form-item-remove', this);
2624
}
2725
}

‎src/mixins/validate.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import schema from 'async-validator';
2-
import { EventBus } from '../utils';
32

43
export default {
54
computed: {
@@ -24,7 +23,7 @@ export default {
2423
// 按理说无法修改props的值,但是这里可以修改,控制台也没有警告
2524
// this.validateObj.validateState = '';
2625
// this.validateObj.validateMessage = '';
27-
EventBus.$emit('on-input-validate', {
26+
this.$props.EVENT_BUS.$emit('on-input-validate', {
2827
parentName: this.parentName,
2928
keyArr: this.keyArr,
3029
validateObj: {
@@ -54,7 +53,7 @@ export default {
5453
let state = !err ? 'success' : 'error';
5554
let msg = err ? err[0].message : '';
5655
if(this.validateObj !== undefined) {
57-
EventBus.$emit('on-input-validate', {
56+
this.$props.EVENT_BUS.$emit('on-input-validate', {
5857
parentName: this.parentName,
5958
keyArr: this.keyArr,
6059
validateObj: {

‎src/utils/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import Vue from "vue";
22

3-
export const EventBus = new Vue();
3+
export const createEventBus = function () {
4+
return new Vue()
5+
};
46

57
// 根据propertyOrder 从小到大排序
68
export function orderProperty(obj) {

0 commit comments

Comments
 (0)
Please sign in to comment.