Skip to content

Commit ec466f0

Browse files
committed
update
1 parent 2819388 commit ec466f0

File tree

9 files changed

+344
-3
lines changed

9 files changed

+344
-3
lines changed

.editorconfig

+2-1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ ij_rust_spaces_around_assoc_type_binding = false
8383
# ij_editorconfig_spaces_around_assignment_operators = true
8484

8585
[{*.ats,*.cts,*.mts,*.ts}]
86+
indent_size = 2
8687
# ij_continuation_indent_size = 4
8788
# ij_typescript_align_imports = false
8889
# ij_typescript_align_multiline_array_initializer_expression = false
@@ -510,4 +511,4 @@ trim_trailing_whitespace = false
510511

511512
[*.{yml,yaml}]
512513
indent_style = space
513-
indent_size = 2
514+
indent_size = 2

crates/rs-tauri-vue/src/main.ts

+32-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import devtools from '@vue/devtools'
2-
import { createApp } from 'vue'
2+
import {createApp} from 'vue'
3+
import type {ComponentPublicInstance} from 'vue'
4+
import {router, routerHistory} from './router'
5+
import {globalState} from './store'
36
import App from './App.vue'
47

58
import './assets/main.postcss'
@@ -8,4 +11,31 @@ if (process.env.NODE_ENV === 'development') {
811
devtools.connect('http://localhost', 5001) // TODO X: 注意和vue devtool 调试工具的端口保持一致
912
}
1013

11-
createApp(App).mount('#app')
14+
15+
declare global {
16+
interface Window {
17+
// h: HTML5History
18+
h: typeof routerHistory
19+
r: typeof router
20+
// @ts-ignore
21+
vm: ComponentPublicInstance
22+
}
23+
}
24+
25+
// for testing purposes
26+
window.h = routerHistory
27+
window.r = router
28+
29+
const app = createApp(App)
30+
app.mixin({
31+
beforeRouteEnter() {
32+
console.log('mixin enter')
33+
},
34+
})
35+
36+
app.provide('state', globalState)
37+
38+
// todo x: 路由表
39+
app.use(router)
40+
41+
window.vm = app.mount('#app')

crates/rs-tauri-vue/src/router.ts

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import {createRouter, createWebHistory, RouterView} from 'vue-router'
2+
import Home from './views/Home.vue'
3+
4+
import NotFound from './views/NotFound.vue'
5+
6+
7+
const component = () => {
8+
console.log('fetching component')
9+
return import('./views/Generic.vue')
10+
}
11+
12+
13+
import LongView from './views/HomeView.vue'
14+
15+
16+
import {globalState} from './store'
17+
import {scrollWaiter} from './scrollWaiter'
18+
19+
20+
21+
let removeRoute: (() => void) | undefined
22+
23+
export const routerHistory = createWebHistory()
24+
export const router = createRouter({
25+
history: routerHistory,
26+
strict: true,
27+
routes: [
28+
{path: '/home', redirect: '/'},
29+
{
30+
path: '/',
31+
components: {default: Home, other: component},
32+
props: {default: to => ({waited: to.meta.waitedFor})},
33+
},
34+
{
35+
path: '/always-redirect',
36+
redirect: () => ({
37+
name: 'user',
38+
params: {id: String(Math.round(Math.random() * 100))},
39+
}),
40+
},
41+
42+
43+
{path: encodeURI('/n/€'), name: 'euro', component},
44+
{path: '/n/:n', name: 'increment', component},
45+
{path: '/multiple/:a/:b', name: 'multiple', component},
46+
{path: '/long-:n', name: 'long', component: LongView},
47+
{
48+
path: '/lazy',
49+
meta: {transition: 'slide-left'},
50+
component: async () => {
51+
await delay(500)
52+
return component
53+
},
54+
},
55+
{
56+
path: '/with-guard/:n',
57+
name: 'guarded',
58+
component,
59+
beforeEnter(to) {
60+
if (to.params.n !== 'valid') return false
61+
},
62+
},
63+
64+
65+
66+
67+
{path: '/:data(.*)', component: NotFound, name: 'NotFound'},
68+
69+
70+
{
71+
path: '/admin',
72+
children: [
73+
{path: '', component},
74+
{path: 'dashboard', component},
75+
{path: 'settings', component},
76+
],
77+
},
78+
],
79+
async scrollBehavior(to, from, savedPosition) {
80+
await scrollWaiter.wait()
81+
if (savedPosition) {
82+
return savedPosition
83+
} else {
84+
if (to.matched.every((record, i) => from.matched[i] !== record))
85+
return {left: 0, top: 0}
86+
}
87+
// leave scroll as it is by not returning anything
88+
// https://github.com/Microsoft/TypeScript/issues/18319
89+
return false
90+
},
91+
})
92+
93+
// router.push({ name: 'user', params: {} })
94+
95+
const delay = (t: number) => new Promise(resolve => setTimeout(resolve, t))
96+
97+
// remove trailing slashes
98+
router.beforeEach(to => {
99+
if (/.\/$/.test(to.path)) {
100+
to.meta.redirectCode = 301
101+
return to.path.replace(/\/$/, '')
102+
}
103+
})
104+
105+
router.beforeEach(async to => {
106+
// console.log(`Guard from ${from.fullPath} to ${to.fullPath}`)
107+
if (to.params.id === 'no-name') return false
108+
109+
const time = Number(to.query.delay)
110+
if (time > 0) {
111+
console.log('⏳ waiting ' + time + 'ms')
112+
to.meta.waitedFor = time
113+
await delay(time)
114+
}
115+
})
116+
117+
router.beforeEach(() => {
118+
if (globalState.cancelNextNavigation) return false
119+
})
120+
121+
router.afterEach((to, from) => {
122+
if (to.name === from.name && to.name === 'repeat') {
123+
const toDepth = to.path.split('/').length
124+
const fromDepth = from.path.split('/').length
125+
to.meta.transition = toDepth < fromDepth ? 'slide-right' : 'slide-left'
126+
}
127+
})
128+
129+
router.afterEach((to, from) => {
130+
// console.log(
131+
// `After guard: from ${from.fullPath} to ${
132+
// to.fullPath
133+
// } | location = ${location.href.replace(location.origin, '')}`
134+
// )
135+
})
136+
137+
export function go(delta: number) {
138+
return new Promise((resolve, reject) => {
139+
function popStateListener() {
140+
clearTimeout(timeout)
141+
}
142+
143+
window.addEventListener('popstate', popStateListener)
144+
145+
function clearHooks() {
146+
removeAfterEach()
147+
removeOnError()
148+
window.removeEventListener('popstate', popStateListener)
149+
}
150+
151+
// if the popstate event is not called, consider this a failure
152+
const timeout = setTimeout(() => {
153+
clearHooks()
154+
reject(new Error('Failed to use router.go()'))
155+
// using 0 leads to false positives
156+
}, 1)
157+
158+
const removeAfterEach = router.afterEach((_to, _from, failure) => {
159+
clearHooks()
160+
resolve(failure)
161+
})
162+
const removeOnError = router.onError(err => {
163+
clearHooks()
164+
reject(err)
165+
})
166+
167+
router.go(delta)
168+
})
169+
}
170+
171+
// @ts-expect-error
172+
window._go = go
173+
174+
router.beforeEach(to => {
175+
// console.log('second guard')
176+
if (typeof to.query.to === 'string' && to.query.to) return to.query.to
177+
})
178+
179+
const dirLog = {
180+
'': '?',
181+
back: '⏪',
182+
forward: '⏩',
183+
}
184+
routerHistory.listen((to, from, info) => {
185+
console.log(`${dirLog[info.direction]} as a ${info.type}`)
186+
})
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class ScrollQueue {
2+
private resolve: ((value?: any) => void) | null = null
3+
private promise: Promise<any> | null = null
4+
5+
add() {
6+
this.promise = new Promise(resolve => {
7+
this.resolve = resolve
8+
})
9+
}
10+
11+
flush() {
12+
this.resolve && this.resolve()
13+
this.resolve = null
14+
this.promise = null
15+
}
16+
17+
async wait() {
18+
await this.promise
19+
}
20+
}
21+
22+
export const scrollWaiter = new ScrollQueue()

