sh-view 2.0.3 → 2.0.5

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": "sh-view",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "description": "基于vxe-table二次封装",
5
5
  "main": "packages/index.js",
6
6
  "scripts": {
@@ -26,19 +26,18 @@
26
26
  "core-js": "^3.32.0",
27
27
  "countup.js": "^1.9.3",
28
28
  "cron-parser": "^4.8.1",
29
- "element-resize-detector": "^1.2.0",
30
29
  "exceljs": "^4.3.0",
31
30
  "jspdf": "^2.5.1",
32
31
  "jszip": "^3.10.1",
33
32
  "popper.js": "^1.16.1",
34
- "sh-tools": "^1.4.0",
33
+ "sh-tools": "^1.5.0",
35
34
  "tinymce": "^5.10.5",
36
35
  "vue": "^3.3.4",
37
36
  "vue-demi": "^0.13.11",
38
37
  "vue-masonry": "^0.16.0",
39
38
  "vue-router": "^4.2.2",
40
39
  "vuex": "^4.1.0",
41
- "vxe-table": "^4.5.5",
40
+ "vxe-table": "^4.5.6",
42
41
  "vxe-table-plugin-export-pdf": "^3.0.4",
43
42
  "vxe-table-plugin-export-xlsx": "^3.0.5",
44
43
  "xe-clipboard": "^1.10.2",
@@ -103,12 +103,12 @@ export default {
103
103
  }
104
104
  }
105
105
  .sh-card-body {
106
+ display: block;
106
107
  border-top: 1px solid var(--vxe-table-border-color);
107
- @include layoutFlex;
108
108
  }
109
109
  .sh-card-foot {
110
- border-top: 1px solid var(--vxe-table-border-color);
111
110
  @include layoutFlex;
111
+ border-top: 1px solid var(--vxe-table-border-color);
112
112
  }
