original post: https://www.ycmjason.com/blog/2018/06/14.html
It's almost there! It's almost there!!!!
Few weeks ago I published vue-vs-react
Since the star difference are getting closer and closer (268 stars gap at the moment I am typing this), I decided to add a new feature to my project. Fireworks will explode with a background audio at the moment that Vue out-star React!
You can simply open the website
I am so so so so so excited!
$refs
There isn't many cases of obtaining direct reference to the DOM when using Vue. Most stuff could be easily handled with the power of Vue.
In this project tho, I have an <audio>
which will be triggered to play when vue.stars > react.stars
. In order to do so, I must get the reference to the element and do elem.play()
. The way to get a reference to a DOM in Vue is by adding ref="name"
. So I just simply did the following (see this line
<audio src="..." ref="audio"></audio>
Then this.$refs.audio
will be pointing to that element! Now I could do this.$refs.audio.play()
and this.$refs.audio.pause()
inside the component!!!! (see this line
This make me realise for the first time that $refs
could be useful when you want to access the native apis.
The way that I am currently doing is quite hacky. The proper way would probably look something like:
// Audio.vue
<template>
<audio :src="src" ref="audio"></audio>
</template>
<script>
export default {
props: ['playing'],
watch: {
playing(p) {
if (p) this.$refs.audio.play();
else this.$refs.audio.pause();
// actually I will write: this.$refs.audio[p? 'play': 'pause']();
},
},
}
</script>
With this wrapping Audio component, we don't ever need to use $refs
anywhere else in the codebase! $refs
are low-level stuff and IMO, we should always wrap it around to lift the level of abstractions of the code.
If you have clicked into the website, you might notice the numbers kind of grow towards the number of stars of the repos. This effect is implemented with this TransitioningNumber
The way this component work is that whenever the porps.number
changes, it calculates the animation frames
frames
is simply a list of numbers ranging from the previous props.number
to the current props.number
. Since I have set the FPS
to 22, the corresponding second per frame would be 1 / 22
. To animate this, we can simply change the this.displayNumber
from the first frame to the last frame with a timeout of 1 / 22
seconds between each frame. I am surprised how good can Vue handle this and the result looks really satisfying to me.
I will give an example to illustrate the above implementation. Say we want to show transition from 0
to 1000
within 2
seconds. To achieve 22 FPS, we know that we need 22 * 2 = 44
frames. So we will construct a list, frames
, with 44 frames ranging from from 0 to 1000. It is obvious that each frame would have step = 1000 / 44 = 22.7272727 ~= 23
. Then we construct the list frames = [0, 23, 46, 68, ..., 1000]
. Then we set this.displayNumber
to each frame with a timeout of 1 / 22
seconds between each frame.
This approach is more of an experiment and does look very naive. I would really appreciate if you could suggest a better approach. Please comment below!
In this project I used firebase
Firestore
Please refer to these two files (1
// services/repoSnapshots.js (expanded)
import firebase from 'firebase';
export default {
subscribe: (fn) => firebase.firestore()
.collection('repo-snapshots')
.orderBy("timestamp", "desc")
.limit(20)
.onSnapshot(snapshot => fn(snapshot.docs.map(d => d.data()))),
}
// App.vue (<script>)
import repoSnapshots from './services/repoSnapshots.js';
export default {
...
data: () => ({
snapshots: [],
}),
created() {
repoSnapshots.subscribe(snapshots => this.snapshots = snapshots);
},
...
}
As you can see, the code is insanely descriptive and easy. Although the documentation is not very complete, it takes some time to dig our the method I want. It is still very simple to use.
Vue-cli 3.0 is absolutely amazing. But I think Parcelsass-loader
/vue-loader
or whatever loader. It just, do it for you! MAGIC!
I hope you are as excited as I am to see Vue out-starring React and enjoyed reading this post. Please feel free to ask me any questions I would definitely answer if I could. Thanks for reading!