vue/benchmarks/uptime/index.html
2019-08-12 10:05:31 +02:00

201 lines
5.1 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Vue benchmark</title>
<style type="text/css">
html, body {
margin: 0;
padding: 0 10px;
font-family: sans-serif;
}
#fps {
position: fixed;
top: 0px;
right: 0px;
padding: 32px;
font-size: 32px;
text-align: right;
}
* {
box-sizing: border-box;
}
.server-uptime {
display: block;
overflow: hidden;
margin: 0 auto;
width: 50%;
}
.server-uptime + .server-uptime {
margin: 20px auto 0 auto;
border-top: 1px solid #999;
}
.days {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.uptime-day {
display: flex;
}
span.uptime-day-status {
width: 10px;
height: 10px;
margin: 1px;
}
.hover {
display: none;
}
.uptime-day-status:hover + .hover {
display: flex;
position: absolute;
margin-top: -35px;
margin-left: -30px;
border-radius: 4px;
color: #eee;
background-color: #333;
padding: 10px;
font-size: 11px;
}
</style>
</head>
<body>
<p>Reference: <a href="https://github.com/tildeio/glimmer/blob/master/packages/glimmer-demos/lib/uptime.ts">Ember Glimmer 2 demo</a></p>
<div id="app">
<p>FPS: {{ fps }}</p>
<button @click="toggle">{{ playing ? 'pause' : 'play' }}</button>
<server-uptime
v-for="server in servers"
:key="server.name"
:name="server.name"
:days="server.days">
</server-uptime>
</div>
<script src="../../dist/vue.min.js"></script>
<script>
// functional components are perfect for small, presentational components
// and they are much more efficient than stateful ones.
Vue.component('uptime-day', {
props: ['day'],
functional: true,
render (h, ctx) {
var day = ctx.props.day
return h('div', { staticClass: 'uptime-day'}, [
h('span', { staticClass: 'uptime-day-status', style: { backgroundColor: day.up ? '#8cc665' : '#ccc' } }),
h('span', { staticClass: 'hover' }, [day.number + ': ' + day.up ? 'Servers operational!' : 'Red alert!'])
])
}
})
Vue.component('server-uptime', {
props: ['name', 'days'],
computed: {
upDays () {
return this.days.reduce(function (upDays, day) {
return upDays += (day.up ? 1 : 0)
}, 0)
},
maxStreak () {
var streak = this.days.reduce(([max, streak], day) => {
if (day.up && streak + 1 > max) {
return [streak + 1, streak + 1]
} else if (day.up) {
return [max, streak + 1]
} else {
return [max, 0]
}
}, [0, 0])
return streak.max
}
},
template: `
<div class="server-uptime">
<h1>{{name}}</h1>
<h2>{{upDays}} Days Up</h2>
<h2>Biggest Streak: {{maxStreak}}</h2>
<div class="days">
<uptime-day
v-for="day in days"
:key="day.number"
:day="day">
</uptime-day>
</div>
</div>
`
})
function generateServer (name) {
var days = []
for (var i=0; i<=364; i++) {
var up = Math.random() > 0.2
days.push({ number: i, up })
}
return { name, days }
}
function generateServers () {
return [
generateServer("Stefan's Server"),
generateServer("Godfrey's Server"),
generateServer("Yehuda's Server")
]
}
var s = window.performance.now()
var app = new Vue({
el: '#app',
data: {
fps: 0,
playing: false,
servers: Object.freeze(generateServers())
},
methods: {
toggle () {
this.playing = !this.playing
if (this.playing) {
update()
} else {
clearTimeout(timeoutId)
}
}
}
})
console.log('initial render: ' + (window.performance.now() - s) + 'ms')
var fpsMeter = {
alpha: 2/121,
lastValue: null,
push (dataPoint) {
if (this.lastValue) {
return this.lastValue = this.lastValue + this.alpha * (dataPoint - this.lastValue)
} else {
return this.lastValue = dataPoint
}
}
}
var timeoutId
var lastFrame = null
function update () {
var thisFrame = window.performance.now()
if (lastFrame) {
app.fps = Math.round(fpsMeter.push(1000 / (thisFrame - lastFrame)))
}
app.servers = Object.freeze(generateServers())
timeoutId = setTimeout(update, 0) // not using rAF because that limits us to 60fps!
lastFrame = thisFrame
}
</script>
</body>
</html>