@mpxjs/webpack-plugin 2.9.0-beta.1 → 2.9.0-beta.3

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.
Files changed (46) hide show
  1. package/lib/dependencies/CommonJsExtractDependency.js +51 -0
  2. package/lib/extractor.js +1 -0
  3. package/lib/helpers.js +9 -1
  4. package/lib/index.js +103 -21
  5. package/lib/json-compiler/helper.js +20 -7
  6. package/lib/json-compiler/index.js +48 -19
  7. package/lib/loader.js +1 -1
  8. package/lib/native-loader.js +18 -6
  9. package/lib/platform/json/wx/index.js +44 -2
  10. package/lib/platform/run-rules.js +2 -1
  11. package/lib/platform/template/normalize-component-rules.js +2 -0
  12. package/lib/platform/template/wx/component-config/fix-html-tag.js +17 -0
  13. package/lib/platform/template/wx/component-config/index.js +2 -0
  14. package/lib/platform/template/wx/index.js +45 -14
  15. package/lib/runtime/base.styl +9 -6
  16. package/lib/runtime/components/web/filterTag.js +9 -30
  17. package/lib/runtime/components/web/getInnerListeners.js +2 -14
  18. package/lib/runtime/components/web/mpx-keep-alive.vue +8 -17
  19. package/lib/runtime/components/web/mpx-movable-view.vue +28 -9
  20. package/lib/runtime/components/web/mpx-picker-view.vue +1 -1
  21. package/lib/runtime/components/web/mpx-scroll-view.vue +21 -10
  22. package/lib/runtime/components/web/mpx-video.vue +123 -89
  23. package/lib/runtime/components/web/mpx-web-view.vue +119 -81
  24. package/lib/runtime/components/wx/default-page.mpx +27 -0
  25. package/lib/runtime/optionProcessor.js +27 -20
  26. package/lib/style-compiler/index.js +5 -1
  27. package/lib/template-compiler/bind-this.js +248 -48
  28. package/lib/template-compiler/compiler.js +69 -109
  29. package/lib/template-compiler/index.js +16 -1
  30. package/lib/utils/dom-tag-config.js +101 -0
  31. package/lib/utils/make-map.js +12 -0
  32. package/lib/utils/string.js +7 -1
  33. package/lib/utils/ts-loader-watch-run-loader-filter.js +1 -1
  34. package/lib/web/processJSON.js +35 -0
  35. package/lib/web/processMainScript.js +1 -1
  36. package/lib/web/processTemplate.js +18 -35
  37. package/lib/web/script-helper.js +5 -2
  38. package/package.json +4 -4
  39. package/lib/json-compiler/default-page.mpx +0 -3
  40. package/lib/template-compiler/preprocessor.js +0 -29
  41. package/lib/wxss/compile-exports.js +0 -52
  42. package/lib/wxss/createResolver.js +0 -36
  43. package/lib/wxss/css-base.js +0 -79
  44. package/lib/wxss/getLocalIdent.js +0 -25
  45. package/lib/wxss/localsLoader.js +0 -44
  46. package/lib/wxss/processCss.js +0 -274
@@ -1,20 +1,14 @@
1
1
  <template>
2
2
  <video
3
3
  ref="_mpx_video_ref"
4
- :class="classList"
5
- :src="src"
6
- :controls="showControlsTool"
7
- :autoplay="autoplay"
8
- :loop="loop"
9
- :muted="mutedCopy"
10
- :poster="poster"
4
+ class="video-js"
11
5
  v-bind="playsinlineAttr"
12
- >
13
- </video>
14
- </template>
15
-
16
- <script>
6
+ ></video>
7
+ </template>
8
+ <script>
17
9
  import { inheritEvent } from './getInnerListeners'
10
+ import videojs from 'video.js'
11
+ import 'video.js/dist/video-js.min.css'
18
12
 
19
13
  export default {
20
14
  name: 'mpx-video',
@@ -54,7 +48,7 @@
54
48
  type: Boolean,
55
49
  default: false
56
50
  },