113
113
  &.large {
114
114
  .sh-card-head .sh-card-head-title {
@@ -51,13 +51,14 @@ export default {
51
51
  [`${prefixCls}-pull-${this.pull}`]: this.pull
52
52
  }
53
53
  ]
54
- ;['xs', 'sm', 'md', 'lg', 'xl', 'xxl'].forEach(size => {
54
+ let sizeList = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl']
55
+ sizeList.forEach(size => {
55
56
  if (typeof this[size] === 'number') {
56
57
  classList.push(`${prefixCls}-span-${size}-${this[size]}`)
57
58
  } else if (typeof this[size] === 'object') {
58
59
  let props = this[size]
59
60
  Object.keys(props).forEach(prop => {
60
- classList.push(prop !== 'span' ? `${prefixCls}-${size}-${prop}-${props[prop]}` : `${prefixCls}-${size}-span-${props[prop]}`)
61
+ classList.push(`${prefixCls}-${size}-${prop}-${props[prop]}`)
61
62
  })
62
63
  }
63
64
  })
@@ -116,7 +116,9 @@ export default {
116
116
  }
117
117
  },
118
118
  created() {},
119
- mounted() {},
119
+ mounted() {
120
+ this.computeOffset()
121
+ },
120
122
  beforeUnmount() {},
121
123
  methods: {
122
124
  px2percent(numerator, denominator) {
@@ -246,7 +246,7 @@ export default {
246
246
  overflow: hidden;
247
247
  }
248
248
  &-inner {
249
- display: block;
249
+ display: flex;
250
250
  width: fit-content;
251
251
  white-space: nowrap;
252
252
  transition: transform 0.2s ease-in-out;
@@ -294,7 +294,7 @@ export default {
294
294
  }
295
295
  .sh-tab-item-active {
296
296
  background-color: var(--vxe-primary-color);
297
- border-color: var(--vxe-primary-darken-color);
297
+ border-color: var(--vxe-primary-color);
298
298
  color: #fff !important;
299
299
  }
300
300
  }
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <div class="sh-tag" :class="classes" :style="[borderStyle, backgroundStyle]" @click.stop="check">
3
- <span v-if="type === 'dot'" class="sh-tag-dot" :style="[backgroundStyle]"></span>
3
+ <span v-if="type === 'dot'" class="sh-tag-other"><span class="sh-tag-dot" :style="[backgroundStyle]"></span></span>
4
4
  <span class="sh-tag-text" :class="textClasses" :style="[fontStyle]"><slot></slot></span>
5
- <a v-if="closable" class="sh-tag-close" :style="[borderStyle]" @click="close">
5
+ <a v-if="closable" class="sh-tag-other sh-tag-close" :style="[borderStyle]" @click="close">
6
6
  <slot name="close"><sh-icon type="ios-close"></sh-icon></slot>
7
7
  </a>
8
8
  </div>
@@ -118,7 +118,7 @@ export default {
118
118
  $default-color: #f7f7f7;
119
119
  .sh-tag {
120
120
  display: inline-flex;
121
- align-items: center;
121
+ align-items: stretch;
122
122
  margin: 2px 4px 2px 0;
123
123
  border: 1px solid var(--vxe-table-border-color);
124
124
  border-radius: var(--vxe-border-radius);
@@ -141,13 +141,17 @@ $default-color: #f7f7f7;
141
141
  border: none !important;
142
142
  }
143
143
  }
144
+ &-other {
145
+ display: inline-flex;
146
+ align-items: center;
147
+ }
144
148
  &-dot {
145
149
  display: inline-block;
146
150
  width: 12px;
147
151
  height: 12px;
148
152
  border-radius: 50%;
149
153
  background-color: #ccc;
150
- margin: 0 5px 0 12px;
154
+ margin: 0 2px 0 8px;
151
155
  }
152
156
  &-text {
153
157
  padding: 0 8px;
@@ -6,7 +6,6 @@ import ShCodeEditor from './global-components/sh-code-editor/index.vue'
6
6
  import ShCol from './global-components/sh-col/index.vue'
7
7
  import ShCorner from './global-components/sh-corner/index.vue'
8
8
  import ShCountTo from './global-components/sh-count-to/index.vue'
9
- import ShDate from './global-components/sh-date/index.vue'
10
9
  import ShDrawer from './global-components/sh-drawer/index.vue'
11
10
  import ShEmpty from './global-components/sh-empty/index.vue'
12
11
  import ShForm from './global-components/sh-form/index.vue'
@@ -41,7 +40,6 @@ const components = {
41
40
  ShCol,
42
41
  ShCorner,
43
42
  ShCountTo,
44
- ShDate,
45
43
  ShDrawer,
46
44
  ShEmpty,
47
45
  ShForm,
@@ -0,0 +1,304 @@
1
+ <template>
2
+ <div class="sh-menu" :class="classes">
3
+ <div v-clickout="handleOut" class="sh-menu-inner">
4
+ <template v-for="(item, index) in options" :key="index">
5
+ <menuGroupContent :menu-item="item" />
6
+ </template>
7
+ </div>
8
+ </div>
9
+ </template>
10
+
11
+ <script>
12
+ import menuGroupContent from './menu-group-content.vue'
13
+ export default {
14
+ name: 'ShMenu',
15
+ components: {
16
+ menuGroupContent
17
+ },
18
+ provide() {
19
+ return {
20
+ MenuInstance: this
21
+ }
22
+ },
23
+ props: {
24
+ modelValue: {
25
+ type: String
26
+ },
27
+ mode: {
28
+ type: String,
29
+ default: 'vertical' // horizontal
30
+ },
31
+ indent: {
32
+ type: Number,
33
+ default: 20
34
+ },
35
+ accordion: {
36
+ type: Boolean,
37
+ default: true
38
+ },
39
+ theme: {
40
+ type: Boolean
41
+ },
42
+ fix: {
43
+ type: Boolean
44
+ },
45
+ collapsed: {
46
+ type: Boolean
47
+ },
48
+ options: {
49
+ type: Array,
50
+ default() {
51
+ return []
52
+ }
53
+ },
54
+ labelField: {
55
+ type: String,
56
+ default: 'label'
57
+ },
58
+ labelFormat: {
59
+ type: Function
60
+ }
61
+ },
62
+ emits: ['update:modelValue', 'change', 'expand'],
63
+ data() {
64
+ return {
65
+ activeName: this.modelValue,
66
+ activeNames: [],
67
+ openedNames: []
68
+ }
69
+ },
70
+ computed: {
71
+ classes() {
72
+ return {
73
+ theme: this.theme,
74
+ fix: this.fix,
75
+ collapsed: this.collapsed,
76
+ [`${this.mode}`]: this.mode
77
+ }
78
+ }
79
+ },
80
+ watch: {
81
+ modelValue(to, from) {
82
+ this.resetMenu()
83
+ }
84
+ },
85
+ mounted() {
86
+ this.resetMenu()
87
+ },
88
+ methods: {
89
+ // 重新渲染菜单
90
+ resetMenu() {
91
+ this.activeName = this.modelValue
92
+ this.resetExpand(this.activeName, true)
93
+ },
94
+ resetExpand(menuName, mount) {
95
+ let activeNames = []
96
+ let parentTree = this.$vUtils.searchTree(this.options, item => item.name === menuName)
97
+ this.$vUtils.eachTree(parentTree, item => {
98
+ activeNames.push(item.name)
99
+ })
100
+ if (mount) {
101
+ this.activeNames = activeNames
102
+ if (this.collapsed) return
103
+ }
104
+ // 过滤掉所有子节点
105
+ let menuIndex = activeNames.findIndex(item => item === menuName)
106
+ let parentNames = activeNames.filter((item, itemIndex) => menuIndex >= itemIndex)
107
+ if (!this.accordion) parentNames = Array.from(new Set(this.openedNames.concat(parentNames)))
108
+ this.openedNames = parentNames
109
+ },
110
+ onMenuSelect(menu) {
111
+ this.handleOut()
112
+ this.$emit('change', menu)
113
+ },
114
+ onMenuExpand(expand, menu) {
115
+ this.$emit('expand', expand, menu)
116
+ if (!expand) {
117
+ this.openedNames = this.openedNames.filter(name => name !== menu.name)
118
+ return
119
+ }
120
+ this.resetExpand(menu.name)
121
+ },
122
+ handleOut() {
123
+ if (!this.collapsed && this.mode === 'vertical') return
124
+ this.openedNames = []
125
+ }
126
+ }
127
+ }
128
+ </script>
129
+
130
+ <style lang="scss">
131
+ $textColor: var(--vxe-font-color);
132
+ $textActive: var(--vxe-primary-color);
133
+ $mainBgColor: var(--vxe-table-body-background-color);
134
+ $expandBgColor: var(--vxe-table-header-background-color);
135
+
136
+ $textDkColor: hsla(0, 0%, 100%, 0.6);
137
+ $textDkActive: #fff;
138
+ $mainDkBgColor: var(--vxe-primary-color);
139
+ $expandDkBgColor: var(--vxe-primary-darken-color);
140
+ .sh-menu {
141
+ position: relative;
142
+ background-color: $mainBgColor;
143
+ &.theme {
144
+ background-color: $mainDkBgColor;
145
+ .sh-menu-group {
146
+ &.is__expand {
147
+ background: $expandDkBgColor;
148
+ & > .sh-menu-item {
149
+ color: $textDkActive;
150
+ }
151
+ }
152
+ &.is__active {
153
+ & > .sh-menu-item {
154
+ color: $textDkActive;
155
+ }
156
+ }
157
+ & > .sh-menu-group-dropdown,
158
+ & > .sh-menu-group-dropright {
159
+ background-color: $mainDkBgColor;
160
+ }
161
+ }
162
+ .sh-menu-item {
163
+ color: $textDkColor;
164
+ &:hover {
165
+ color: $textDkActive;
166
+ background: var(--vxe-primary-lighten-color) !important;
167
+ }
168
+ &.sh-menu-item-active {
169
+ color: $textDkActive;
170
+ background: var(--vxe-primary-lighten-color);
171
+ &:after {
172
+ background: $textDkColor;
173
+ }
174
+ }
175
+ }
176
+ }
177
+ &.fix {
178
+ position: fixed;
179
+ top: 0;
180
+ left: 0;
181
+ right: 0;
182
+ }
183
+ &.horizontal {
184
+ .sh-menu-inner {
185
+ display: flex;
186
+ align-items: center;
187
+ height: 100%;
188
+ }
189
+ .sh-menu-item {
190
+ height: 100%;
191
+ &.sh-menu-item-active {
192
+ &:after {
193
+ width: 100%;
194
+ height: 3px;
195
+ top: auto;
196
+ bottom: 0;
197
+ }
198
+ }
199
+ &.sh-menu-item-level {
200
+ .sh-menu-item-arrow {
201
+ transform: rotate(90deg);
202
+ transform-origin: center;
203
+ }
204
+ }
205
+ }
206
+ .sh-menu-group {
207
+ height: 100%;
208
+ &.is__expand {
209
+ & > .sh-menu-item-level {
210
+ .sh-menu-item-arrow {
211
+ transform: rotate(-90deg);
212
+ transform-origin: center;
213
+ }
214
+ }
215
+ }
216
+ }
217
+ }
218
+ &.collapsed {
219
+ .sh-menu-item.sh-menu-item-level {
220
+ flex-wrap: wrap;
221
+ text-align: center;
222
+ padding: 5px;
223
+ &.sh-menu-item-active {
224
+ &:after {
225
+ display: none;
226
+ }
227
+ }
228
+ .sh-menu-item-icon {
229
+ margin-right: 0;
230
+ margin-bottom: 3px;
231
+ flex: 1;
232
+ }
233
+ .sh-menu-item-title {
234
+ min-width: 100%;
235
+ }
236
+ }
237
+ }
238
+ .sh-menu-group {
239
+ position: relative;
240
+ &.is__expand {
241
+ background: $expandBgColor;
242
+ & > .sh-menu-item {
243
+ color: $textActive;
244
+ .sh-menu-item-arrow {
245
+ transform: rotate(90deg);
246
+ transform-origin: center;
247
+ }
248
+ }
249
+ }
250
+ &.is__active {
251
+ & > .sh-menu-item {
252
+ color: $textActive;
253
+ }
254
+ }
255
+ & > .sh-menu-group-dropdown,
256
+ & > .sh-menu-group-dropright {
257
+ position: fixed;
258
+ line-height: 1.5;
259
+ background-color: $mainBgColor;
260
+ box-shadow: var(--box-shadow);
261
+ overflow: auto;
262
+ z-index: 1000;
263
+ }
264
+ }
265
+ .sh-menu-item {
266
+ padding: 10px 12px;
267
+ display: flex;
268
+ align-items: center;
269
+ justify-content: flex-start;
270
+ cursor: pointer;
271
+ position: relative;
272
+ user-select: none;
273
+ color: $textColor;
274
+ text-align: left;
275
+ &:hover {
276
+ color: $textActive;
277
+ }
278
+ &.sh-menu-item-active {
279
+ color: $textActive;
280
+ background: var(--primary-weak-color);
281
+ &:after {
282
+ width: 3px;
283
+ content: '';
284
+ position: absolute;
285
+ top: 0;
286
+ right: 0;
287
+ height: 100%;
288
+ background: var(--vxe-primary-color);
289
+ }
290
+ }
291
+ .sh-menu-item-icon {
292
+ margin-right: 8px;
293
+ }
294
+ .sh-menu-item-title {
295
+ flex: 1;
296
+ white-space: nowrap;
297
+ }
298
+ .sh-menu-item-arrow {
299
+ margin-left: 5px;
300
+ transition: 0.1s all ease-in-out;
301
+ }
302
+ }
303
+ }
304
+ </style>
@@ -0,0 +1,122 @@
1
+ <template>
2
+ <div v-if="showChildren(menuItem)" class="sh-menu-group" :class="groupClass">
3
+ <menuItemContent ref="groupItem" :menu-item="menuItem" :menu-level="menuLevel" :arrow="isArrow" @click="onMenuExpand(!expand)" />
4
+ <div v-show="expand" ref="groupList" class="sh-menu-group-list" :class="groupListClass" :style="groupListStyle">
5
+ <template v-for="(item, index) in menuItem.children" :key="`sh-menu-${menuLevel}-${index}`">
6
+ <menuGroupContent :menu-item="item" :menu-level="menuNextLevel" />
7
+ </template>
8
+ </div>
9
+ </div>
10
+ <template v-else>
11
+ <menuItemContent :menu-item="menuItem" :menu-level="menuLevel" @click.stop="onMenuClick" />
12
+ </template>
13
+ </template>
14
+
15
+ <script>
16
+ import menuItemContent from './menu-item-content.vue'
17
+ export default {
18
+ name: 'MenuGroupContent',
19
+ components: {
20
+ menuItemContent
21
+ },
22
+ inject: {
23
+ MenuInstance: {
24
+ default: null
25
+ }
26
+ },
27
+ props: {
28
+ menuLevel: {
29
+ type: Number,
30
+ default: 0
31
+ },
32
+ menuItem: {
33
+ type: Object,
34
+ default() {
35
+ return {}
36
+ }
37
+ }
38
+ },
39
+ data() {
40
+ return {
41
+ expand: false,
42
+ groupListStyle: {}
43
+ }
44
+ },
45
+ computed: {
46
+ menuNextLevel() {
47
+ return this.menuLevel + 1
48
+ },
49
+ isArrow() {
50
+ return this.MenuInstance.collapsed ? !!this.menuLevel : true
51
+ },
52
+ groupClass() {
53
+ return {
54
+ is__level: !this.menuLevel,
55
+ is__active: this.MenuInstance.activeNames.includes(this.menuItem.name),
56
+ is__expand: this.expand
57
+ }
58
+ },
59
+ groupListClass() {
60
+ const { mode, collapsed } = this.MenuInstance
61
+ return {
62
+ 'sh-menu-group-dropdown': mode === 'horizontal',
63
+ 'sh-menu-group-dropright': mode === 'vertical' && collapsed
64
+ }
65
+ }
66
+ },
67
+ watch: {
68
+ 'MenuInstance.openedNames'(names) {
69
+ this.setMenuExpand()
70
+ }
71
+ },
72
+ mounted() {
73
+ this.setMenuExpand()
74
+ },
75
+ methods: {
76
+ setMenuExpand() {
77
+ let names = this.MenuInstance.openedNames
78
+ this.expand = names.includes(this.menuItem.name)
79
+ const { mode, collapsed } = this.MenuInstance
80
+ if (this.expand && this.$refs.groupItem && ((mode === 'vertical' && collapsed) || mode === 'horizontal')) {
81
+ this.$nextTick(() => {
82
+ const { left, right, top, bottom } = this.$refs.groupItem.$refs?.shMenuItem.getBoundingClientRect()
83
+ const { offsetHeight, offsetWidth } = this.$refs.groupList
84
+ const winWidth = window.innerWidth
85
+ const winHeight = window.innerHeight
86
+ if (mode === 'vertical') {
87
+ let groupStyle = { left: `${right}px` }
88
+ if (offsetHeight >= winHeight) {
89
+ groupStyle.top = '10px'
90
+ groupStyle.bottom = '10px'
91
+ } else if (top + offsetHeight >= winHeight) {
92
+ groupStyle.bottom = '10px'
93
+ } else {
94
+ groupStyle.top = `${top}px`
95
+ }
96
+ this.groupListStyle = groupStyle
97
+ } else {
98
+ let groupStyle = { top: `${this.menuLevel ? top : bottom}px` }
99
+ if (right + offsetWidth >= winWidth) {
100
+ groupStyle.right = '10px'
101
+ } else {
102
+ groupStyle.left = `${this.menuLevel ? right : left}px`
103
+ }
104
+ this.groupListStyle = groupStyle
105
+ }
106
+ })
107
+ }
108
+ },
109
+ showChildren(item) {
110
+ return item.children && item.children.length > 0
111
+ },
112
+ onMenuClick() {
113
+ this.MenuInstance.onMenuSelect(this.menuItem)
114
+ },
115
+ onMenuExpand(value) {
116
+ this.MenuInstance.onMenuExpand(value, this.menuItem)
117
+ }
118
+ }
119
+ }
120
+ </script>
121
+
122
+ <style scoped></style>
@@ -0,0 +1,61 @@
1
+ <template>
2
+ <div ref="shMenuItem" class="sh-menu-item" :class="itemClass" :style="itemStyle">
3
+ <sh-icon v-if="iconType" class="sh-menu-item-icon" :type="iconType"></sh-icon>
4
+ <span class="sh-menu-item-title">{{ formatTitle(menuItem) }}</span>
5
+ <sh-icon v-if="arrow" class="sh-menu-item-arrow" type="ios-arrow-forward"></sh-icon>
6
+ </div>
7
+ </template>
8
+
9
+ <script>
10
+ export default {
11
+ name: 'MenuItemBox',
12
+ inject: {
13
+ MenuInstance: {
14
+ default: null
15
+ }
16
+ },
17
+ props: {
18
+ arrow: Boolean,
19
+ menuLevel: {
20
+ type: Number
21
+ },
22
+ menuItem: {
23
+ type: Object,
24
+ default() {
25
+ return {}
26
+ }
27
+ }
28
+ },
29
+ computed: {
30
+ defaultIcon() {
31
+ if (!this.menuLevel || this.menuLevel < 2) return 'md-folder'
32
+ else if (this.menuLevel === 2) return 'md-bookmark'
33
+ else return ''
34
+ },
35
+ iconType() {
36
+ return this.menuItem.meta?.icon || this.menuItem.icon || this.defaultIcon
37
+ },
38
+ itemClass() {
39
+ return {
40
+ 'sh-menu-item-level': !this.menuLevel,
41
+ 'sh-menu-item-active': this.MenuInstance.activeName === this.menuItem.name
42
+ }
43
+ },
44
+ itemStyle() {
45
+ let result = {}
46
+ const { mode, collapsed, indent } = this.MenuInstance
47
+ if (mode === 'vertical' && !collapsed && this.menuLevel) {
48
+ result.paddingLeft = `${indent * this.menuLevel}px`
49
+ }
50
+ return result
51
+ },
52
+ itemTitle() {
53
+ const { labelField, labelFormat } = this.MenuInstance
54
+ return labelFormat ? labelFormat(this.menuItem) : this.$vUtils.get(this.menuItem, labelField)
55
+ }
56
+ },
57
+ methods: {}
58
+ }
59
+ </script>
60
+
61
+ <style scoped></style>
@@ -180,6 +180,7 @@ export default {
180
180
  justify-content: space-between;
181
181
  align-items: center;
182
182
  flex-wrap: wrap;
183
+ width: 100%;
183
184
  > div {
184
185
  width: 47%;
185
186
  display: inline-flex;
@@ -1,19 +1,159 @@
1
- import elementResizeDetectorMaker from 'element-resize-detector'
1
+ /**
2
+ * 是否是IE浏览器的判断
3
+ * @function
4
+ * @return {Boolean} 是否IE浏览器的判断结果
5
+ */
6
+ function isIE() {
7
+ let _isIE = false
8
+ if (typeof navigator !== 'undefined') {
9
+ _isIE = navigator.userAgent.match(/Trident/) || navigator.userAgent.match(/Edge/)
10
+ }
11
+ return _isIE
12
+ }
13
+
14
+ var lastTime = 0
15
+ var vendors = ['ms', 'moz', 'webkit', 'o']
16
+ if (typeof window === 'undefined') {
17
+ global.window = {}
18
+ }
19
+ for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
20
+ window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']
21
+ window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame']
22
+ }
23
+
24
+ if (!window.requestAnimationFrame) {
25
+ window.requestAnimationFrame = function (callback, element) {
26
+ var currTime = new Date().getTime()
27
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime))
28
+ var id = window.setTimeout(function () {
29
+ callback(currTime + timeToCall)
30
+ }, timeToCall)
31
+ lastTime = currTime + timeToCall
32
+ return id
33
+ }
34
+ }
35
+
36
+ if (!window.cancelAnimationFrame) {
37
+ window.cancelAnimationFrame = function (id) {
38
+ clearTimeout(id)
39
+ }
40
+ }
41
+
42
+ /**
43
+ * requestAnimationFrame的兼容处理
44
+ */
45
+ const $requestAnimationFrame = window.requestAnimationFrame
46
+
47
+ /**
48
+ * cancelAnimationFrame的兼容处理
49
+ */
50
+ const $cancelAnimationFrame = window.cancelAnimationFrame
51
+
52
+ /**
53
+ * resize处理器,此处回调元素v-resize的方法
54
+ * @param event {Event} resizeTrigge的resize事件传递,来自{@link registereResizeHandler}方法中产生的事件源
55
+ * @function
56
+ */
57
+ function resizeHandler(event) {
58
+ event.__currentTarget__ = this.__container__
59
+ this.__resize__handler__.call(
60
+ this,
61
+ {
62
+ width: this.offsetWidth,
63
+ height: this.offsetHeight
64
+ },
65
+ event
66
+ )
67
+ }
68
+
69
+ /**
70
+ * 优化resize监听
71
+ * @param event {Event} resizeTrigge的resize事件传递,来自{@link registereResizeHandler}方法中产生的事件源
72
+ * @function
73
+ */
74
+ function resizeTriggerListener(event) {
75
+ const _resizeTrigger = event.currentTarget || event.srcElement
76
+ if (_resizeTrigger.__requestAnimationFrameID__) {
77
+ $cancelAnimationFrame(_resizeTrigger.__requestAnimationFrameID__)
78
+ }
79
+ _resizeTrigger.__requestAnimationFrameID__ = $requestAnimationFrame(resizeHandler.bind(this, event))
80
+ }
81
+
82
+ /**
83
+ * 注册resize处理方法
84
+ * @function
85
+ */
86
+ function registereResizeHandler() {
87
+ if (document.attachEvent) {
88
+ this.__container__.attachEvent('onresize', resizeHandler.bind(this))
89
+ } else {
90
+ this.contentDocument.defaultView.addEventListener('resize', resizeTriggerListener.bind(this))
91
+ }
92
+ }
93
+
94
+ /**
95
+ * 创建resize真正的触发器
96
+ * @function
97
+ */
98
+ function createResizeTrigger() {
99
+ const object = document.createElement('object')
100
+ object.setAttribute('aria-hidden', 'true')
101
+ object.setAttribute('tabindex', -1)
102
+ const objectStyle = `
103
+ display: block !important;
104
+ position: absolute !important;
105
+ top: 0 !important;
106
+ left: 0 !important;
107
+ width: 100% !important;
108
+ height: 100% !important;
109
+ overflow: hidden !important;
110
+ pointer-events: none !important;
111
+ z-index: -1 !important;
112
+ opacity: 0 !important;
113
+ `
114
+ object.setAttribute('style', objectStyle)
115
+ object.type = 'text/html'
116
+ return object
117
+ }
2
118
 
3
119
  export default {
4
- // 使用 bind,会在初始化时调用两次handler
5
- mounted(el, binding) {
6
- function resizeHandler(e) {
7
- binding.value(e)
120
+ beforeMount(el, binding, vnode, oldVnode) {
121
+ // 获得真正的触发器
122
+ el.__resizeTrigger__ = createResizeTrigger()
123
+ el.__resizeTrigger__.__container__ = el
124
+ el.__resizeTrigger__.__resize__handler__ = binding.value
125
+ el.__resizeTrigger__.onload = registereResizeHandler
126
+ // 将真正的触发器作为子元素添加到当前元素
127
+ const _isIE = isIE()
128
+ _isIE && el.appendChild(el.__resizeTrigger__)
129
+ el.__resizeTrigger__.data = 'about:blank'
130
+ !_isIE && el.appendChild(el.__resizeTrigger__)
131
+ },
132
+ mounted(el, binding, vnode, oldVnode) {
133
+ if (getComputedStyle(el).position === 'static') {
134
+ el.style.setProperty('position', 'relative', 'important')
8
135
  }
9
- el.__resizeHandler__ = resizeHandler
10
- el.__observer__ = elementResizeDetectorMaker()
11
- el.__observer__.listenTo(el, resizeHandler)
12
136
  },
13
- updated() {},
14
- unmounted(el, binding) {
15
- el.__observer__.removeListener(el, el.__resizeHandler__)
16
- delete el.__resizeHandler__
17
- delete el.__observer__
137
+ updated(el, binding, vnode, oldVnode) {
138
+ var inserted = false
139
+ for (var i = 0, length = el.children.length; i < length; i++) {
140
+ if (el.children[i] === el.__resizeTrigger__) {
141
+ inserted = true
142
+ }
143
+ }
144
+ if (!inserted) {
145
+ var _isIE = isIE()
146
+ _isIE && el.appendChild(el.__resizeTrigger__)
147
+ el.__resizeTrigger__.data = 'about:blank'
148
+ !_isIE && el.appendChild(el.__resizeTrigger__)
149
+ }
150
+ },
151
+ unmounted(el, binding, vnode, oldVnode) {
152
+ if (document.attachEvent) {
153
+ el.detachEvent('onresize', resizeHandler)
154
+ } else if (el.__resizeTrigger__ && el.__resizeTrigger__.contentDocument) {
155
+ el.__resizeTrigger__.contentDocument.defaultView.removeEventListener('resize', resizeTriggerListener)
156
+ el.__resizeTrigger__ = !el.removeChild(el.__resizeTrigger__)
157
+ }
18
158
  }
19
159
  }
@@ -1,40 +0,0 @@
1
- <template>
2
- <div class="sh-date">
3
- <div class="sh-date-input" @click="inputClick">{{ dataValue }}</div>
4
- <div class="sh-date-drop">
5
- <vxe-input ref="inputA" v-model="value1" type="date"></vxe-input>
6
- <vxe-input ref="inputB" v-model="value2" type="date"></vxe-input>
7
- </div>
8
- </div>
9
- </template>
10
-
11
- <script>
12
- export default {
13
- name: 'ShDate',
14
- emits: ['update:modelValue'],
15
- data() {
16
- return {
17
- dataValue: '',
18
- value1: '',
19
- value2: ''
20
- }
21
- },
22
- computed: {},
23
- methods: {
24
- inputClick() {
25
- this.$refs.inputA.focus()
26
- this.$refs.inputB.focus()
27
- }
28
- }
29
- }
30
- </script>
31
-
32
- <style scoped lang="scss">
33
- .sh-date {
34
- &-input {
35
- width: 300px;
36
- height: 50px;
37
- border: 1px solid #ccc;
38
- }
39
- }
40
- </style>