@neatui/vue 1.2.3 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neatui/vue",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "description": "basic component ui",
5
5
  "main": "./src/index.ts",
6
6
  "license": "MIT",
@@ -13,8 +13,8 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@fekit/floor": "^2.2.2",
16
- "@fekit/follow": "^1.0.9",
17
- "@fekit/itable": "^1.1.3",
16
+ "@fekit/follow": "^1.0.10",
17
+ "@fekit/itable": "^1.1.5",
18
18
  "@fekit/pullload": "^1.3.4",
19
19
  "@fekit/scale": "^2.0.1",
20
20
  "@fekit/scrollto": "^3.0.2",
@@ -23,6 +23,6 @@
23
23
  "@fekit/utils": "^2.10.7",
24
24
  "swiper": "^11.0.4",
25
25
  "vue-cropper": "^0.6.4",
26
- "vuedraggable": "^2.24.3"
26
+ "vuedraggable": "^4.1.0"
27
27
  }
28
28
  }
@@ -24,9 +24,8 @@
24
24
  <script setup lang="ts">
25
25
  import { reactive, ref, onMounted, onUnmounted, watch } from 'vue';
26
26
  import Follow from '@fekit/follow';
27
- // import Follow from './follow';
28
27
 
29
- const emits = defineEmits(['onhide', 'onshow']);
28
+ const emits = defineEmits(['update:modelValue', 'onhide', 'onshow']);
30
29
 
31
30
  const area: any = document.querySelector('#ifollow');
32
31
  if (!area) {
@@ -35,15 +34,30 @@
35
34
  document.body.appendChild(el);
36
35
  }
37
36
 
38
- const props = defineProps({
39
- pos: { type: String, default: 'bl' },
40
- event: { type: String, default: 'click' },
41
- btnClass: { type: String, default: 'dib' },
42
- btnStyle: { type: String, default: 'dib' },
43
- tipClass: { type: String, default: '' },
44
- tipStyle: { type: String, default: '' },
45
- tipBoxClass: { type: String, default: '' },
46
- tipBoxStyle: { type: String, default: '' }
37
+ // 类型
38
+ interface Props {
39
+ modelValue?: string | number;
40
+ pos?: string;
41
+ event?: string;
42
+ btnClass?: string;
43
+ btnStyle?: string;
44
+ tipClass?: string;
45
+ tipStyle?: string;
46
+ tipBoxClass?: string;
47
+ tipBoxStyle?: string;
48
+ }
49
+
50
+ // 入参
51
+ const props: any = withDefaults(defineProps<Props>(), {
52
+ modelValue: 0,
53
+ pos: 'bl',
54
+ event: 'click',
55
+ btnClass: 'dib',
56
+ btnStyle: 'dib',
57
+ tipClass: '',
58
+ tipStyle: '',
59
+ tipBoxClass: '',
60
+ tipBoxStyle: ''
47
61
  });
48
62
 
49
63
  const dom: any = ref(null);
@@ -90,6 +104,7 @@
90
104
  } else {
91
105
  emits('onhide');
92
106
  }
107
+ emits('update:modelValue', state.show);
93
108
  },
94
109
  { deep: true }
95
110
  );
