Skip to content
This repository was archived by the owner on Oct 24, 2023. It is now read-only.

Commit ac57705

Browse files
refactor: migrate to vue composition api (#99)
1 parent 1d7f719 commit ac57705

File tree

16 files changed

+309
-244
lines changed

16 files changed

+309
-244
lines changed

components/Footer.vue

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<div class="flex flex-col lg:flex-row items-center">
55
<div class="text-center leading-loose lg:text-left lg:leading-normal">
66
<span>
7-
&copy; 2015 - {{ $options.currentYear }}
7+
&copy; 2015 - {{ currentYear }}
88
<a
99
href="/"
1010
class="no-underline text-developmint-500 hover:text-developmint-400"
@@ -31,14 +31,14 @@
3131
target="_blank"
3232
rel="noopener"
3333
>
34-
<div>v{{ $options.version }}</div>
34+
<div>v{{ version }}</div>
3535
<GitHubIcon class="block w-4 h-4 ml-1 fill-current" />
3636
</a>
3737
</div>
3838
<div class="py-4 lg:hidden" />
3939
<div class="flex items-center lg:inline">
4040
<NuxtLink
41-
v-for="link in $options.links"
41+
v-for="link in links"
4242
:key="link"
4343
:to="localePath(link)"
4444
no-prefetch
@@ -58,9 +58,13 @@ export default {
5858
components: {
5959
GitHubIcon: () => import('~/assets/img/icons/github.svg')
6060
},
61-
links: ['legal', 'privacy', 'disclaimer'],
62-
version,
63-
currentYear: (new Date()).getFullYear()
61+
setup () {
62+
return {
63+
links: ['legal', 'privacy', 'disclaimer'],
64+
version,
65+
currentYear: (new Date()).getFullYear()
66+
}
67+
}
6468
}
6569
</script>
6670

components/about-us/TeamMember.vue

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,13 @@
5858
</template>
5959

6060
<script>
61-
import logClick from '~/mixins/logClick'
62-
6361
export default {
6462
components: {
6563
GitHubIcon: () => import('~/assets/img/icons/github.svg'),
6664
GlobeIcon: () => import('~/assets/img/icons/team/globe.svg'),
6765
TwitterIcon: () => import('~/assets/img/icons/team/twitter.svg'),
6866
LinkedInIcon: () => import('~/assets/img/icons/team/linkedin.svg')
6967
},
70-
mixins: [logClick],
7168
props: {
7269
slug: {
7370
type: String,
@@ -81,6 +78,17 @@ export default {
8178
type: Object,
8279
default: () => ({})
8380
}
81+
},
82+
setup ({ name }, context) {
83+
const logClick = (eventName) => {
84+
context.root.$ga.event({
85+
eventCategory: 'click',
86+
eventAction: `${name} - ${eventName}`
87+
})
88+
}
89+
return {
90+
logClick
91+
}
8492
}
8593
}
8694
</script>

components/work/AnimatedNumber.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { tween } from 'shifty/src/tweenable'
2+
import { ref, watch, createElement as h } from '@vue/composition-api'
3+
4+
export default {
5+
props: {
6+
from: {
7+
type: Number,
8+
default: 0
9+
},
10+
to: {
11+
type: Number,
12+
required: true
13+
},
14+
duration: {
15+
type: Number,
16+
required: true,
17+
validator: value => value > 0
18+
},
19+
easing: {
20+
type: String,
21+
default: 'easeOutQuad'
22+
},
23+
precision: {
24+
type: Number,
25+
default: 3
26+
},
27+
shouldStart: {
28+
type: Boolean,
29+
required: true
30+
}
31+
},
32+
setup (props) {
33+
const number = ref('0')
34+
const isRunning = ref(false)
35+
const updateNumber = (tweenState) => {
36+
number.value = Number(tweenState.x).toFixed(props.precision).toLocaleString()
37+
}
38+
39+
const startAnimation = async () => {
40+
if (isRunning.value) {
41+
return
42+
}
43+
44+
isRunning.value = true
45+
46+
const options = {
47+
from: { x: props.from, y: 0 },
48+
to: { x: props.to, y: 0 },
49+
duration: props.duration,
50+
easing: props.easing,
51+
step: updateNumber
52+
}
53+
54+
await tween(options)
55+
56+
number.value = Number(number.value).toLocaleString()
57+
isRunning.value = false
58+
}
59+
60+
watch(() => props.shouldStart,
61+
() => {
62+
if (!props.shouldStart) {
63+
return
64+
}
65+
startAnimation()
66+
})
67+
68+
return () => h('span', number.value)
69+
}
70+
}

components/work/AnimatedNumber.vue

Lines changed: 0 additions & 78 deletions
This file was deleted.

components/work/WorkPreview.vue

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
class="flex flex-col xl:justify-around md:mx-16 xl:p-16"
99
>
1010
<a
11-
v-bind="bindUrl"
11+
v-bind="boundUrl"
1212
target="_blank"
13-
rel="noopener"
13+
:rel="rel"
1414
class="text-rains-500 flex justify-center group sm:mt-8 lg:my-8 md:w-1/2"
1515
@click="logClick('img')"
1616
>
@@ -28,9 +28,9 @@
2828
</a>
2929
<div class="my-6 xl:px-6 xl:w-1/2">
3030
<a
31-
v-bind="bindUrl"
31+
v-bind="boundUrl"
3232
target="_blank"
33-
rel="noopener"
33+
:rel="rel"
3434
class="block text-rains-500 no-underline mx-6 md:px-6 mt-4 hover:underline transition-all"
3535
@click="logClick('heading')"
3636
><h2 v-t="`work.projects.${slug}.title`" class="text-2xl font-semibold" /></a>
@@ -42,10 +42,9 @@
4242
</template>
4343

4444
<script>
45-
import logClick from '~/mixins/logClick'
45+
import { computed } from '@vue/composition-api'
4646
4747
export default {
48-
mixins: [logClick],
4948
props: {
5049
slug: {
5150
type: String,
@@ -62,18 +61,35 @@ export default {
6261
svg: {
6362
type: [Boolean, Function],
6463
default: false
64+
},
65+
shouldFollow: {
66+
type: Boolean,
67+
default: false
6568
}
6669
},
67-
computed: {
68-
bindUrl () {
69-
// Looks weird, but is needed to disable links if empty url is provided, because no href will be bound then
70-
return this.url.length ? { href: `${this.url}?ref=developmint.de` } : {}
71-
},
72-
imageSources () {
73-
return {
74-
src: require(`~/assets/img/work/${this.slug}.jpg`),
75-
srcset: `${require(`~/assets/img/work/${this.slug}@2x.jpg`)} 2x`
76-
}
70+
setup (props, context) {
71+
const logClick = (eventName) => {
72+
context.root.$ga.event({
73+
eventCategory: 'click',
74+
eventAction: `work preview: ${props.slug} - ${eventName}`
75+
})
76+
}
77+
78+
// Looks weird, but is needed to disable links if empty url is provided, because no href will be bound then
79+
const boundUrl = computed(() => props.url.length ? { href: `${props.url}?ref=developmint.de` } : {})
80+
81+
const rel = computed(() => `noopener${props.shouldFollow ? '' : ' nofollow'}`)
82+
83+
const imageSources = computed(() => ({
84+
src: require(`~/assets/img/work/${props.slug}.jpg`),
85+
srcset: `${require(`~/assets/img/work/${props.slug}@2x.jpg`)} 2x`
86+
}))
87+
88+
return {
89+
logClick,
90+
boundUrl,
91+
imageSources,
92+
rel
7793
}
7894
}
7995
}

compositions/useInterval.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { onMounted, onUnmounted } from '@vue/composition-api'
2+
3+
export const useInterval = (intervalInSeconds, intervalAction) => {
4+
let intervalListener = null
5+
6+
onMounted(() => {
7+
intervalListener = setInterval(intervalAction, intervalInSeconds * 1000)
8+
})
9+
10+
onUnmounted(() => {
11+
if (!intervalListener) {
12+
return
13+
}
14+
15+
clearInterval(intervalListener)
16+
})
17+
}

i18n/de.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export default {
184184
title: 'Addism',
185185
shortDescription: 'Addissm ist ein moderner und intuitiver Taschenrechner für den Mac. Seine Hauptfunktion' +
186186
' ist es, dem Nutzer die gesamte Berechnung auf einen Blick zu zeigen. Weiterhin werden verschiedene' +
187-
' Exportfunktionalitäten und ein Nachtmodus geboten'
187+
' Exportfunktionalitäten und ein Nachtmodus geboten.'
188188
},
189189
itexia: {
190190
title: 'Itexia',

i18n/en.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ export default {
180180
addism: {
181181
title: 'Addism',
182182
shortDescription: 'A beautiful, structured and modern calculator for macOS with useful features including' +
183-
' the opportunity to export the calculation history in several ways, global shortcuts and a night mode'
183+
' the opportunity to export the calculation history in several ways, global shortcuts and a night mode.'
184184
},
185185
itexia: {
186186
title: 'Itexia',
@@ -192,14 +192,14 @@ export default {
192192
title: 'Hochschulinitiative Deutschland',
193193
shortDescription: 'Hochschulinitiative Deutschland is a German platform that provides great offers for' +
194194
' students, including giveaways, seminars, and other goodies. We have created huge parts of the initial' +
195-
' homepage and have developed new features of the platform for quite some time.'
195+
' homepage and have developed new features of the platform for quite some time.'
196196
},
197197
'lichter-io': {
198198
title: 'Lichter.io',
199199
shortDescription: 'The personal website of Alex which is used as CV and portfolio page. Want to know more' +
200200
' about how the website was created? No problem, the code is <a href="https://github.com/manniL/lichter.io"' +
201201
' target="_blank" rel="noopener" class="text-developmint-500 hover:text-developmint-400 no-underline">open' +
202-
' source</a>'
202+
' source</a>.'
203203
},
204204
'nuxt': {
205205
title: 'Nuxt.js',

mixins/logClick.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

nuxt.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ export default {
129129
* Nuxt plugins
130130
*/
131131
plugins: [
132+
'~/plugins/composition-api',
132133
'~/plugins/vue-prototype-extensions',
133134
'~/plugins/vue-scroll-directive.client',
134135
'~/plugins/vue-observe-visibility-directive.client'

0 commit comments

Comments
 (0)