crates/rs-tauri-vue/src/store.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { reactive } from 'vue'
2+
3+
export const globalState = reactive({
4+
cancelNextNavigation: false,
5+
})
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<template>
2+
<section>
3+
<h1>Generic view</h1>
4+
<pre>{{ $route.fullPath }}</pre>
5+
</section>
6+
</template>
7+
8+
<script>
9+
import { defineComponent } from 'vue'
10+
11+
export default defineComponent({
12+
name: 'Generic',
13+
})
14+
</script>
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<template>
2+
<div>
3+
<div>Home</div>
4+
<p>My Data is: {{ someData }}</p>
5+
<p v-if="waited != null">I waited for {{ waited }}</p>
6+
toggle: {{ log(toggle) }}
7+
<button @click="counter++">{{ counter }}</button>
8+
</div>
9+
</template>
10+
11+
<script>
12+
import { defineComponent, getCurrentInstance, ref } from 'vue'
13+
14+
export default defineComponent({
15+
name: 'Home',
16+
props: ['waited'],
17+
data: () => ({
18+
toggle: false,
19+
counter: 0,
20+
}),
21+
22+
setup() {
23+
const me = getCurrentInstance()
24+
25+
function log(value) {
26+
console.log(value)
27+
return value
28+
}
29+
30+
return {
31+
log,
32+
someData: ref(0),
33+
}
34+
},
35+
36+
_beforeRouteEnter() {
37+
this.toggle = true
38+
},
39+
})
40+
</script>
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<template>
2+
<section>
3+
<div class="long" id="top">
4+
This one is long: {{ route.params.n }}. Go down to click on a link
5+
</div>
6+
<p class="long">
7+
<router-link
8+
:to="{ name: 'long', params: { n: Number(route.params.n || 0) + 1 } }"
9+
>/long-{{ Number(route.params.n || 0) + 1 }}</router-link
10+
>
11+
</p>
12+
<a href="#top">Go to top</a>
13+
</section>
14+
</template>
15+
16+
<script>
17+
import { defineComponent } from 'vue'
18+
import { useRoute } from 'vue-router'
19+
20+
export default defineComponent({
21+
name: 'LongView',
22+
setup() {
23+
const route = useRoute()
24+
return { route }
25+
},
26+
})
27+
</script>
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<template>
2+
<div>Not Found: {{ route.fullPath }}</div>
3+
</template>
4+
5+
<script>
6+
import { defineComponent } from 'vue'
7+
import { useRoute } from 'vue-router'
8+
9+
export default defineComponent({
10+
name: 'NotFound',
11+
setup() {
12+
const route = useRoute()
13+
return { route }
14+
},
15+
})
16+
</script>

0 commit comments

Comments
 (0)