@@ -145,6 +160,7 @@
145
160
  onUnmounted(() => {
146
161
  document.removeEventListener('click', cancel, true);
147
162
  state.show = 0;
163
+
148
164
  if (ex.value) {
149
165
  ex.value.remove();
150
166
  }
@@ -1,7 +1,7 @@
1
1
  import { Layer, LayerById } from './LayerView';
2
2
  import Icon from './Icon.vue';
3
- import IFollowView from './IFollowView@v2.vue';
3
+ import IFollowView from './IFollowView.vue';
4
4
  import IPickerView from './IPickerView.vue';
5
5
  import IScrollView from './IScrollView.vue';
6
- import IRouterView from './IRouterView@v4.vue';
6
+ import IRouterView from './IRouterView.vue';
7
7
  export { Icon, IRouterView, IFollowView, IPickerView, IScrollView, Layer, LayerById };
@@ -83,7 +83,7 @@
83
83
  </thead>
84
84
  <tbody :ui-tbody-load="state.load">
85
85
  <template v-if="lists.length">
86
- <tr v-for="(item, idx) in lists" :key="idx" v-bind="rows.attrs" v-on="event(rows.event, item)">
86
+ <tr v-for="(item, idx) in lists" :key="idx" v-bind="rows.attrs" v-on="event(rows.event, item, 'td')">
87
87
  <td v-if="showSelectAll" col-fixed="1" min-width>
88
88
  <label class="mb-ss" ui-form="@a type:checkbox"><input type="checkbox" v-model="item.__selected" /><span></span></label>
89
89
  </td>
@@ -96,7 +96,8 @@
96
96
  :col-fixed-side="col.fixed || 'l'"
97
97
  :data-field="col.field"
98
98
  >
99
- <TableColView :col="col" :data="item" />
99
+ <slot v-if="slots[col.field]" :name="col.field"></slot>
100
+ <TableColView v-else :col="col" :data="item" />
100
101
  </td>
101
102
  </template>
102
103
  <td v-if="slots.operate" col-fixed="r" class="ar"><slot name="operate" :item="item" :idx="idx"></slot></td>
@@ -186,6 +187,7 @@
186
187
  attrs?: Array<any> | (() => string | Array<any>);
187
188
  value?: any | (() => any);
188
189
  clear?: boolean | (() => boolean);
190
+ sort?: boolean | (() => boolean);
189
191
  }
190
192
  interface Props {
191
193
  words?: { [key: string]: any };
@@ -1,188 +0,0 @@
1
- <template>
2
- <div ref="dom" :class="btnClass" :style="btnStyle" @click="toggle" @mouseover="hovershow" @mouseout="hoverhide">
3
- <slot>
4
- <button ui-btn="@a s case :border"><i class="icon icon-dropdown"></i></button>
5
- </slot>
6
- </div>
7
- <Teleport to="#ifollow" v-if="$slots.tips">
8
- <div
9
- ref="tip"
10
- :class="tipClass"
11
- :style="`position: fixed; pointer-events: none; ${tipStyle}`"
12
- ui-tips="@a"
13
- :ui-tips-view="state.show ? 1 : 0"
14
- @mouseover="hovershow"
15
- @mouseout="hoverhide"
16
- >
17
- <div ref="box" :ui-tips-box="state.pos" :class="tipBoxClass" :style="tipBoxStyle">
18
- <slot name="tips"></slot>
19
- <div ui-tips-arrow=""></div>
20
- </div>
21
- </div>
22
- </Teleport>
23
- </template>
24
- <script setup lang="ts">
25
- import { reactive, ref, onMounted, onUnmounted, watch } from 'vue';
26
- import Follow from '@fekit/follow';
27
-
28
- const emits = defineEmits(['update:modelValue', 'onhide', 'onshow']);
29
-
30
- const area: any = document.querySelector('#ifollow');
31
- if (!area) {
32
- const el = document.createElement('div');
33
- el.id = 'ifollow';
34
- document.body.appendChild(el);
35
- }
36
-
37
- // 类型
38
- interface Props {
39
- modelValue?: string | number;
40
- pos: string;
41
- event: string;
42
- btnClass: string;
43
- btnStyle: string;
44
- tipClass: string;
45
- tipStyle: string;
46
- tipBoxClass: string;
47
- tipBoxStyle: string;
48
- }
49
-
50
- // 入参
51
- const props: any = withDefaults(defineProps<Props>(), {
52
- modelValue: 0,
53
- pos: 'bl',
54
- event: 'click',
55
- btnClass: 'dib',
56
- btnStyle: 'dib',
57
- tipClass: '',
58
- tipStyle: '',
59
- tipBoxClass: '',
60
- tipBoxStyle: ''
61
- });
62
-
63
- const dom: any = ref(null);
64
- const tip: any = ref(null);
65
- const box: any = ref(null);
66
- const state = reactive({
67
- view: 0,
68
- show: 0,
69
- pos: props.pos,
70
- hover: 0
71
- });
72
-
73
- const showTimer: any = ref(null);
74
- const hideTimer: any = ref(null);
75
- watch(
76
- () => state.hover,
77
- () => {
78
- clearTimeout(showTimer.value);
79
- clearTimeout(hideTimer.value);
80
- if (state.hover) {
81
- showTimer.value = setTimeout(() => {
82
- state.show = 1;
83
- }, 100);
84
- } else {
85
- hideTimer.value = setTimeout(() => {
86
- state.show = 0;
87
- }, 100);
88
- }
89
- }
90
- );
91
-
92
- // 开关
93
- const toggle = () => {
94
- if (props.event === 'click') {
95
- state.show = state.show ? 0 : 1;
96
- }
97
- };
98
-
99
- watch(
100
- [() => state.show, () => state.hover],
101
- () => {
102
- if (state.show) {
103
- emits('onshow');
104
- } else {
105
- emits('onhide');
106
- }
107
- emits('update:modelValue', state.show);
108
- },
109
- { deep: true }
110
- );
111
-
112
- const hovershow = () => {
113
- if (props.event === 'hover') {
114
- state.hover = 1;
115
- }
116
- };
117
-
118
- const hoverhide = () => {
119
- if (props.event === 'hover') {
120
- state.hover = 0;
121
- }
122
- };
123
-
124
- const show = () => {
125
- state.show = 1;
126
- };
127
-
128
- const hide = () => {
129
- state.show = 0;
130
- };
131
-
132
- // 取消
133
- const cancel = ({ target }: any = {}) => {
134
- if (tip.value && !tip.value?.contains(target) && dom.value && !dom.value.contains(target)) {
135
- state.show = 0;
136
- }
137
- };
138
-
139
- onMounted(() => {
140
- document.addEventListener('click', cancel, true);
141
- });
142
-
143
- const ex: any = ref(null);
144
- watch([() => dom.value, () => tip.value], () => {
145
- if (dom.value && tip.value) {
146
- ex.value = new Follow(dom.value, tip.value, (status) => {
147
- if (status === 'b') {
148
- const _pos = props.pos.replace(/b/g, 't');
149
- state.pos = _pos;
150
- } else {
151
- const _pos = props.pos.replace(/t/g, 'b');
152
- state.pos = _pos;
153
- }
154
- });
155
- } else {
156
- ex.value = null;
157
- }
158
- });
159
-
160
- onUnmounted(() => {
161
- document.removeEventListener('click', cancel, true);
162
- state.show = 0;
163
-
164
- if (ex.value) {
165
- ex.value.remove();
166
- }
167
- });
168
-
169
- watch(
170
- () => state.show,
171
- (show: any) => {
172
- if (ex.value) {
173
- if (show) {
174
- ex.value.listen();
175
- } else {
176
- ex.value.remove();
177
- }
178
- }
179
- }
180
- );
181
-
182
- defineExpose({
183
- toggle,
184
- show,
185
- hide,
186
- cancel
187
- });
188
- </script>
@@ -1,119 +0,0 @@
1
- <template>
2
- <div :am-view="view" :am-mode="mode" class="route-view pr full bg-back" :view-full="full ? 1 : 0" @animationend="anim">
3
- <div class="full" am-view-item="list">
4
- <slot name="list" :mode="mode"></slot>
5
- </div>
6
- <div class="full" am-view-item="item">
7
- <slot name="item" :mode="mode"></slot>
8
- </div>
9
- </div>
10
- </template>
11
- <script setup lang="ts">
12
- import { ref, watch } from 'vue';
13
- import { useRoute } from 'vue-router';
14
-
15
- interface Props {
16
- full?: boolean | 0 | 1;
17
- once?: number;
18
- mode?: 'default' | 'preview' | 'window';
19
- }
20
- const props: any = withDefaults(defineProps<Props>(), {
21
- full: 0,
22
- once: 0,
23
- mode: 'default'
24
- });
25
-
26
- const route = useRoute();
27
- const init = ref(0);
28
- const view = ref('');
29
- const anim = (e: any) => {
30
- if (e.animationName === 'am-hide') {
31
- view.value = route.query.id ? 'item' : 'list';
32
- }
33
- };
34
-
35
- const a = () => {
36
- if (init.value) {
37
- if (!props.once) {
38
- view.value = route.query.id ? 'iteming' : 'listing';
39
- }
40
- } else {
41
- view.value = route.query.id ? 'item' : 'list';
42
- init.value = 1;
43
- }
44
- };
45
-
46
- watch(() => route.query.id, a);
47
- a();
48
- </script>
49
-
50
- <style lang="scss">
51
- // 默认模式
52
- [am-view] {
53
- overflow: hidden;
54
-
55
- @keyframes am-show {
56
- 0% {
57
- opacity: 0;
58
- transform: translate3d(2em, 0, 0);
59
- }
60
- 100% {
61
- opacity: 1;
62
- transform: translate3d(0, 0, 0);
63
- }
64
- }
65
- @keyframes am-hide {
66
- 0% {
67
- opacity: 1;
68
- transform: translate3d(0, 0, 0);
69
- }
70
- 100% {
71
- opacity: 0;
72
- transform: translate3d(2em, 0, 0);
73
- }
74
- }
75
-
76
- &[view-full~='1'] {
77
- position: fixed;
78
- width: 100%;
79
- height: 100%;
80
- left: 0;
81
- top: 0;
82
- z-index: 15;
83
- }
84
-
85
- [am-view-item] {
86
- display: none;
87
-
88
- &[am-view-item~='row'] {
89
- flex-direction: row !important;
90
- }
91
- }
92
- &[am-view='list'] {
93
- [am-view-item~='list'] {
94
- flex-direction: column;
95
- display: flex;
96
- animation: am-show 0.35s ease both;
97
- }
98
- }
99
- &[am-view='listing'] {
100
- [am-view-item~='item'] {
101
- flex-direction: column;
102
- display: flex;
103
- animation: am-hide 0.3s ease-in-out both;
104
- }
105
- }
106
- &[am-view='item'] {
107
- [am-view-item~='item'] {
108
- display: flex;
109
- animation: am-show 0.35s ease both;
110
- }
111
- }
112
- &[am-view='iteming'] {
113
- [am-view-item~='list'] {
114
- display: flex;
115
- animation: am-hide 0.3s ease-in-out both;
116
- }
117
- }
118
- }
119
- </style>
@@ -1,252 +0,0 @@
1
- <template>
2
- <div :am-view="view" :am-mode="mode" class="route-view pr full bg-back" :view-full="full ? 1 : 0" @animationend="anim">
3
- <div class="full" am-view-item="list">
4
- <slot name="list" :mode="mode"></slot>
5
- </div>
6
- <div v-if="mode === 'default'" class="full" am-view-item="item">
7
- <slot name="item" :mode="mode"></slot>
8
- </div>
9
- <div v-if="mode === 'preview'" class="full" am-view-item="side" ref="SideRef">
10
- <slot name="side" :mode="mode"></slot>
11
- </div>
12
- </div>
13
- </template>
14
- <script setup lang="ts">
15
- import { onMounted, ref, watch } from 'vue';
16
- import { useRoute, useRouter } from 'vue-router';
17
-
18
- interface Props {
19
- full?: boolean | 0 | 1;
20
- once?: number;
21
- mode?: 'default' | 'preview' | 'window';
22
- queryName?: string;
23
- }
24
- const props: any = withDefaults(defineProps<Props>(), {
25
- full: 0,
26
- once: 0,
27
- mode: 'default',
28
- queryName: 'id'
29
- });
30
-
31
- const route = useRoute();
32
- const router = useRouter();
33
- const init = ref(0);
34
- const view = ref('');
35
- const anim = (e: any) => {
36
- if (e.animationName === 'am-hide') {
37
- view.value = route.query[props.queryName] ? 'item' : 'list';
38
- }
39
- };
40
-
41
- const a = () => {
42
- if (init.value) {
43
- if (!props.once) {
44
- view.value = route.query[props.queryName] ? 'iteming' : 'listing';
45
- }
46
- } else {
47
- view.value = route.query[props.queryName] ? 'item' : 'list';
48
- init.value = 1;
49
- }
50
- };
51
-
52
- watch(() => route.query[props.queryName], a);
53
- a();
54
-
55
- const SideRef: any = ref(null);
56
- // 取消
57
- const cancel = ({ target }: any = {}) => {
58
- const ifollow: any = document.querySelector('#ifollow');
59
- const toasts: any = document.querySelectorAll('.mc-toast');
60
- if (SideRef.value && !SideRef.value.contains(target) && !ifollow?.contains(target) && Array.from(toasts).every((t: any) => !t.contains(target))) {
61
- const _query = { ...route.query };
62
- delete _query[props.queryName];
63
- router.push({ path: route.path, query: _query });
64
- }
65
- };
66
- onMounted(() => {
67
- document.addEventListener('click', cancel, true);
68
- });
69
- </script>
70
-
71
- <style lang="scss">
72
- // 默认模式
73
- [am-view][am-mode~='default'] {
74
- overflow: hidden;
75
-
76
- @keyframes am-show {
77
- 0% {
78
- opacity: 0;
79
- transform: translate3d(2em, 0, 0);
80
- }
81
- 100% {
82
- opacity: 1;
83
- transform: translate3d(0, 0, 0);
84
- }
85
- }
86
- @keyframes am-hide {
87
- 0% {
88
- opacity: 1;
89
- transform: translate3d(0, 0, 0);
90
- }
91
- 100% {
92
- opacity: 0;
93
- transform: translate3d(2em, 0, 0);
94
- }
95
- }
96
-
97
- &[view-full~='1'] {
98
- position: fixed;
99
- width: 100%;
100
- height: 100%;
101
- left: 0;
102
- top: 0;
103
- z-index: 15;
104
- }
105
-
106
- [am-view-item] {
107
- display: none;
108
-
109
- &[am-view-item~='row'] {
110
- flex-direction: row !important;
111
- }
112
- }
113
- &[am-view='list'] {
114
- [am-view-item~='list'] {
115
- flex-direction: column;
116
- display: flex;
117
- animation: am-show 0.35s ease both;
118
- }
119
- }
120
- &[am-view='listing'] {
121
- [am-view-item~='item'] {
122
- flex-direction: column;
123
- display: flex;
124
- animation: am-hide 0.3s ease-in-out both;
125
- }
126
- }
127
- &[am-view='item'] {
128
- [am-view-item~='item'] {
129
- display: flex;
130
- animation: am-show 0.35s ease both;
131
- }
132
- }
133
- &[am-view='iteming'] {
134
- [am-view-item~='list'] {
135
- display: flex;
136
- animation: am-hide 0.3s ease-in-out both;
137
- }
138
- }
139
- }
140
-
141
- // 默认模式
142
- [am-view][am-mode~='preview'] {
143
- overflow: hidden;
144
-
145
- &[view-full~='1'] {
146
- position: fixed;
147
- width: 100%;
148
- height: 100%;
149
- left: 0;
150
- top: 0;
151
- z-index: 15;
152
- }
153
-
154
- [am-view-item] {
155
- &[am-view-item~='row'] {
156
- flex-direction: row !important;
157
- }
158
-
159
- &[am-view-item~='list'] {
160
- display: flex;
161
- }
162
- &[am-view-item~='side'] {
163
- position: absolute;
164
- top: 0;
165
- right: 0;
166
- z-index: 10;
167
- display: flex;
168
- justify-content: flex-end;
169
- align-items: stretch;
170
- align-content: space-between;
171
- pointer-events: none;
172
- & > * {
173
- pointer-events: auto;
174
- }
175
- transition: all 0.5s;
176
- }
177
- }
178
- &[am-view='list'],
179
- &[am-view='listing'] {
180
- [am-view-item~='side'] {
181
- display: flex;
182
- opacity: 0;
183
- transform: translate3d(110%, 0, 0);
184
- }
185
- }
186
- &[am-view='item'],
187
- &[am-view='iteming'] {
188
- [am-view-item~='side'] {
189
- display: flex;
190
- opacity: 1;
191
- transform: translate3d(0, 0, 0);
192
- }
193
- }
194
- }
195
-
196
- // 开新窗口
197
-
198
- // 弹出窗口
199
- [am-view][am-mode~='pop-up'] {
200
- overflow: hidden;
201
-
202
- &[view-full~='1'] {
203
- position: fixed;
204
- width: 100%;
205
- height: 100%;
206
- left: 0;
207
- top: 0;
208
- z-index: 15;
209
- }
210
-
211
- [am-view-item] {
212
- &[am-view-item~='row'] {
213
- flex-direction: row !important;
214
- }
215
-
216
- &[am-view-item~='list'] {
217
- display: flex;
218
- }
219
- &[am-view-item~='side'] {
220
- position: absolute;
221
- top: 0;
222
- right: 0;
223
- z-index: 10;
224
- display: flex;
225
- justify-content: flex-end;
226
- align-items: stretch;
227
- align-content: space-between;
228
- pointer-events: none;
229
- & > * {
230
- pointer-events: auto;
231
- }
232
- transition: all 0.5s;
233
- }
234
- }
235
- &[am-view='list'],
236
- &[am-view='listing'] {
237
- [am-view-item~='side'] {
238
- display: flex;
239
- opacity: 0;
240
- transform: translate3d(110%, 0, 0);
241
- }
242
- }
243
- &[am-view='item'],
244
- &[am-view='iteming'] {
245
- [am-view-item~='side'] {
246
- display: flex;
247
- opacity: 1;
248
- transform: translate3d(0, 0, 0);
249
- }
250
- }
251
- }
252
- </style>
@@ -1,119 +0,0 @@
1
- import ResizeObserver from 'resize-observer-polyfill';
2
-
3
- class Follow {
4
- box: any[];
5
- dom: any;
6
- tip: any;
7
- ing: any;
8
- sub: any;
9
- obs: any;
10
- fun: (status: any) => void;
11
- private css: () => void;
12
- z: number;
13
- constructor(dom: any, tip: any, fun = (_status: any) => {}) {
14
- this.dom = dom;
15
- this.tip = tip;
16
- this.box = [];
17
- this.css = this.setcss.bind(this);
18
- this.fun = fun;
19
- this.sub = this.tip.firstElementChild;
20
- this.z = 0;
21
- }
22
- setcss() {
23
- if (!this.ing) {
24
- window.requestAnimationFrame(() => {
25
- this.ing = false;
26
- const dr = this.dom?.getBoundingClientRect() || { width: 0, height: 0, top: 0, bottom: 0, left: 0, right: 0 };
27
- const sr = this.sub?.getBoundingClientRect() || { height: 0 };
28
- this.tip.style.inset = `${dr.top}px auto auto ${dr.left}px`;
29
- this.tip.style.width = dr.width + 'px';
30
- this.tip.style.height = dr.height + 'px';
31
- this.fun('');
32
- this.box.forEach((e: any) => {
33
- const ar = e?.getBoundingClientRect() || {};
34
- if (dr.bottom < ar.top || dr.top > ar.bottom || dr.right < ar.left || dr.left > ar.right) {
35
- this.tip.style.opacity = '0';
36
- this.sub.style.pointerEvents = 'none';
37
- } else {
38
- this.tip.style.opacity = '';
39
- this.sub.style.pointerEvents = '';
40
- }
41
- if (dr.bottom + sr.height + 10 > ar.bottom) {
42
- this.fun('b');
43
- }
44
- });
45
- const tr = this.tip?.getBoundingClientRect() || { left: 0 };
46
- const x = this.sub.offsetLeft + tr.left;
47
- const arrow = this.sub.querySelector('[ui-tips-arrow]');
48
- if (x < 0) {
49
- this.sub.style.transform = `translate3d(${-x}px,0,0)`;
50
- if (arrow && arrow.style) {
51
- arrow.style.transform = `translateX(${x}px) rotate(45deg)`;
52
- }
53
- } else {
54
- this.sub.style.transform = '';
55
- if (arrow && arrow.style) {
56
- arrow.style.transform = '';
57
- }
58
- }
59
- });
60
- this.ing = true;
61
- }
62
- }
63
- listen() {
64
- // 向上查询有滚动条的元素
65
- const _find = (e: any) => {
66
- // 判断是否为DOM节点
67
- if (e && e.nodeType === 1) {
68
- const css: any = window.getComputedStyle(e);
69
- // 查询所有父组节点的最高层级
70
- if (!isNaN(css.zIndex) && css.zIndex >= this.z) {
71
- this.z = Number(css.zIndex) + 10;
72
- }
73
- // 节点是否有滚动条
74
- if (
75
- (css.overflowY === 'auto' || css.overflowY === 'scroll' || css.overflowX === 'auto' || css.overflowX === 'scroll') &&
76
- (e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth)
77
- ) {
78
- this.box.push(e);
79
- }
80
- _find(e.parentNode);
81
- }
82
- };
83
- _find(this.dom);
84
-
85
- // 自动层级
86
- if (window.getComputedStyle(this.tip).zIndex) {
87
- this.tip.style.zIndex = `${this.z}`;
88
- }
89
-
90
- this.css();
91
- // 监听窗口尺寸变化
92
- window.addEventListener('resize', this.css);
93
- window.addEventListener('click', this.css);
94
- // 监听滚动条的元素
95
- this.box.forEach((e: any) => {
96
- e.addEventListener('scroll', this.css);
97
- });
98
- // 监听移入事件
99
- this.dom?.addEventListener('mouseenter', this.css);
100
- // 监听参考元素变化
101
- this.obs = new ResizeObserver(this.css);
102
- this.obs?.observe(this.dom);
103
- }
104
- remove() {
105
- // console.log('移除监听');
106
- // 清除窗口尺寸变化事件监听器
107
- window.removeEventListener('resize', this.css);
108
- window.removeEventListener('click', this.css);
109
- // 清除滚动条元素的事件监听器
110
- this.box.forEach((e: any) => {
111
- e.removeEventListener('scroll', this.css);
112
- });
113
- // 清除鼠标移入事件监听器
114
- this.dom?.removeEventListener('mouseenter', this.css);
115
- // 清除监听参考元素变化
116
- this.obs?.disconnect();
117
- }
118
- }
119
- export default Follow;