57
- initialTime: { // done
51
+ initialTime: {
58
52
  type: Number,
59
53
  default: 0
60
54
  },
@@ -63,6 +57,10 @@
63
57
  type: Boolean,
64
58
  default: true
65
59
  },
60
+ showBottomProgress: { // done
61
+ type: Boolean,
62
+ default: true
63
+ },
66
64
  showFullscreenBtn: { // done
67
65
  type: Boolean,
68
66
  default: true
@@ -125,130 +123,166 @@
125
123
  default: false
126
124
  },
127
125
  playsinline: {
128
- type: Boolean,
129
- default: true
130
- }
126
+ type: Boolean,
127
+ default: true
128
+ }
131
129
  },
132
- computed: {
133
- playsinlineAttr () {
134
- if (!this.playsinline) return {}
135
- return {
136
- 'webkit-playsinline': true,
137
- 'playsinline': true,
138
- 'x5-playsinline': true
139
- }
130
+ data () {
131
+ return {
140
132
  }
141
133
  },
142
- data () {
134
+ computed: {
135
+ playsinlineAttr () {
136
+ if (!this.playsinline) return {}
143
137
  return {
144
- showControlsTool: this.controls,
145
- mutedCopy: this.muted,
146
- classList: ''
138
+ 'webkit-playsinline': true,
139
+ 'playsinline': true,
140
+ 'x5-playsinline': true,
141
+ 'x5-video-orientation': 'landscape|portrait'
142
+ }
143
+ }
144
+ },
145
+ watch: {
146
+ muted: function (val) {
147
+ this._player?.muted(val)
148
+ },
149
+ controls: function (show) {
150
+ this.$emit('controlstoggle', inheritEvent('controlstoggle', {}, { show }))
147
151
  }
148
152
  },
149
153
  mounted () {
154
+ const videoNode = this.$refs['_mpx_video_ref']
155
+ this._player = videojs(videoNode, {
156
+ controls: true,
157
+ sources:[
158
+ {
159
+ src: this.src
160
+ }
161
+ ],
162
+ autoplay: this.autoplay,
163
+ loop: this.loop,
164
+ /**
165
+ log 若 controls 属性值为 false 则设置 poster 无效
166
+ */
167
+ poster: this.controls ? this.poster : ''
168
+ }, function () {
169
+ })
170
+ this.initPlayer()
150
171
  this.initStyle()
151
172
  this.initEvent()
152
173
  },
153
174
  methods: {
154
- initStyle () {
155
- const videoNode = this.$refs['_mpx_video_ref']
175
+ initPlayer () {
176
+ this._player.muted(this.muted)
156
177
  if (this.initialTime) {
157
- videoNode.currentTime = this.initialTime
178
+ this._player.currentTime(this.initialTime)
158
179
  }
159
- if (this.autoplay) { // log 解决autoplay无法自动播放问题
160
- this.mutedCopy = true
161
- }
162
- if (!this.showProgress) this.classList += ' mpx-no-show_progress'
163
- if (!this.showFullscreenBtn) this.classList += ' mpx-no-show_fullscreen_btn'
164
- if (!this.showPlayBtn) this.classList += ' mpx-no-show_play_btn'
165
- if (!this.showCenterPlayBtn) this.classList += ' mpx-no-show_center_play_btn'
166
- if (!this.showMuteBtn) this.classList += ' mpx-no-show_mute_btn'
167
180
  },
168
- initEvent () {
169
- const videoNode = this.$refs['_mpx_video_ref']
181
+ initStyle () {
182
+ if (!this.controls) this._player.el_.classList.add('mpx-no-show_controls')
183
+
184
+ if (!this.showBottomProgress) this._player.el_.classList.add('mpx-no-show_progress')
185
+
186
+ /**
187
+ showProgress若不设置,宽度大于240时才会显示
188
+ */
189
+ if (!this.showProgress || (this._player.el_.offsetWidth < 240 && this.showProgress)) this._player.el_.classList.add('mpx-no-show_progress')
190
+
191
+ if (!this.showFullscreenBtn) this._player.el_.classList.add('mpx-no-show_fullscreen_btn')
192
+
193
+ if (!this.showPlayBtn) this._player.el_.classList.add('mpx-no-show_play_btn')
194
+
195
+ if (!this.showCenterPlayBtn) this._player.el_.classList.add('mpx-no-show_center_play_btn')
170
196
 
171
- videoNode.addEventListener('play', (e) => {
197
+ if (!this.showMuteBtn) this._player.el_.classList.add('mpx-no-show_mute_btn')
198
+ },
199
+ initEvent () {
200
+ this._player.on('play', (e) => {
172
201
  this.$emit('play', inheritEvent('play', e, {}))
173
202
  })
174
203
 
175
- videoNode.addEventListener('pause', (e) => {
204
+ this._player.on('pause', (e) => {
176
205
  this.$emit('pause', inheritEvent('pause', e, {}))
177
206
  })
178
207
 
179
- videoNode.addEventListener('ended', (e) => {
208
+ this._player.on('ended', (e) => {
180
209
  this.$emit('ended', inheritEvent('ended', e, {}))
181
210
  })
182
211
 
183
- videoNode.addEventListener('timeupdate', (e) => {
184
- const eNode = e.target
185
- this.$emit('timeupdate', inheritEvent('timeupdate', e, { currentTime: eNode.currentTime, duration: eNode.duration }))
212
+ this._player.on('timeupdate', (e) => {
213
+ this.$emit('timeupdate', inheritEvent('timeupdate', e, {}))
186
214
  })
187
215
 
188
- videoNode.addEventListener('error', (e) => {
216
+ this._player.on('error', (e) => {
189
217
  this.$emit('error', inheritEvent('error', e, {}))
190
218
  })
191
219
 
192
- videoNode.addEventListener('waiting', (e) => {
220
+ this._player.on('waiting', (e) => {
193
221
  this.$emit('waiting', inheritEvent('waiting', e, {}))
194
222
  })
195
-
196
- videoNode.addEventListener('loadedmetadata', (e) => {
197
- const eNode = e.target
198
- this.$emit('loadedmetadata', inheritEvent('loadedmetadata', e, { width: eNode.videoWidth, height: eNode.videoHeight, duration: eNode.duration }))
223
+ this._player.on('loadedmetadata', (e) => {
224
+ this.$emit('loadedmetadata', inheritEvent('loadedmetadata', e, {}))
199
225
  })
200
226
 
201
- videoNode.addEventListener('progress', (e) => {
227
+ this._player.on('progress', (e) => {
202
228
  const eNode = e.target
203
229
  const buffered = (eNode?.buffered?.end(0)) / (eNode?.duration)
204
230
  this.$emit('progress', inheritEvent('progress', e, { buffered: buffered * 100 }))
205
231
  })
206
232
 
207
- videoNode.addEventListener('seeked', (e) => {
233
+ this._player.on('seeked', (e) => {
208
234
  const eNode = e.target
209
- this.$emit('seekcomplete', inheritEvent('seekcomplete', e, { position: eNode.currentTime }))
235
+ this.$emit('seekcomplete', inheritEvent('seekcomplete', e, { position: eNode.currentTime }))
210
236
  })
211
-
212
- videoNode.addEventListener('fullscreenchange', (e) => {
213
- // TODO direction
214
- if (document.isFullScreen) {
215
- this.$emit('fullscreenchange', inheritEvent('fullscreenchange', e, { fullScreen: true }))
216
- } else {
217
- this.$emit('fullscreenchange', inheritEvent('fullscreenchange', e, { fullScreen: false }))
237
+ this._player.on('fullscreenchange', (e) => {
238
+ if (!this._player.paused()) {
239
+ // hack: 解决退出全屏自动暂停
240
+ setTimeout(() => {
241
+ this._player.play()
242
+ }, 500)
218
243
  }
244
+ this.$emit('fullscreenchange', inheritEvent('fullscreenchange', e, { fullScreen: this._player.isFullscreen() }))
219
245
  })
220
246
 
221
- videoNode.addEventListener('enterpictureinpicture', (e) => {
247
+ this._player.on('enterpictureinpicture', (e) => {
222
248
  this.$emit('enterpictureinpicture', inheritEvent('enterpictureinpicture', e, {}))
223
249
  })
224
250
 
225
- videoNode.addEventListener('leavepictureinpicture', (e) => {
251
+ this._player.on('leavepictureinpicture', (e) => {
226
252
  this.$emit('leavepictureinpicture', inheritEvent('leavepictureinpicture', e, {}))
227
253
  })
254
+
228
255
  }
229
256
  }
230
257
  }
231
- </script>
232
-
233
- <style lang="stylus">
234
- .mpx-video-container
235
- .mpx-no-show_progress
236
- &::-webkit-media-controls-timeline
237
- display none !important
238
-
239
- .mpx-no-show_fullscreen_btn
240
- &::-webkit-media-controls-fullscreen-button
241
- display none !important
242
-
243
- .mpx-no-show_play_btn
244
- &::-webkit-media-controls-play-button
245
- display none !important
246
-
247
- .mpx-no-show_center_play_btn
248
- &::-webkit-media-controls-start-playback-button
249
- display none !important
250
-
251
- .mpx-no-show_mute_btn
252
- &::-webkit-media-controls-mute-button
253
- display none !important
254
- </style>
258
+ </script>
259
+
260
+ <style lang="stylus">
261
+
262
+ .vjs-chapters-button
263
+ display: none !important
264
+
265
+ .mpx-no-show_controls
266
+ .vjs-control-bar
267
+ display none !important
268
+
269
+ .mpx-no-show_progress
270
+ .vjs-progress-control
271
+ display none !important
272
+
273
+ .mpx-no-show_fullscreen_btn
274
+ .vjs-fullscreen-control
275
+ display none !important
276
+
277
+ .mpx-no-show_play_btn
278
+ .vjs-play-control
279
+ display none !important
280
+
281
+ .mpx-no-show_center_play_btn
282
+ .vjs-big-play-button
283
+ display none !important
284
+
285
+ .mpx-no-show_mute_btn
286
+ .vjs-mute-control
287
+ display none !important
288
+ </style>
@@ -1,107 +1,77 @@
1
1
  <template>
2
- <iframe ref="mpxIframe" class="mpx-iframe" :src="src"></iframe>
2
+ <iframe ref="mpxIframe" class="mpx-iframe" :src="currentUrl" :key="currentUrl"></iframe>
3
3
  </template>
4
4
 
5
5
  <script>
6
6
  import { getCustomEvent } from './getInnerListeners'
7
- import { redirectTo, navigateTo, navigateBack, reLaunch, switchTab} from '@mpxjs/api-proxy/src/web/api/index'
7
+ import { redirectTo, navigateTo, navigateBack, reLaunch, switchTab } from '@mpxjs/api-proxy/src/web/api/index'
8
8
 
9
9
  const eventLoad = 'load'
10
10
  const eventError = 'error'
11
11
  const eventMessage = 'message'
12
+ const mpx = global.__mpx
12
13
  export default {
13
- data: function () {
14
- return {
15
- origin: '',
16
- messageList: [],
17
- Loaded: false,
18
- isActived: false,
19
- mpxIframe: null,
20
- isPostMessage: false
21
- }
22
- },
23
14
  props: {
24
15
  src: {
25
16
  type: String
26
17
  }
27
18
  },
28
19
  computed: {
29
- mainDomain () {
30
- let domain
31
- const src = location.href
32
- let index = src.indexOf('?')
33
- if (index > -1) {
34
- domain = src.substr(0, index)
35
- return domain
36
- }
37
- domain = src.split('/')
38
- if (domain[2]) {
39
- domain = domain[0] + '//' + domain[2]
20
+ host () {
21
+ let host = this.src.split('/')
22
+ if (host[2]) {
23
+ host = host[0] + '//' + host[2]
40
24
  } else {
41
- domain = ''
25
+ host = ''
26
+ }
27
+ return host
28
+ },
29
+ currentUrl () {
30
+ if (!this.src) return ''
31
+ const hostValidate = this.hostValidate(this.host)
32
+ if (!hostValidate) {
33
+ console.error('访问页面域名不符合domainWhiteLists白名单配置,请确认是否正确配置该域名白名单')
34
+ return ''
35
+ }
36
+ return this.src
37
+ },
38
+ loadData () {
39
+ return {
40
+ src: this.host,
41
+ fullUrl: this.src
42
42
  }
43
- return domain
44
43
  }
45
44
  },
46
- mounted () {
47
- setTimeout(() => {
48
- if (!this.Loaded) {
49
- const loadData = {
50
- src: this.src
45
+ watch: {
46
+ currentUrl: {
47
+ handler (value) {
48
+ if (!value) {
49
+ this.$emit(eventError, getCustomEvent(eventError, {
50
+ ...this.loadData,
51
+ errMsg: 'web-view load failed due to not in domain list'
52
+ }, this))
53
+ } else {
54
+ this.$nextTick(() => {
55
+ if (this.$refs.mpxIframe && this.mpxIframe != this.$refs.mpxIframe) {
56
+ this.mpxIframe = this.$refs.mpxIframe
57
+ this.mpxIframe.addEventListener('load', (event) => {
58
+ this.$emit(eventLoad, getCustomEvent(eventLoad, this.loadData, this))
59
+ })
60
+ }
61
+ })
51
62
  }
52
- this.$emit(eventError, getCustomEvent(eventError, loadData, this))
53
- }
54
- }, 1000)
55
- this.mpxIframe = this.$refs.mpxIframe
56
- this.mpxIframe.addEventListener('load', (event) => {
57
- event.currentTarget.contentWindow.postMessage(this.mainDomain, '*')
58
- })
59
- window.addEventListener('message', (event) => {
60
- const data = event.data
61
- const value = data.detail && data.detail.data && data.detail.data
62
- if (!this.isActived) {
63
- return
64
- }
65
- switch (data.type) {
66
- case eventMessage:
67
- this.isPostMessage = true
68
- this.messageList.push(value.data)
69
- break
70
- case 'navigateTo':
71
- this.isActived = false
72
- navigateTo(value)
73
- break
74
- case 'navigateBack':
75
- this.isActived = false
76
- value ? navigateBack(value) : navigateBack()
77
- break
78
- case 'redirectTo':
79
- this.isActived = false
80
- redirectTo(value)
81
- break
82
- case 'switchTab':
83
- this.isActived = false
84
- switchTab(value)
85
- break
86
- case 'reLaunch':
87
- this.isActived = false
88
- reLaunch(value)
89
- break
90
- case 'load':
91
- this.Loaded = true
92
- const loadData = {
93
- src: this.src
94
- }
95
- this.$emit(eventLoad, getCustomEvent(eventLoad, loadData, this))
96
- }
97
- })
63
+ },
64
+ immediate: true
65
+ }
98
66
  },
99
- activated () {
100
- this.isActived = true
101
- this.isPostMessage = false
67
+ beforeCreate () {
68
+ this.messageList = []
69
+ },
70
+ mounted () {
71
+ window.addEventListener('message', this.messageCallback)
102
72
  },
103
73
  deactivated () {
104
- if (!this.isPostMessage) {
74
+ if (!this.messageList.length) {
105
75
  return
106
76
  }
107
77
  let data = {
@@ -111,7 +81,8 @@
111
81
  this.$emit(eventMessage, getCustomEvent(eventMessage, data, this))
112
82
  },
113
83
  destroyed () {
114
- if (!this.isPostMessage) {
84
+ window.removeEventListener('message', this.messageCallback)
85
+ if (!this.messageList.length) {
115
86
  return
116
87
  }
117
88
  let data = {
@@ -119,6 +90,73 @@
119
90
  data: this.messageList
120
91
  }
121
92
  this.$emit(eventMessage, getCustomEvent(eventMessage, data, this))
93
+ },
94
+ methods: {
95
+ messageCallback (event) {
96
+ const hostValidate = this.hostValidate(event.origin)
97
+ const data = event.data
98
+ const value = data.payload
99
+ if (!hostValidate) {
100
+ return
101
+ }
102
+ let asyncCallback = null
103
+ switch (data.type) {
104
+ case 'postMessage':
105
+ this.messageList.push(value)
106
+ asyncCallback = Promise.resolve({
107
+ errMsg: 'invokeWebappApi:ok'
108
+ })
109
+ break
110
+ case 'navigateTo':
111
+ asyncCallback = navigateTo(value)
112
+ break
113
+ case 'navigateBack':
114
+ asyncCallback = value ? navigateBack(value) : navigateBack()
115
+ break
116
+ case 'redirectTo':
117
+ asyncCallback = redirectTo(value)
118
+ break
119
+ case 'switchTab':
120
+ asyncCallback = switchTab(value)
121
+ break
122
+ case 'reLaunch':
123
+ asyncCallback = reLaunch(value)
124
+ break
125
+ case 'getLocation':
126
+ const getLocation = mpx.config.webviewConfig.apiImplementations && mpx.config.webviewConfig.apiImplementations.getLocation
127
+ if (getLocation) {
128
+ asyncCallback = getLocation()
129
+ } else {
130
+ asyncCallback = Promise.reject({
131
+ errMsg: '未在apiImplementations中配置getLocation方法'
132
+ })
133
+ }
134
+ break
135
+ }
136
+ asyncCallback && asyncCallback.then((res) => {
137
+ this.mpxIframe && this.mpxIframe.contentWindow && this.mpxIframe.contentWindow.postMessage && this.mpxIframe.contentWindow.postMessage({
138
+ type: data.type,
139
+ callbackId: data.callbackId,
140
+ result: res
141
+ }, event.origin)
142
+ }).catch((error) => {
143
+ this.mpxIframe && this.mpxIframe.contentWindow && this.mpxIframe.contentWindow.postMessage && this.mpxIframe.contentWindow.postMessage({
144
+ type: data.type,
145
+ callbackId: data.callbackId,
146
+ error
147
+ }, event.origin)
148
+ })
149
+ },
150
+ hostValidate (host) {
151
+ const hostWhitelists = mpx.config.webviewConfig && mpx.config.webviewConfig.hostWhitelists || []
152
+ if (hostWhitelists.length) {
153
+ return hostWhitelists.some((item) => {
154
+ return host.endsWith(item)
155
+ })
156
+ } else {
157
+ return true
158
+ }
159
+ }
122
160
  }
123
161
  }
124
162
  </script>
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <view>局部构建兜底页面</view>
3
+ <view>当前路由:{{currentRoute}}</view>
4
+ </template>
5
+
6
+ <script>
7
+ import { onLoad } from '@mpxjs/core'
8
+ import { createPage } from '@mpxjs/core'
9
+
10
+ createPage({
11
+ data() {
12
+ return {
13
+ currentRoute: '',
14
+ }
15
+ },
16
+ onLoad() {
17
+ this.getPagePath()
18
+ },
19
+ methods: {
20
+ getPagePath() {
21
+ const pages = getCurrentPages() || []
22
+ const currPage = pages[pages.length - 1]
23
+ this.currentRoute = currPage && currPage.route || ''
24
+ },
25
+ }
26
+ })
27
+ </script>
@@ -3,7 +3,19 @@ import { isBrowser } from './env'
3
3
  import transRpxStyle from './transRpxStyle'
4
4
  import animation from './animation'
5
5
 
6
- export default function processComponentOption ({ option, ctorType, outputPath, pageConfig, componentsMap, componentGenerics, genericsInfo, mixin, hasApp }) {
6
+ export default function processComponentOption (
7
+ {
8
+ option,
9
+ ctorType,
10
+ outputPath,
11
+ pageConfig,
12
+ componentsMap,
13
+ componentGenerics,
14
+ genericsInfo,
15
+ mixin,
16
+ hasApp
17
+ }
18
+ ) {
7
19
  // 局部注册页面和组件中依赖的组件
8
20
  for (const componentName in componentsMap) {
9
21
  if (hasOwn(componentsMap, componentName)) {
@@ -101,6 +113,8 @@ function createApp ({ componentsMap, Vue, pagesMap, firstPage, VueRouter, App, t
101
113
 
102
114
  Vue.filter('transRpxStyle', transRpxStyle)
103
115
 
116
+ Vue.config.ignoredElements = ['page']
117
+
104
118
  const routes = []
105
119
 
106
120
  for (const pagePath in pagesMap) {
@@ -128,6 +142,7 @@ function createApp ({ componentsMap, Vue, pagesMap, firstPage, VueRouter, App, t
128
142
  global.__mpxRouter.stack = []
129
143
  global.__mpxRouter.needCache = null
130
144
  global.__mpxRouter.needRemove = []
145
+ global.__mpxRouter.eventChannelMap = {}
131
146
  // 处理reLaunch中传递的url并非首页时的replace逻辑
132
147
  global.__mpxRouter.beforeEach(function (to, from, next) {
133
148
  let action = global.__mpxRouter.__mpxAction
@@ -166,24 +181,15 @@ function createApp ({ componentsMap, Vue, pagesMap, firstPage, VueRouter, App, t
166
181
  })
167
182
  }
168
183
  } else {
169
- let methods = ''
170
- switch (action.type) {
171
- case 'to':
172
- methods = 'navigateTo'
173
- break
174
- case 'redirect':
175
- methods = 'redirectTo'
176
- break
177
- case 'back':
178
- methods = 'navigateBack'
179
- break
180
- case 'reLaunch':
181
- methods = 'reLaunch'
182
- break
183
- default:
184
- methods = 'navigateTo'
184
+ const typeMethodMap = {
185
+ to: 'navigateTo',
186
+ redirect: 'redirectTo',
187
+ back: 'navigateBack',
188
+ switch: 'switchTab',
189
+ reLaunch: 'reLaunch'
185
190
  }
186
- throw new Error(`${methods}:fail page "${to.path}" is not found`)
191
+ const method = typeMethodMap[action.type]
192
+ throw new Error(`${method}:fail page "${to.path}" is not found`)
187
193
  }
188
194
  }
189
195
 
@@ -195,6 +201,7 @@ function createApp ({ componentsMap, Vue, pagesMap, firstPage, VueRouter, App, t
195
201
  case 'to':
196
202
  stack.push(insertItem)
197
203
  global.__mpxRouter.needCache = insertItem
204
+ if (action.eventChannel) global.__mpxRouter.eventChannelMap[to.path.slice(1)] = action.eventChannel
198
205
  break
199
206
  case 'back':
200
207
  global.__mpxRouter.needRemove = stack.splice(stack.length - action.delta, action.delta)
@@ -214,7 +221,7 @@ function createApp ({ componentsMap, Vue, pagesMap, firstPage, VueRouter, App, t
214
221
  // 将非tabBar页面remove
215
222
  let tabItem = null
216
223
  global.__mpxRouter.needRemove = stack.filter((item) => {
217
- if (tabBarMap[item.path.slice(1)]) {
224
+ if (tabBarMap[item.path.slice(1)] && !tabItem) {
218
225
  tabItem = item
219
226
  tabItem.path = to.path
220
227
  return false
@@ -235,7 +242,7 @@ function createApp ({ componentsMap, Vue, pagesMap, firstPage, VueRouter, App, t
235
242
  return next({
236
243
  path: action.path,
237
244
  query: {
238
- reLaunchCount: action.reLaunchCount
245
+ routeCount: action.routeCount
239
246
  },
240
247
  replace: true
241
248
  })
@@ -47,6 +47,10 @@ module.exports = function (css, map) {
47
47
  plugins.push(transSpecial({ id }))
48
48
  }
49
49
 
50
+ if (mode === 'web') {
51
+ plugins.push(transSpecial({ id }))
52
+ }
53
+
50
54
  plugins.push(pluginCondStrip({
51
55
  defs
52
56
  }))
@@ -85,7 +89,7 @@ module.exports = function (css, map) {
85
89
  .process(css, options)
86
90
  .then(result => {
87
91
  // ali环境添加全局样式抹平root差异
88
- if (mode === 'ali' && isApp) {
92
+ if ((mode === 'ali' || mode === 'web') && isApp) {
89
93
  result.css += `\n.${MPX_ROOT_VIEW} { display: initial }\n.${MPX_APP_MODULE_ID} { line-height: normal }`
90
94
  }
91
95